之前原理解析中说到,okHttp3使用了责任链模式添加了很多的拦截器,比如重试拦截器、请求头拦截器等等。有了这些拦截器,就可以把网络请求的不同部分交给各自拦截器实现,然后将拦截器处理的结果拼接成一个完整的请求实体,交给服务器。
一、拦截器接口 Interceptor2
为子链提供拦截方法intercept(),为管理类提供request()和response()方法。
二、责任链管理类 ChainManager2
实现了Chain接口,默认index为0,从第一个拦截器开始。
重写的两个方法如下:
注意这里的reques2是不断发生变化的,比如第一个拦截器处理完将信息放到request中,下一个拦截器也会更新它。最终所有的拦截器处理完成后,这里的request就保存了完整的请求信息。调用interceptor.intercept(next)后,就会触发第index个拦截器。
三、重试拦截器 RetryAndFollowUpInterceptor2
第一个拦截器,主要负责网络请求重试的。重试次数可以自定义。如果拿到请求结果就返回给调用者ChainManager2的response()方法返回。其中在chain.response()的时候,会调用下一个拦截器
四、请求头拦截器 BridgeInterceptor2
是不是看到这样,有点莫名其妙。其实完整的http或https请求就是通过拼接的形式,形成一条完整的请求字符串的。这里先分析下Get请求与Post请求的区别:
1、Get请求
(1)请求行
(2)请求属性集
2、Post请求
(1)请求行
(2)请求属性集
(3)请求体的长度
(4)请求的类型
**因此,代码中加入了POST请求的判断,针对该请求必须要加上请求体的长度和请求类型。**完成了请求头拦截器的处理,下一步交给服务器请求拦截器处理。
五、服务器请求拦截器 ConnectInterceptor2
这一块分为2个部分:
- 请求体的拼接
- 请求结果的解析
1、请求体的拼接
通过ParseSocket这个类,调用getAllHeader()方法,返回所有的拼接字符串。
2、getAllHeader()方法
/**
* 拼接所有的请求头部分
*
* @param request2
* @return
*/
public String getAllHeader(Request2 request2) {
// TODO 获取当前请求的地址 /v3/weather/weatherInfo?city=110101&key=13cb58f5884f9749287abbead9c658f2
String file = null;
try {
URL url = new URL(request2.getUrl2());
file = url.getFile();
} catch (MalformedURLException e) {
e.printStackTrace();
}
StringBuffer sb = new StringBuffer();
/**
* TODO 拼接:
* POST /v3/weather/weatherInfo?city=110101&key=13cb58f5884f9749287abbead9c658f2 HTTP/1.1
*/
sb.append(request2.getMethod())
.append(SPACE)
.append(file)
.append(SPACE)
.append(HTTP_VERSION)
.append(BREAK);
/**
* TODO 拼接:
* Content-Length: 0
* Host: restapi.amap.com
* Content-Type: application/json
*/
Map<String, String> headerList = request2.getHeaderList();
Set<Map.Entry<String, String>> entries = headerList.entrySet();
for (Map.Entry<String, String> entry : entries) {
sb.append(entry.getKey())
.append(":")
.append(SPACE)
.append(entry.getValue())
.append(BREAK);
}
sb.append(BREAK);
/**
* TODO 拼接:
* post请求拼接请求体:
* city=110101&key=13cb58f5884f9749287abbead9c658f2
*/
if ("POST".equalsIgnoreCase(request2.getMethod())) {
sb.append(request2.getRequestBody2().getBody())
.append(BREAK);
}
return sb.toString();
}
按照服务器标准请求的方式,拼接返回,注意空格和换行也要加上。 标准格式如下:
3、发送请求
(1)连接socket
这里注意,HTTP和HTTPS实例化socket的方式是不同的,处理方式如下:
(2)发送请求
不要忘记调用flush()方法。
4、处理返回结果
首先看一下,服务器完整的返回信息:
第一行是返回的请求状态,在解析流的时候只要解析到空行,那么下一行一定是返回的结果,这是规范。
六、使用拦截器
默认实现执行第一个重试拦截器,经过拦截器处理会将结果返回到这里。