Retrofit 2:自定义拦截器的自定义注释

时间:2017-12-11 20:26:33

标签: android retrofit2 interceptor okhttp3

我有自定义拦截器进行身份验证:

@Named("authInterceptor")
    @Provides
    @Singleton
    fun providesAuthInterceptor(preferencesManager: PreferencesManager): Interceptor {
        return Interceptor { chain ->
            val newBuilder = chain.request().newBuilder()
            newBuilder.addHeader("access-token", preferencesManager.getAccessToken())
            val request = newBuilder.build()
            return@Interceptor chain.proceed(request)
        }
    }

但我有一些不需要auth标头的电话。

我希望在我的服务中拥有:

interface NetService {
    @NEEDAUTH
    @GET("users")
    fun getAllShops(key: String): Single<SomeResponse>

    @FormUrlEncoded
    @POST("users")
    fun register(@Field("nickname") nickname: String): Single<SomeResponse>
}

因此,第一个调用将使用authInterceptor,第二个调用将不使用它。

4 个答案:

答案 0 :(得分:5)

从Retrofit 2.6.0版本开始,您可以使用如下标记字段在OkHttp Interceptor中获取批注:

response.request.tag(Invocation::class.java)?.method()?.getAnnotation(YourAnnotation::class.java)

然后在拦截器中,您可以验证请求是否带有注释。

改造变更日志:

新功能:@Tag参数注释,用于在基础OkHttp Request对象上设置标签。可以在CallAdapters或OkHttp拦截器中读取这些内容,以进行跟踪,分析,各种行为等。

https://github.com/square/retrofit/pull/2899/files

答案 1 :(得分:2)

我有类似的要求,我找到的是注释可以在Converter.Factory:requestBodyConverter()中阅读,  Converter.Factory:responseBodyConverter()CallAdapter.Factory.get()

我还发现有两篇文章作为每种方式的实施示例。

  1. 使用转换器:Auto Caching with Retrofit
  2.   

    我们将使用Retrofit提供的gson转换器(GsonConverterFactory)并稍微修改它以在GsonResponseBodyConverter.class中包含一个侦听器来处理http响应解析。

    GsonCacheableConverter中,它会覆盖responseBodyConverter()以保留使用@Cacheable标记的回复。

    1. 使用CallAdapter:Custom Annotations with Retrofit 2
    2.   

      我们在CallAdapter.Factory中读取了注释,当在CallAdapter中创建请求时,我们将在某个地图中存储此类请求的一些信息,以便稍后在某些拦截器中识别它。

      它使用自定义CallAdapter来获取注释@Authenticated,并将数据放入地图中,以后会在拦截器中进行解析。

      我认为requestBodyConverter()CallAdapter更接近您的要求。

      虽然如果你不坚持自定义注释,我认为现在最简单的方法是在api界面添加自定义标头,然后在拦截器中读取并删除它。

      即,将@Headers("needauth: 1")添加到您的服务中,然后使用chain.request().header("needauth")获取该值。

      示例:Sneaking Data into an OkHttp Interceptor

答案 2 :(得分:0)

InterceptorOkHttp中存在的概念,Retrofit对它们一无所知。

您需要做的是拥有两个OkHttp个客户,其各自的实例为Retrofit

  • 一个带有身份验证标题
  • 其余的一个

是否需要身份验证标头将决定要注入哪个实例。

答案 3 :(得分:0)

基于Max Cruz answer。确实尝试在此处发表评论,但它看起来太难看了,因为不知道如何制作多行。

我正在用作扩展功能:

fun <T : Annotation> Request.getCustomAnnotation(annotationClass: Class<T>): T? = this.tag(Invocation::class.java)?.method()?.getAnnotation(annotationClass)

然后您可以像这样使用

request.getCustomAnnotation(YourAnnotation::class.java)