Retrofit2 - 全局检查响应代码

Retrofit2 - check response code globally

我正在使用 Retrofit2 向服务器发出请求。

问题是:有时服务器会 return 为来自用户的每个请求编码 401。如果用户得到这个代码,他应该立即被踢出应用程序(注销并且在重新登录之前不能做任何事情)。

所以对于发送到服务器的每个请求,我想检查服务器是否响应此代码。在所有请求调用中写这个检查并不漂亮,所以我只想写这个检查,每次用户发出请求时它都会执行!

Retrofit(当前版本)需要一个 HTTP 客户端来发出请求。 OkHttp library 由同一位开发人员开发,作为默认客户端与 Retrofit 捆绑在一起。 OkHttp支持添加Interceptor的客户端,可以拦截请求执行。

例如:

import android.util.Log;
import java.io.IOException;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;


public class ErrorInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        // before request
        Request request = chain.request();

        // execute request
        Response response = chain.proceed(request);


        // after request

        // inspect status codes of unsuccessful responses
           switch (response.code()){
               case 401:

                   // do something else
                   Log.e("TEST","Unauthorized error for: " +request.url());

                   // perhaps throw a custom exception ?
                   throw new IOException("Unauthorized !!");
           }

        return response;
    }
}

要使用它,请将它包含在 Retrofit 实例使用的 OkHttpClient 中:

OkHttpClient client = new OkHttpClient.Builder()
            .addInterceptor(new ErrorInterceptor())
            .build();

Retrofit retrofit = new Retrofit.Builder()
            .client(client)
            .baseUrl("/")
            .build();

因此,您可以为每个 "global logic" 或 "cross-cutting concern" 实现一个 Interceptor,然后将它们全部按顺序添加到 Retrofit。

如果您需要检查“401”代码,OkHttp 中有专门的对象:Authenticator (Recipes in OkHttp)。例如:

public class RefreshTokenAuthenticator implements Authenticator {

    @Override
    public Request authenticate(Route route, Response response) throws IOException {
        // You get here, if response code was 401.
        // Then you can somehow change your request or data in your app in this method and resend your request.

        Request request = response.request();

        HttpUrl url = request.url().newBuilder()
            .setQueryParameter("access_token", "new_access_token_may_be")
            .build();

        request = request.newBuilder()
            .url(url)
            .build();

        return request;
    }
}