Retrofit 中设置 OkHttp 拦截器,保存和添加 Cookie

整理一下 Retrofit 使用过程中给 OkHttp设置拦截器,并且在请求体中添加用户登录生成的 Cookie 来确认当前用户。

之前设置拦截器一般是用来添加公共的请求头,要求比较单一,只需要加进去就行了。后来,因为项目需要先获取登录 Cookie , 然后再给每一个请求加入 Cookie 信息,这个时候我的写法是这样的:

new OkHttpClient().newBuilder()
.addInterceptor(new Interceptor() {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Response resp = chain.proceed(chain.request());
        List<String> cookies = resp.headers("Set-Cookie");
        String cookieStr = "";
        if (cookies != null && cookies.size() > 0) {
            for (int i = 0; i < cookies.size(); i++) {
                cookieStr += cookies.get(i);
            }
            UserUtil.saveUserCookieId(cookieStr);
        }
        if (LvEmptyUtil.isEmpty(cookieStr)) {
            cookieStr = UserUtil.getCookieId();
            if (LvEmptyUtil.isNotEmpty(cookieStr)) {
                return chain.proceed(chain.request().newBuilder().header("Cookie",cookieStr).build());
            }
        }
        return resp;
    }
})

整体流程是这样的,先获取当前请求的 Cookie , 然后进行本地持久化存储。判断当前是否拿到Cookie, 或者本地是否存有 Cookie , 添加到请求头中,完成操作。
当然,以上写法是一个失败的案例。我这边出现的情况是,一旦进行登录获取了 Cookie 之后,所有的请求都会进行发送两次。
下面来贴出正确的写法:

 /**
     * 初始化 OkHttpClient
     *
     * @return
     */
    private static OkHttpClient getClient() {
        OkHttpClient.Builder client = new OkHttpClient().newBuilder();

        client.interceptors().add(new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
            // 获取 Cookie
                Response resp = chain.proceed(chain.request());
                List cookies = resp.headers("Set-Cookie");
                String cookieStr = "";
                if (cookies != null && cookies.size() > 0) {
                    for (int i = 0; i < cookies.size(); i++) {
                        cookieStr += cookies.get(i);
                    }
                    UserUtil.saveUserCookieId(cookieStr);
                }
                return resp;
            }
        });
        client.interceptors().add(new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
            // 设置 Cookie
                String cookieStr = UserUtil.getCookieId();
                if (LvEmptyUtil.isNotEmpty(cookieStr)) {
                    return chain.proceed(chain.request().newBuilder().header("Cookie", cookieStr).build());
                }
                return chain.proceed(chain.request());
            }
        });
        client.connectTimeout(TIMOUT, TimeUnit.MILLISECONDS);
        client.writeTimeout(TIMOUT, TimeUnit.MILLISECONDS);
        client.readTimeout(TIMOUT, TimeUnit.MILLISECONDS);
        return client.build();
    }

然后在 Retrofit 初始化中加入 client 配置:

new Retrofit.Builder()
.baseUrl(xx)
//xxx配置
.client(getClient())
//xxx配置

这种写法,所有的请求都能正常,也达到目的。如果需要通过拦截器添加请求的公有参数,可以查看 Retrofit 实践整理 或者查阅其他相关介绍资料。

个人归纳

OkHttp 的拦截器中只能进行单一操作,比如,获取Cookie 就只能获取Cookie ,添加 header 就只能添加 header 不能再次进行其他操作。(ps: 有错误的地方还望各位不吝赐教)

参考地址:
Retrofit2.0 ,OkHttp3完美同步持久Cookie实现免登录(二)

顺便也可以看一下楼上博主的另一篇文章
Retrofit 2.0 超能实践(一),okHttp完美支持Https传输

附言

最近开始整理一个自己 Android 项目中常用到的工具类库(飞机票),会一直持续更新,希望能给大家带来一些便利。

你可能感兴趣的:(Android)