整理一下 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<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);
}
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 项目中常用到的工具类库(
飞机票
),会一直持续更新,希望能给大家带来一些便利。