OkHttp拦截器使用

在Android上进行网络请求时,经常需要维持登录之后的session和cookie状态。session和cookie是加在HTTP请求的header里的。可以通过从header中获取,进行请求时手动添加登录获取的cookie。

OkHttp提供的拦截器可以添加,删除或替换请求标头。 还可以转换具有一个请求的正文。例如,如果您连接到的Web服务器支持压缩,就可以使用应用程序拦截器添加请求体压缩。

OkHttp Interceptor

square的一张图

OkHttp提供了一个拦截器接口Interceptor和两种添加拦截器的方式:

  • Application Interceptor
  • NetWork Interceptor

两者最大的区别就是在一次网络访问中拦截的次数和拦截到的信息。

Interceptors 调用时序图

@startuml

participant client.interceptors #SpringGreen
participant RetryAndFollowUpInterceptor
participant BridgeInterceptor
participant CacheInterceptor
participant ConnectInterceptor
participant client.networkInterceptors #SpringGreen
participant CallServerInterceptor

client.interceptors -> RetryAndFollowUpInterceptor
activate client.interceptors
activate RetryAndFollowUpInterceptor

RetryAndFollowUpInterceptor -> BridgeInterceptor
activate BridgeInterceptor

BridgeInterceptor -> CacheInterceptor
activate CacheInterceptor

CacheInterceptor -> ConnectInterceptor
activate ConnectInterceptor

ConnectInterceptor -> client.networkInterceptors
activate client.networkInterceptors

client.networkInterceptors -> CallServerInterceptor
activate CallServerInterceptor

CallServerInterceptor --> client.networkInterceptors
deactivate CallServerInterceptor

client.networkInterceptors --> ConnectInterceptor
deactivate client.networkInterceptors

ConnectInterceptor --> CacheInterceptor
deactivate ConnectInterceptor

CacheInterceptor --> BridgeInterceptor
deactivate CacheInterceptor

BridgeInterceptor --> RetryAndFollowUpInterceptor
deactivate BridgeInterceptor

RetryAndFollowUpInterceptor --> client.interceptors
deactivate RetryAndFollowUpInterceptor
deactivate client.interceptors

@enduml

Application Interceptor

  • 不必担心中间响应,如重定向和重试。
  • 总是调用一次,即使是从缓存中提供的HTTP响应。
  • 遵守应用程序的原始意图。OkHttp注入的标题,如If-None-Match,不会生效。
  • 允许短路,不调用Chain.proceed()。
  • 允许重试并多次调用Chain.proceed()。

NetWork Interceptor

  • 能够对重定向和重试等中间响应进行操作。
  • 对于缓存网络短路的响应不被调用。
  • 观察数据,就像通过网络传输一样。
  • 访问携带请求的连接。

使用拦截器自动储存和添加cookie

OkHttp 有提供 CookieJar 辅助存储 cookie

OkHttp提供了Interceptors拦截器可以很方便的实现类似cookie本地化维持的操作。

private class AddCookiesInterceptor implements Interceptor {

    @Override
    public Response intercept(@NonNull Chain chain) throws IOException {
        //get cached cookie from local
        HashSet<String> cookies = (HashSet<String>) SharedPrefsUtils
                .getStringSetPreference(
                        AccessApplication.getGlobalContext(),
                        C.SP_COOKIE);
        //add cached cookie into request
        Request.Builder builder = chain.request().newBuilder();
        if (cookies != null) {
            for (String cookie : cookies) {
                builder.addHeader("Cookie", cookie);
            }
        }
        Request request = builder.build();
        //get response
        Response response = chain.proceed(request);
        //save response cookie to local cache
        List<String> newCookies = response.headers("Set-Cookie");
        if (!newCookies.isEmpty()) {
            HashSet<String> cookie = new HashSet<>();
            for (String header : newCookies) {
                cookie.add(header);
            }
            SharedPrefsUtils.setStringSetPreference(
                    AccessApplication.getGlobalContext(),
                    C.SP_COOKIE, cookie);
        }
        return response;
    }
}