改造2.0多个拦截器

时间:2017-06-19 21:21:34

标签: java request retrofit okhttp3

我正在进行改造,需要能够使用多个拦截器。目前我正在使用一个自动附加身份验证令牌,但我需要能够在没有身份验证令牌的情况下进行呼叫。如果我在标题中添加另一个没有auth令牌的拦截器,我该如何使用那个而不是auth令牌拦截器。

    val interceptor: Interceptor = Interceptor { chain ->
    val newRequest = chain.request().newBuilder().
            addHeader("Auth_Token", pref.getString(PSPreferences.prefAuthKey, "")).
            cacheControl(CacheControl.FORCE_NETWORK).
            build()
    chain.proceed(newRequest)
}

okHttpClient = OkHttpClient.Builder().
        readTimeout(1, TimeUnit.MINUTES).
        connectTimeout(1, TimeUnit.MINUTES).
        addInterceptor(interceptor).build()

val retrofitInstance = Retrofit.Builder()
        .baseUrl(APIEndpointInterface.BASE_URL)
        .client(okHttpClient)
        .addConverterFactory(GsonConverterFactory.create())
        .build()
apiInterface = retrofitInstance.create<APIEndpointInterface>(APIEndpointInterface::class.java)

1 个答案:

答案 0 :(得分:6)

OkHttpClient维护一个您可以访问的拦截器列表,但它是一个不可修改的集合。

这让我们有三个选择:

  1. 创建两个OkHttpClient实例,并扣除两个Retrofit 实例,一个用于未经身份验证的请求,另一个用于 经过身份验证的请求。

  2. 检查是否应该使用拦截器,例如:在您的身份验证拦截器中,您可以首先检查令牌的首选项中是否存在密钥,如果是,则使用它;如果没有,你只需继续而不修改任何东西。您也可以为未经验证的拦截器执行此操作。我认为这是您案件最简单的解决方案。

  3. 创建一个拦截器,它将维护一个可修改的列表 您可以随意添加和删除的拦截器。你需要 保持对这个拦截器的引用,也许使它成为一个单身人士。

  4. 对于第三种选择,我提供了一个非常简单的例子:

    public class HttpRequestResponseInterceptor implements Interceptor {
    
        public final List<RequestInterceptor> requestInterceptors = new ArrayList<>();
        public final List<ResponseInterceptor> responseInterceptors = new ArrayList<>();
    
        @Override
        public Response intercept(Chain chain) throws IOException {
    
            Request request = chain.request();
    
            for (RequestInterceptor interceptor : requestInterceptors) {
                request = interceptor.intercept(request);
            }
    
            Response response = chain.proceed(request);
    
            for (ResponseInterceptor interceptor : responseInterceptors) {
                response = interceptor.intercept(response);
            }
    
            return response;
        }
    
        public interface RequestInterceptor {
            Request intercept(Request request) throws IOException;
        }
    
        public interface ResponseInterceptor {
            Response intercept(Response response) throws IOException;
        }
    }
    

    在这种情况下,您需要实现自定义接口RequestInterceptorResponseInterceptor

    这些接口的实现示例如下:

    public class ExampleInterceptor implements HttpRequestResponseInterceptor.RequestInterceptor,
     HttpRequestResponseInterceptor.ResponseInterceptor {
    
        @Override
        public Request intercept(Request request) throws IOException {
            return request.newBuilder().addHeader("REQUEST_HEADER", "EXAMPLE").build();
        }
    
        @Override
        public Response intercept(Response response) throws IOException {
            return response.newBuilder().addHeader("RESPONSE_HEADER", "EXAMPLE").build();
        }
    }
    

    然后,您需要将此拦截器添加到我们的主拦截器两次,一次添加到requestInterceptors,一次添加到responseInterceptors(如果它只拦截请求或仅响应,则只添加到其中一个)。 / p>

    这个例子远非完整。此解决方案的好处是它增加了添加和删除拦截器的功能,而无需重新创建OkHttpClient实例。例如,如果要支持重试请求,则需要额外的工作。