Okhttp简介
HTTP是现代应用常用的一种交换数据和媒体的网络方式,高效地使用HTTP能让资源加载更快,节省带宽。OkHttp是一个高效的HTTP客户端,它有以下默认特性:
- 支持HTTP/2,允许所有同一个主机地址的请求共享同一个socket连接
- 连接池减少请求延时
- 透明的GZIP压缩减少响应数据的大小
- 缓存响应内容,避免一些完全重复的请求
当网络出现问题的时候OkHttp依然坚守自己的职责,它会自动恢复一般的连接问题,如果你的服务有多个IP地址,当第一个IP请求失败时,OkHttp会交替尝试你配置的其他IP,OkHttp使用现代TLS技术(SNI, ALPN)初始化新的连接,当握手失败时会回退到TLS 1.0。
pom依赖:
<!-- https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp --> <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>4.7.2</version> </dependency>
Okhttp使用
本文使用的OkHttp版本为4.7.2。OkHttp的核心类主要有OkHttpClient,Dispatcher,Call,Request,Response,Interceptor,Chain。其中OkHttpClient是负责管理多个Call的组织者,而每个Call又包含一个Request和Response,并且Call中的回调用于提供响应结果。要完成一次网络请求,我们需要告诉Call需要处理的Request是什么样的,例如它的URL是什么,然后将Call交给OkHttpClient。OkHttpClient仅对本次请求做一些配置,例如指定缓存路径,它会让Dispatcher去决定何时执行Call。而Dispatcher的底层实现就是一个由OkHttp默认实现的线程池,它将最终执行Call中的.run()方法。最后的Interceptor和Chain将用于数据的拦截处理。OkHttp提供两种方式提交网络请求,分别是Call.execute()和Call.enqueue(Callback),前者会阻塞线程,后者加入队列异步执行。通过调用response.body().string()我们可以得到响应的body部分并以String形式返回,但值得注意的是.string()只能调用一次。
创建并配置OkHttpClient
基础配置
/** * OkHttpClient是通过OkHttpClient.Builder来配置参数的。 */ OkHttpClient.Builder builder = new OkHttpClient.Builder(); //设置连接超时 builder.connectTimeout(30, TimeUnit.SECONDS); //设置读超时 builder.readTimeout(30, TimeUnit.SECONDS); //设置写超时 builder.writeTimeout(30, TimeUnit.SECONDS); //是否自动重连 builder.retryOnConnectionFailure(true); //......其他配置 //创建OkHttpClient客户端,一般一个项目可以将OkHttpClient设置成单例 OkHttpClient okHttpClient = builder.build();
其他配置
//从调用call.execute();和enqueue();这两个方法开始计时,时间到后网络还未请求完成将调用cancel();方法 builder.callTimeout(10, TimeUnit.SECONDS); //只有http2和webSocket中有使用,如果设置了这个值会定时的向服务器发送一个消息来保持长连接 builder.pingInterval(10, TimeUnit.SECONDS);
1、添加拦截器
builder.addInterceptor(new LoggingInterceptor());
LoggingInterceptor.java
import okhttp3.Interceptor; import okhttp3.Request; import okhttp3.Response; import okhttp3.ResponseBody; import java.io.IOException; /** * 请求拦截器 * 打印OKHttp请求日志 */ public class LoggingInterceptor implements Interceptor { @Override public Response intercept(Interceptor.Chain chain) throws IOException { //这个chain里面包含了request和response,所以你要什么都可以从这里拿 Request request = chain.request(); long t1 = System.nanoTime();//请求发起的时间 System.out.println(String.format("发送请求 %s on %s%n%s", request.url(), chain.connection(), request.headers())); Response response = chain.proceed(request); long t2 = System.nanoTime();//收到响应的时间 //这里不能直接使用response.body().string()的方式输出日志 //因为response.body().string()之后,response中的流会被关闭,程序会报错,我们需要创建出一 //个新的response给应用层处理 ResponseBody responseBody = response.peekBody(1024 * 1024); System.out.println(String.format("接收响应: [%s] %n返回json:【%s】 %.1fms%n%s", response.request().url(), responseBody.string(), (t2 - t1) / 1e6d, response.headers())); return response; } }
2、
发送请求