Okhttp进阶使用

Post请求

json数据提交

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

String post(String url, String json) throws IOException {
     RequestBody body = RequestBody.create(JSON, json);
      Request request = new Request.Builder()
      .url(url)
      .post(body)
      .build();

      Response response = client.newCall(request).execute();
}

FromBody---表单提交

//把参数传进Map中
HashMap<String,String> paramsMap=new HashMap<>();
paramsMap.put("name","哈哈");
paramsMap.put("client","Android");
paramsMap.put("id","3243598");
FormBody.Builder builder = new FormBody.Builder();
for (String key : paramsMap.keySet()) {
      //追加表单信息
      builder.add(key, paramsMap.get(key));
}

OkHttpClient okHttpClient=new OkHttpClient();
RequestBody formBody=builder.build();
Request request=new   Request.Builder().url(netUrl).post(formBody).build();

MultipartBody---文件上传

  • Content-Type - 用于请求头的,固定用:form-data、mixed、alternative、digest、parallel。

  • boundary - 每个字段/文件都被boundary(Content-Type中指定)分成单独的段
  • 每个分段里面包含name,fileName(可空),contentType(可空),body这几个部分
OkHttpClient.Builder builder = new OkHttpClient.Builder();
OkHttpClient okHttpClient = builder.build();

//buidler构造方法可以传递一个string作为boundary
//不传会默认生成UUID作为boundary
MultipartBody.Builder multiBuilder=new MultipartBody.Builder();
//设置请求头的content-type
multiBuilder.setType(MultipartBody.FORM);

File file=new File(Environment.getExternalStorageDirectory(), "balabala.png");
MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");
//第一个参数为分段的content-type类型
RequestBody filebody = RequestBody.create(MEDIA_TYPE_PNG, file);
//这里是 封装上传图片参数。参数分别是name,filename,body
multiBuilder.addFormDataPart("file", file.getName(), filebody);

//这是其他参数,都是无content-type和filename。第二个参数就是body
multiBuilder.addFormDataPart("client", "Android");
multiBuilder.addFormDataPart("uid", "1061");
multiBuilder.addFormDataPart("token", "1911173227afe098143caf4d315a436d");
multiBuilder.addFormDataPart("uuid", "A000005566DA77");

MultipartBody body = multiBuilder.build();
Request request = new Request.Builder()
        .url("http://baidu.com")
        .post(body)
        .build();

Call call = okHttpClient.newCall(request);

Client配置

证书

信任所有的证书

okhttp默认用filter是抓不了包的,测试阶段抓包时需要添加配置:

/**
 * 全部证书信任
 * var allTrustManager = HttpsUtils.AllTrustManager()
 * var createAllTrustSocketFactory = HttpsUtils.createAllTrustSocketFactory(allTrustManager)
 *
 *var build = OkHttpClient.Builder()
 *           .sslSocketFactory(createAllTrustSocketFactory, allTrustManager)
 *           .build()
 * @return
 */
public static SSLSocketFactory createAllTrustSocketFactory(TrustManager manager) {
    SSLSocketFactory ssfFactory = null;
    try {
        SSLContext sc = SSLContext.getInstance("TLS");
        sc.init(null, new TrustManager[]{manager}, new SecureRandom());
        ssfFactory = sc.getSocketFactory();
    } catch (Exception ignored) {
        ignored.printStackTrace();
    }

    return ssfFactory;
}

public static class AllTrustManager implements X509TrustManager {

    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
    }

    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return new X509Certificate[0];
    }
}

支持自签名

项目不是用ca证书,而是自生成的证书

public class CertificateUtils {

    public static void setClientSslSocket(OkHttpClient.Builder builder,String certFileName,String passWord){
        try {
            InputStream open = Utils.getApp().getAssets().open(certFileName);
            X509TrustManager x509TrustManager = trustManagerForCertificates(open, passWord);
            SSLContext tls = SSLContext.getInstance("TLS");
            tls.init(null,new TrustManager[]{x509TrustManager},null);

            SSLSocketFactory socketFactory = tls.getSocketFactory();
            builder.sslSocketFactory(socketFactory);

        } catch (GeneralSecurityException | IOException e) {
            e.printStackTrace();
        }
    }

    /**
     *
     * @param in
     * @param password
     * @return
     * @throws GeneralSecurityException
     */
    public static X509TrustManager trustManagerForCertificates(InputStream in, String password)
            throws GeneralSecurityException {
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        //通过证书工厂得到自签证书对象集合
        Collection<? extends Certificate> certificates = certificateFactory.generateCertificates(in);
        if (certificates.isEmpty()) {
            throw new IllegalArgumentException("expected non-empty set of trusted certificates");
        }
        //为证书设置一个keyStore
        char[] passwordChar = password.toCharArray(); // Any password will work.
        KeyStore keyStore = newEmptyKeyStore(passwordChar);
        int index = 0;
        //将证书放入keystore中
        for (Certificate certificate : certificates) {
            String certificateAlias = Integer.toString(index++);
            keyStore.setCertificateEntry(certificateAlias, certificate);
        }
        // Use it to build an X509 trust manager.
        //使用包含自签证书信息的keyStore去构建一个X509TrustManager
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(
                KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(keyStore, passwordChar);
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
                TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(keyStore);
        TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
        if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
            throw new IllegalStateException("Unexpected default trust managers:"
                    + Arrays.toString(trustManagers));
        }
        return (X509TrustManager) trustManagers[0];
    }

    private static KeyStore newEmptyKeyStore(char[] password) throws GeneralSecurityException {
        try {
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            // By convention, 'null' creates an empty key store.
            keyStore.load(null, password);
            return keyStore;
        } catch (IOException e) {
            throw new AssertionError(e);
        }
    }

}

代理

//代理服务器的IP和端口号
       //优先于proxySelector,设置了proxySelector就会失效
        builder.proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 8080)));
        
        //默认取系统的代理(ProxySelector.getDefault()),防转包可以设置成空
        NullProxySelector nullProxySelector = new NullProxySelector();
        builder.proxySelector(nullProxySelector)
           
        //代理的鉴权账号密码
        final String userName = "";
        final String password = "";
        builder.proxyAuthenticator(new Authenticator() {
            @Override
            public Request authenticate(Route route, Response response) throws IOException {
                //设置代理服务器账号密码
                String credential = Credentials.basic(userName, password);
                return response.request().newBuilder()
                        .header("Proxy-Authorization", credential)
                        .build();
            }
        });

同步异步调度池

Dispatcher dispatcher = new Dispatcher();
        dispatcher.setMaxRequests(64);
        dispatcher.setMaxRequestsPerHost(5);
        //闲置的回调
        dispatcher.setIdleCallback(() -> {
            LogUtils.i("没有在运行的请求");
        });
        
builder .dispatcher(dispatcher)   

协议

List<Protocol> protocols = Util.immutableList(
                Protocol.HTTP_2, Protocol.HTTP_1_1,Protocol.HTTP_1_0);
List<ConnectionSpec> DEFAULT_CONNECTION_SPECS = Util.immutableList(
                ConnectionSpec.MODERN_TLS, ConnectionSpec.CLEARTEXT);
                
//支持的应用层协议,默认支持http2和http1.1
 builder .protocols(protocols)
 //支持的连接协议,主要是tls的协议
 builder.connectionSpecs(DEFAULT_CONNECTION_SPECS) 

连接池

maxIdleConnections - 每个address的最大空闲连接数
keepAliveDurationNs - 空闲连接的保活时间

ConnectionPool connectionPool = new ConnectionPool(5, 60, TimeUnit.SECONDS);
builder.connectionPool(connectionPool);

其他

OkHttpClient.Builder builder = new OkHttpClient.Builder();
        
  builder.addInterceptor()//插在最前面
        //插在ConnectionInterceptor后
        .addNetworkInterceptor()
        //全局事件监听
        .eventListener(new OkHttpListener());
        //TLS域名验证,设为true就可以抓包
        .hostnameVerifier((hostname, session) -> true)
        .connectTimeout(30, TimeUnit.SECONDS)
        .writeTimeout(30, TimeUnit.SECONDS)
        .readTimeout(30, TimeUnit.SECONDS)
        //失败重试,默认ture
        .retryOnConnectionFailure(true)
        //重定向,默认ture
        .followRedirects(true)
        //TLS重定向,默认ture
        .followSslRedirects(true);   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值