`
xuanzhui
  • 浏览: 197014 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

okhttp3同步请求使用总结

阅读更多

官方文档:https://github.com/square/okhttp/wiki/Recipes

https://github.com/square/okhttp

 

以下只考虑小数据量请求,比如请求rest json API

 

 

相关注意点

1. okhttp3比较多的地方使用了builder模式,OkHttpClient、Request、FormBody等都可以通过<Class>.Builder()获取相应的Builder,进而进行相关的配置。

 

2. ResponseBody用完了要及时关闭

Each response body is backed by a limited resource like a socket (live network responses) or an open file (for cached responses). Failing to close the response body will leak these resources and may ultimately cause the application to slow down or crash. Close the response body by calling either close()byteStream().close(), or reader().close(). The bytes() and string() methods both close the response body automatically.

 

 

相关请求代码

首先创建一个自定义的Response(这个个人喜好)

public static class Response {
    public Integer code;
    public String content;
}

 

 

Get请求

/**
 * http get 请求
 * @param url   请求uri
 * @return      Response请求结果实例,通过response.code==200判断是否有效
 */
public static Response httpGet(String url) {

    Response response = new Response();

    OkHttpClient client = new OkHttpClient();

    Request request = new Request.Builder()
            .url(url)
            .build();

    proceedRequest(client, request, response);

    return response;
}

 

 

此处的通用处理请求函数

private static void proceedRequest(OkHttpClient client, Request request, Response response) {
    try {
        okhttp3.Response temp = client.newCall(request).execute();
        response.code = temp.code();
        ResponseBody body = temp.body();
        if (temp.isSuccessful()) {
            //call string auto close body
            response.content = body.string();
        } else {
            response.content = "网络请求失败";
            temp.body().close();
        }
    } catch (IOException e) {
        e.printStackTrace();
        Log.w(TAG, e.getMessage() == null ? " " : e.getMessage());
        response.code = -1;
        response.content = e.getMessage();
    }
}

 

 

Post Json字符串请求

/**
 * http post 请求
 * @param url       请求url
 * @param jsonStr    post参数
 * @return          Response请求结果实例,通过response.code==200判断
 */
public static Response httpPost(String url, String jsonStr) {
    Response response = new Response();

    MediaType JSON = MediaType.parse("application/json; charset=utf-8");
    OkHttpClient client = new OkHttpClient();

    RequestBody body = RequestBody.create(JSON, jsonStr);
    Request request = new Request.Builder()
            .url(url)
            .post(body)
            .build();

    proceedRequest(client, request, response);

    return response;
}

 

 

Post Form请求

/**
 * http post 请求
 * @param url       请求url
 * @param para      post参数,表单键值对
 * @return          HttpResponse请求结果实例
 */
public static Response httpPostForm(String url, Map<String, String> para) {
    if (para == null || para.size() == 0)
        return null;

    Response response = new Response();

    OkHttpClient client = new OkHttpClient();

    FormBody.Builder builder = new FormBody.Builder();

    for (Map.Entry<String, String> entry : para.entrySet()) {
        builder.add(entry.getKey(), entry.getValue());
    }

    RequestBody formBody = builder.build();

    Request request = new Request.Builder()
            .url(url)
            .post(formBody)
            .build();

    proceedRequest(client, request, response);

    return response;
}

 

 

Put Json字符串请求

和post非常类似

/**
 * http put 请求
 * @param url       请求url
 * @param jsonStr    post参数
 * @return          Response请求结果实例,通过response.code==200判断
 */
public static Response httpPut(String url, String jsonStr) {
    Response response = new Response();

    MediaType JSON = MediaType.parse("application/json; charset=utf-8");
    OkHttpClient client = new OkHttpClient();

    RequestBody body = RequestBody.create(JSON, jsonStr);
    Request request = new Request.Builder()
            .url(url)
            .put(body)
            .build();

    proceedRequest(client, request, response);

    return response;
}

 

 

如果Request中需要携带自定义的header信息

Request request = new Request.Builder()
        .url(getPayPalAccessTokenUrl())
        .header("Accept", "application/json")
        .header("Content-Type", "application/x-www-form-urlencoded")
        .header("Authorization", "some secret token")
        .post(body)
        .build();

 

 

如果需要添加自定义的SSL规则

1) 自定义SSL类,比如强制使用TLSv1.2协议

/**
 * XZTLSSocketFactory.java
 * 
 * Created by xuanzhui on 2016/3/18.
 * Copyright (c) 2016 xuanzhui. All rights reserved.
 */
package cn.beecloud;

import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;

public class XZTLSSocketFactory extends SSLSocketFactory {

    private SSLSocketFactory delegate;

    public XZTLSSocketFactory() throws KeyManagementException, NoSuchAlgorithmException {
        SSLContext context = SSLContext.getInstance("TLSv1.2");
        context.init(null, null, null);
        delegate = context.getSocketFactory();
    }

    @Override
    public String[] getDefaultCipherSuites() {
        return delegate.getDefaultCipherSuites();
    }

    @Override
    public String[] getSupportedCipherSuites() {
        return delegate.getSupportedCipherSuites();
    }

    @Override
    public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
        return enableTLSOnSocket(delegate.createSocket(s, host, port, autoClose));
    }

    @Override
    public Socket createSocket(String host, int port) throws IOException {
        return enableTLSOnSocket(delegate.createSocket(host, port));
    }

    @Override
    public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
        return enableTLSOnSocket(delegate.createSocket(host, port, localHost, localPort));
    }

    @Override
    public Socket createSocket(InetAddress host, int port) throws IOException {
        return enableTLSOnSocket(delegate.createSocket(host, port));
    }

    @Override
    public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
        return enableTLSOnSocket(delegate.createSocket(address, port, localAddress, localPort));
    }

    private Socket enableTLSOnSocket(Socket socket) {
        if(socket != null && (socket instanceof SSLSocket)) {
            ((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.2"});
        }
        return socket;
    }
}

 

2) 设置OkHttpClient

OkHttpClient client = new OkHttpClient.Builder()
						//定义连接超时
                    	.connectTimeout(connectTimeout, TimeUnit.MILLISECONDS)
                    	//自定义SSL协议
                    	.sslSocketFactory(new XZTLSSocketFactory()).build();

 

关于android SSL协议的支持列表

Client socket:

Protocol Supported (API Levels) Enabled by default (API Levels)
SSLv3 1+ 1+
TLSv1 1+ 1+
TLSv1.1 16+ 20+
TLSv1.2 16+ 20+


Server socket:

Protocol Supported (API Levels) Enabled by default (API Levels)
SSLv3 1+ 1+
TLSv1 1+ 1+
TLSv1.1 16+ 16+
TLSv1.2 16+ 16+

意味着API level 16+ (Android 4.1, Jelly Bean)是支持TLSv1.2的最低版本要求

ref Android 4.1+ enable TLS 1.1 and TLS 1.2

 

如果遇到错误

java.lang.IllegalStateException: Unable to extract the trust manager on okhttp3.internal.Platform

将成员变量SSLSocketFactory重名为delegate

ref https://github.com/square/okhttp/issues/2323

 

 

 

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics