一、Retrofit与OkHttp的关系
Retrofit是现在最为流行的网络请求框架,那么与OkHttp有什么关系呢?
Retrofit的底层是默认是基于OkHttp,只不过Retrofit帮你封装了请求前与请求后的过程。
那么既然是基于OkHttp,Okhttp是支持对请求头Cookie的封装。
二、结合OkHttp对请求头的思路
在设置请求头的时,使用header(name,value)方法来设置HTTP的头的唯一值。可以通过OkHttp中Interceptor来拦截并重新设置请求头。随后可以结合Retrofit的.client(OkHttpClient)进行对请求头的修改,这是我们的思路。
三、处理
1.实现Interceptor处理请求头,需要处理两次:
- 首次请求cookie为空,需要从响应报文中获取,并保存到客户端的首选项中。
- 非首次请求时,从首选中中取出cookie并添加到请求头中。
首次请求的处理:
/**
* @author : jc.lu
* @create : 17/07/07.
*/
public class ReceivedCookiesInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Response originalResponse = chain.proceed(chain.request());
if (!originalResponse.headers("Set-Cookie").isEmpty()) {
HashSet<String> cookies = new HashSet<>();
for (String header : originalResponse.headers("Set-Cookie")) {
cookies.add(header);
}
SharedPreferences.Editor config = MyApplication.getContext().getSharedPreferences("config", MyApplication.getContext().MODE_PRIVATE)
.edit();
config.putStringSet("cookie", cookies);
config.commit();
}
return originalResponse;
}
}
非首次请求:
/**
* @author : jc.lu
* @create : 17/07/07.
*/
public class AddCookiesInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request.Builder builder = chain.request().newBuilder();
HashSet<String> preferences = (HashSet) MyApplication.getContext().getSharedPreferences("config",
MyApplication.getContext().MODE_PRIVATE).getStringSet("cookie", null);
if (preferences != null) {
for (String cookie : preferences) {
builder.addHeader("Cookie", cookie);
Log.v("OkHttp", "Adding Header: " + cookie); // This is done so I know which headers are being added; this interceptor is used after the normal logging of OkHttp
}
}
return chain.proceed(builder.build());
}
}
2.将拦截器添加到OkHttpClient中
private static OkHttpClient client = new OkHttpClient.Builder()
.addNetworkInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR)
.addInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR)
.addInterceptor(new AddCookiesInterceptor()) //这部分
.addInterceptor(new ReceivedCookiesInterceptor()) //这部分
.cache(cache)
.build();
3.创建retrofit并添加client
mRetrofit = new Retrofit.Builder()
.baseUrl(mBaseUrl)
.addConverterFactory(GsonConverterFactory.create(new GsonBuilder().create()))
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.client(client) //这部分
.build();
由此为止retrofit对cookie持久化的工作都完成了,看看效果。
首次请求:
非首次请求:
有图有真相,可以看出cookie已经被添加到每次请求的请求头上去了。
总结
使用这种方法可以有效解决retrofit请求头对cookie的封装。注意Interceptor拦截器不止是可以添加cookie,可以自定义添加任何属性,当然这是取决于实际需要和后台与客户端的如何处理了。
如果不想使用这种方法添加cookie可以使用这个第三方库,简单到爆炸……
https://github.com/franmontiel/PersistentCookieJar