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

Posted LeBron_Six

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于Retrofit2+Okhttp3实现统一添加请求参数和重定向相关的知识,希望对你有一定的参考价值。

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);

以上是关于关于Retrofit2+Okhttp3实现统一添加请求参数和重定向的主要内容,如果未能解决你的问题,请参考以下文章

OkHttp3 + retrofit2 封装

Android网络实战篇——OkHttp3(Retrofit2)五种缓存模式的实现

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

Android Okhttp3+Retrofit2网络加载效率优化

Android 使用Retrofit2.0+OkHttp3.0实现缓存处理+Cookie持久化第三方库

Retrofit2 OkHttp3 响应正文空错误