Retrofit2 Cookie管理-按声明决定是否带Cookie请求接口

原创 2017年01月03日 11:38:24

整理自最近的项目经验,Retrofit关于cookie缓存与使用的文章已经很多了,无论是使用CookieJar还是在OkHttpClient build的时候通过Interceptor设置header,但是在项目中有针对接口决定是否在请求中带cookie的需求,比如获取应用首页数据,推荐商品之类的账户无关接口不需要带cookie,而账户相关接口需要带cookie。

最简单的实现方案是将接口分为需要cookie和不需要cookie两组分别声明,但是这样就限定了接口的声明方式,对于已有的项目改起来会比较麻烦,另一方面降低了声明的自由度,限制了其它方式的声明。是一种比较挫的做法。

对于这个问题,我首先想到的是能不能像Retrofit那样通过注解为接口声明属性,比如写个@UseCookie注解,被这个注解标识的接口在请求时将Cookie设置在Request的Header中。

要实现这个需求需要2点:

1. 解析自定义注解

2. 在解析自定义注解的期间能够编辑请求的Headers

这就需要阅读Retrofit的源码了,有关源码解析可以参考鸿洋大神的文章:

http://blog.csdn.net/lmj623565791/article/details/51304204

通过阅读Retrofit的源码可以知道Retrofit将声明的method转化成具体的Call主要是在ServiceMethod中进行的,如果不想动Retrofit的源码,而是用其对外提供的接口实现Annotation解析的功能,那就只有在ConverterFactory和CallAdapterFactory中动手脚了。

来看一下继承Converter.Factory后所能重写的方法:

public class AConverterFactory extends Converter.Factory {
    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
        return super.responseBodyConverter(type, annotations, retrofit);
    }

    @Override
    public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
        return super.requestBodyConverter(type, parameterAnnotations, methodAnnotations, retrofit);
    }

    @Override
    public Converter<?, String> stringConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
        return super.stringConverter(type, annotations, retrofit);
    }
}
可以看到,真的是已经很接近了,这里已经可以拿到注解进行判断了,可惜的是,方法要求的返回值是RequestBody。没有办法编辑Headers。

如果在项目中Session不是通过Cookie传输而是放在body里面,那么自定义注解在这里就可以用了。


如果说一定要用Cookie来发送Session,那么就得另寻它路。回想在Retrofit2中为请求设置统一Headers的方法是在OkHttpClient中添加Interceptor,在Interceptor中配置Header;而通过Retrofit的Headers注解可以为具体method添加指定Header。那么应该可以在@Headers注解中为某一接口添加一个Key,在Interceptor编辑Headers的时候,如果检测到这个Key,则断定这个请求需要在Header中添加Cookie。

先声明一个常量Key

public class NetConstants {
    public static final String ADD_COOKIE = "Add-Cookie";
    
}
然后在具体接口中通过@Headers注解标识

public interface ClientApi {

    @Headers(NetConstants.ADD_COOKIE)
    @GET("adat/sk/{cityId}.html")
    Call<ResponseBody> getWeather(@Path("cityId") String cityId);
}
在配置Retrofit Builder的时候,在Interceptor中添加判断:

 Interceptor configInterceptor = new Interceptor() {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request.Builder builder = chain.request().newBuilder();

        // add costom headers......

       if (chain.request().headers().get(NetConstants.ADD_COOKIE) != null) { 
            builder.removeHeader(NetConstants.ADD_COOKIE);
            if (!TextUtils.isEmpty(SessionManager.getSession())) { //SessionManager只是一个简易Session管理,就不贴代码了
                builder.header("Set-Cookie", SessionManager.getSession());
            }
        }

        Request request = builder.build();
        if (BuildConfig.DEBUG) {
            Log.d("TAG", "request url : " + request.url());
        }
        return chain.proceed(request);
    }
};
Interceptor responseInterceptor = new Interceptor() {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Response response = chain.proceed(chain.request());
        //存入Session
        if (response.header("Set-Cookie") != null) {
            SessionManager.setSession(response.header("Set-Cookie"));
        }
        //刷新API调用时间
        SessionManager.setLastApiCallTime(System.currentTimeMillis());

        return response;
    }
};
okHttpClientBuilder.addInterceptor(configInterceptor);
okHttpClientBuilder.addInterceptor(responseInterceptor);
mRetrofitBuilder.client(okHttpClientBuilder.build());
这样就可以实现根据具体的接口来决定是否在请求时附带Cookie了,理论上来说最好的解决方案还是自定义注解,但是碍于框架限制,只能使用不是最优雅的办法。

当然,如果与后端商定SessionID在body中附带,那么就完全可以通过自定义注解来解决这个问题了。


版权声明:本文为博主原创文章,未经博主允许不得转载。

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

通过对Retrofit2.0的基础入门和案例实践,掌握了怎么样使用Retrofit访问网络,加入自定义header,包括加入SSL证书,基本的调试基础,但是正常的开发中会涉及cookie同步问题,可以...

Retrofit2添加Cookie

(转载)http://tsuharesu.com/handling-cookies-with-okhttp/ When you are dealing with APIs you always ...

Retrofit+OKHttp 教你怎么持久化管理Cookie

绪论最近小编有点忙啊,项目比较紧,所以一直在忙活项目,继之前的自定义组件之后就没再写博客了,如果你没看到之前的自定义组件你可以看一下: Android自定义下拉刷新动画–仿百度外卖下拉刷新 And...
  • lyhhj
  • lyhhj
  • 2016年05月08日 13:46
  • 25184

Retrofit2.0 OkHttp如何自动加载Cookie 持久化

今天给大家分享Retrofit2.0 OkHttp如何自动加载Cookie; Retrofit,话说Retrofit最近真的很火啊,Retrofit+OKHttp现在似乎已经成为了Android网络请...

Retrofit——Cookie

今天学习了有关http的cookie知识后,刚好想结合retrofit来试验一下学习成果,于是拿了别人的接口来做实验。要想获取cookie,那么肯定有个入口区提供cookie,一般都是在app应用的第...

Retrofit2.0 完美同步Cookie实现免登录

Cookies是一种能够让网站服务器把少量数据储存到客户端的硬盘或内存,或是从客户端的硬盘读取数据的一种技术。Cookies是当你浏览某网站时,由Web服务器置于你硬盘上的一个非常小的文本文件,它可以...

关于Retrofit2+Okhttp3实现统一添加请求参数和重定向

Android开发中难免会遇到一些比较“不友好”的服务端接口。比如以前遇到的json数据中,某个字段偶尔为Object,偶尔为List… 最近遇到的一个问题就是:所有请求接口都要增加一个token参数...

【Android 进阶】Retrofit2 目前最优雅的网络请求框架

身为Geek的我们,面对不断更新换代的技术是不是有点感到迷茫呢?其实只要掌握正确的学习方法,新的技术也就不畏惧了。 福利来了 推荐一位大牛【人称:面哥】呕心沥血的一篇经验分享: 程序员之路-学习...

网络请求--Retrofit2使用方法

欢迎Follow我的GitHub, 关注我的CSDN. Retrofit是Square开发的网络请求库, 简化了网络请求的使用, 这个库太知名了, 好处我就不多说了. 让我们看看如何使用吧? 注...

rxandroid结合retrofit2发送post请求

近日retrofit2正式版发布,终于可以愉快的使用retrofit2了。retrofit2是一个android http通讯框架,内部集成了okhttp。RxJava是一个异步执行框架,采用的是发布...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Retrofit2 Cookie管理-按声明决定是否带Cookie请求接口
举报原因:
原因补充:

(最多只允许输入30个字)