Cookie保存
Cookie的保存也提供了快捷方式,当然也可以通过拦截器自己实现
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.cookieJar(new CookieJar() {
@Override
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
// 保存cookie通常使用SharedPreferences
}
@Override
public List<Cookie> loadForRequest(HttpUrl url) {
// 从保存位置读取,注意此处不能为空,否则会导致空指针
return new ArrayList<>();
}
})
.build();
Websocket
okhttp3支持websocket,如果不了解请自行搜索,简易推送,轮训都可以使用。websocket协议首先会发起http请求,握手成功后,转换协议保持长连接,类似心跳
// 方法可以选择实现
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.build();
Request request = new Request.Builder()
.url("https://wwww.xxx.com")
.build();
okHttpClient.newWebSocket(request, new WebSocketListener() {
@Override
public void onMessage(WebSocket webSocket, String text) {
super.onMessage(webSocket, text);
// 当收到文本消息
}
@Override
public void onOpen(WebSocket webSocket, Response response) {
super.onOpen(webSocket, response);
// 连接成功
}
@Override
public void onMessage(WebSocket webSocket, ByteString bytes) {
super.onMessage(webSocket, bytes);
// 收到字节消息,可转换为文本
}
@Override
public void onClosed(WebSocket webSocket, int code, String reason) {
super.onClosed(webSocket, code, reason);
// 连接被关闭
}
@Override
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
super.onFailure(webSocket, t, response);
// 连接失败
}
});
拦截器 Intercepter
拦截器是一种强大的机制,可以监视,重写和重试呼叫。这是一个简单的拦截器,用于记录传出的请求和传入的响应。
对chain.proceed(request)的调用是每个拦截器实现的关键部分。这个简单的方法是所有HTTP工作发生的地方,产生一个满足请求的响应。
拦截器可以链接。假设您同时拥有一个压缩拦截器和一个校验和拦截器:您需要确定数据是否被压缩,然后进行校验和,或校验和然后压缩。OkHttp使用列表跟踪拦截器,拦截器按顺序调用。
![img_b7e14d63ed649dd40ec80b14ece8471e.png](https://i-blog.csdnimg.cn/blog_migrate/352884c4af2c2597db8f6a3077cb3f7b.png)
怎么说呢,这拦截器应该就是面向切面了,反正我觉得很像。一般我们在拦截器里进行log打印,便于开发调试吧。正如图上所示,分为应用拦截器和网络拦截器,当然实质就是对拦截到的请求和响应进行处理,应该类似传说中的网络爬虫吧。
简单实例
/**
* Created by Newtrek on 2017/5/7.
*/
public class LoggingInterceptor implements Interceptor {
// 自定义拦截器就实现拦截器接口就行
@Override
public Response intercept(Chain chain) throws IOException {
// 对chain操作,我查看了下字典Chain是链子的意思,我的理解是这个方法体里相当于链子的断点切面吧,
// 切面里啥内容都有,就看我们怎么处理
Request request=chain.request();//获取请求
long t1=System.nanoTime();//开始发送请求的时间
System.out.println("请求信息:发送时间》"+t1+" >>"+chain.connection()+" headers>>"+request.headers());
Response response=chain.proceed(request);
long t2=System.nanoTime();
System.out.println("花费时间:"+(t2-t1)+"响应信息》》");
return response;
}
}
添加应用拦截器
builder.addInterceptor(new LoggingInterceptor());
可以验证
先打印的拦截设置的内容,然后才是正常响应处理结果
添加网络拦截器
builder.addInterceptor(new LoggingInterceptor());
我们可以看到网络拦截器有更多的信息,还有网页有重定向的话,可能会对此调用网络拦截器
应用拦截器和网络拦截器的优点
应用拦截器
- 不必担心中间响应,如重定向和重试
- 总是调用一次,即使从缓存中提供HTTP响应。
- 遵守应用程序的原始意图。不注意OkHttp注入的标题,如If-None-Match。
- 允许短路,不调用Chain.proceed()。
- 允许重试并多次调用Chain.proceed()。
网路拦截器
- 能够对重定向和重试等中间响应进行操作。
- 对于缓存网络短路的响应不被调用。
- 观察数据,就像通过网络传输一样。
- 访问携带请求的连接。
重写请求
拦截器可以添加,删除或替换请求标头。他们还可以转换具有一个请求的正文。例如,如果您连接到已知支持它的Web服务器,则可以使用应用程序拦截器添加请求体压缩。
/** This interceptor compresses the HTTP request body. Many webservers can't handle this! */
final class GzipRequestInterceptor implements Interceptor {
@Override public Response intercept(Interceptor.Chain chain) throws IOException {
Request originalRequest = chain.request();
if (originalRequest.body() == null || originalRequest.header("Content-Encoding") != null) {
return chain.proceed(originalRequest);
}
Request compressedRequest = originalRequest.newBuilder()
.header("Content-Encoding", "gzip")
.method(originalRequest.method(), gzip(originalRequest.body()))
.build();
return chain.proceed(compressedRequest);
}
private RequestBody gzip(final RequestBody body) {
return new RequestBody() {
@Override public MediaType contentType() {
return body.contentType();
}
@Override public long contentLength() {
return -1; // We don't know the compressed length in advance!
}
@Override public void writeTo(BufferedSink sink) throws IOException {
BufferedSink gzipSink = Okio.buffer(new GzipSink(sink));
body.writeTo(gzipSink);
gzipSink.close();
}
};
}
}
重写响应
对称地,拦截器可以重写响应头并转换响应体。这通常比重写请求头更危险,因为它可能违反了网络服务器的期望!
例如,您可以修复服务器配置错误的Cache-Control响应头以实现更好的响应缓存:
/** Dangerous interceptor that rewrites the server's cache-control header. */
private static final Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = new Interceptor() {
@Override public Response intercept(Interceptor.Chain chain) throws IOException {
Response originalResponse = chain.proceed(chain.request());
return originalResponse.newBuilder()
.header("Cache-Control", "max-age=60")
.build();
}
};
可用性
OkHttp的拦截器需要OkHttp2.2或更高。不幸的是,拦截器不能与OkUrlFactory或其上构建的库一起使用,包括Retrofit≤1.8和Picasso≤2.4。
HTTPS
特定安全性与连接性决定由ConnectionSpec实现。 OkHttp包含三个内置的连接规范:
- MODERN_TLS是连接到现代HTTPS服务器的安全配置。
- COMPATIBLE_TLS是连接到安全但不是当前HTTPS服务器的安全配置。
- CLEARTEXT是用于http:// URL的不安全配置。
默认情况下,OkHttp将尝试MODERN_TLS连接,如果现代配置失败,则返回COMPATIBLE_TLS连接。
例:
ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
.tlsVersions(TlsVersion.TLS_1_2)
.cipherSuites(
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256)
.build();
OkHttpClient client = new OkHttpClient.Builder()
.connectionSpecs(Collections.singletonList(spec))
.build();
信任固定
默认情况下,OkHttp信任主机平台的证书颁发机构。这种策略最大限度地提高连接性,但是受到2011年DigiNotar攻击的证书颁发机构攻击。它还假设您的HTTPS服务器的证书由证书颁发机构签署。
client = new OkHttpClient.Builder()
.certificatePinner(new CertificatePinner.Builder()
.add("publicobject.com", "sha256/afwiKY3RxoMmLkuRW1l7QsPZTJPwDS2pdDROQjXw8ig=")
.build())
.build();
自定义受信任的证书
private final OkHttpClient client;
public CustomTrust() {
SSLContext sslContext = sslContextForTrustedCertificates(trustedCertificatesInputStream());
client = new OkHttpClient.Builder()
.sslSocketFactory(sslContext.getSocketFactory())
.build();
}
public void run() throws Exception {
Request request = new Request.Builder()
.url("https://publicobject.com/helloworld.txt")
.build();
Response response = client.newCall(request).execute();
System.out.println(response.body().string());
}
private InputStream trustedCertificatesInputStream() {
... // Full source omitted. See sample.
}
public SSLContext sslContextForTrustedCertificates(InputStream in) {
... // Full source omitted. See sample.
}
Contact GitHub API Training Shop Blog About
© 2017 GitHub, Inc. Terms Privacy
与Okhttp3合作使用
说明都在链接上
https://github.com/square/okhttp/wiki/Works-with-OkHttp
我放几个比较常用的
- Chuck 一个android HTTP客户端 http检查器 star 2k+
- Fresco 一个用于管理图像和他们使用的内存的Android库start 12K+。https://www.fresco-cn.org/docs/using-other-network-layers.html
- Glide Android的图像加载和缓存库专注于平滑滚动 star 15K+
- Moshi json解析库 2.6K+
- Ok2Curl 就是一个拦截器,方便打印日志
- okhttp-digedt okhttp的摘要验证器
- okhttp-signpost 用于签署OkHttp请求的Signpost扩展。
- Oklog 一个方便查看log的库
- PersistentCookieJar 基于SharedPreferences的OkHttp 3的持久CookieJar实现。
- picasso Android的功能强大的图像下载和缓存库 13.3K+
- Retrofit Square and Inc.的Android和Java类型安全HTTP客户端 20.9K+
- Stetho Stetho是Android应用程序的复杂调试桥。启用后,开发人员可以访问Chrome浏览器工具功能,而Chrome浏览器桌面浏览器的本地部分。开发人员还可以选择启用可选的dumpapp工具,该工具为应用程序内部构件提供强大的命令行界面。7.5K+
- wire 用于Android和Java的清洁,轻便的协议缓冲区。