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

版权声明:本文为博主原创文章,未经博主允许不得转载。更多文章,请查看 http://blog.csdn.net/yyh352091626 https://blog.csdn.net/yyh352091626/article/details/53082350

Android开发中难免会遇到一些比较“不友好”的服务端接口。比如以前遇到的json数据中,某个字段偶尔为Object,偶尔为List…

最近遇到的一个问题就是:所有请求接口都要增加一个token参数… 并且token参数有可能过期,比如请求某一条接口,如果token失效则在该请求的响应中把新的token带回来,客户端就得用新的token再次发送该请求,类似重定向。

token失效的stateCode为3,新的token在data字段中返回。如下:

{
    "stateCode":3,
    "data":"E78kH6",
    "errorMsg":null
}

庆幸的是,Okhttp提供了强大的拦截器功能,是一种能够监控,重写,重试调用的强大机制。

public class TokenInterceptord implements Interceptor {

     private final String TAG = "respond";

     @Override
     public Response intercept(Chain chain) throws IOException {
         Request oldRequest = chain.request();
         String url = oldRequest.url().toString();
         Response response = null;

         // 新的请求,添加参数
         Request newRequest = addParam(oldRequest);
         response = chain.proceed(newRequest);

         ResponseBody value = response.body();
         byte[] resp = value.bytes();
         String json = new String(resp, "UTF-8");

         // 判断stateCode值
         try {
             JSONObject jsonObject = new JSONObject(json);
             int stateCode = jsonObject.optInt("stateCode");
             if (stateCode == 3) {
                 String data = jsonObject.optString("data");
                 Log.d(TAG, "token失效,新的token:" + data);
                 DataStorageUtils.saveToken(data);
                 // token失效,重新执行请求
                 Request newTokenRequest = addParam(oldRequest);
                 response = chain.proceed(newTokenRequest);
             } else {
                 // 这里值得注意。由于前面value.bytes()把响应流读完并关闭了,所以这里需要重新生成一个response,否则数据就无法正常解析了
                 response = response.newBuilder()
                         .body(ResponseBody.create(null, resp))
                         .build();
             }
         } catch (Exception e) {

         }

         return response;
     }

     /**
      * 添加公共参数
      *
      * @param oldRequest
      * @return
      */
     private Request addParam(Request oldRequest) {

         HttpUrl.Builder builder = oldRequest.url()
                 .newBuilder()
                 .setEncodedQueryParameter("lversion", PackagesUtils.getAppVersionName())
                 .setEncodedQueryParameter("token", DataStorageUtils.getToken());

         Request newRequest = oldRequest.newBuilder()
                 .method(oldRequest.method(), oldRequest.body())
                 .url(builder.build())
                 .build();

         return newRequest;
     }
 }

当然,也可以为请求或响应添加Header。

Request request = oldRequest.newBuilder()
        .header("Content-Encoding", "gzip")
        .build();

Response response = response.newBuilder()
        .header("Content-Encoding", "gzip")
        .build();

然后为OkHttp配置一个拦截器。

public static OkHttpClient getOkHttpClient() {
        Interceptor interceptor = new TokenInterceptor();
        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(30 * 1000, TimeUnit.MILLISECONDS)
                .readTimeout(30 * 1000, TimeUnit.MILLISECONDS)
                .addInterceptor(interceptor)
                .addInterceptor(new HttpLoggingInterceptor(new MyLog()).setLevel(HttpLoggingInterceptor.Level.BODY))
                .build();
        return client;
    }

Retrofit 使用 Okhttp作为client

Retrofit retrofit = new Retrofit.Builder()
    .addConverterFactory(ScalarsConverterFactory.create())
    .addConverterFactory(GsonConverterFactory.create())
    .baseUrl(baseUrl)
    .client(getOkHttpClient())
    .build();

Api api = retrofit.create(Api.class);

猜你喜欢

转载自blog.csdn.net/yyh352091626/article/details/53082350
今日推荐