栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 移动开发 > Android

详解Retrofit Interceptor(拦截器) 拦截请求并做相关处理

Android 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

详解Retrofit Interceptor(拦截器) 拦截请求并做相关处理

本文介绍Retrofit拦截器(Interceptor)的使用方法及相关注意事项。如果本文对您有所帮助,烦请点亮小红心~

首先看一下Interceptor源码:



public interface Interceptor {
  Response intercept(Chain chain) throws IOException;

  interface Chain {
    Request request();

    Response proceed(Request request) throws IOException;

    
    @Nullable Connection connection();
  }
}

先看一下api描述,翻译过来其实就是可以通过拦截器拦截即将发出的请求及对响应结果做相应处理,典型的处理方式是修改header。其实我们可能不仅要处理header,有时也需要添加统一参数,都可以在拦截器内部完成。

看一下Interceptor接口,只有intercept(Chain chain)方法,其返回值是Response,顾名思义,是响应数据,我们要做的也就是重写该方法以达到我们的目的。intercept(Chain chain)方法中有个Chain参数,Chain是Interceptor接口内部中定义的另一个接口,我们暂且不管Retrofit内部是如何实现该接口的(这部分内容将会在新的文章中统一讲解),现在只需要知道调用其request()方法可以拿到Request,调用其proceed(Request request)方法可以得到相应数据即可。

到此为止,Interceptor基本用法已经知晓,下面上示例代码:

public class CommonInterceptor implements Interceptor {

  private static Map commonParams;

  public synchronized static void setCommonParam(Map commonParams) {
    if (commonParams != null) {
      if (CommonInterceptor.commonParams != null) {
 CommonInterceptor.commonParams.clear();
      } else {
 CommonInterceptor.commonParams = new HashMap<>();
      }
      for (String paramKey : commonParams.keySet()) {
 CommonInterceptor.commonParams.put(paramKey, commonParams.get(paramKey));
      }
    }
  }

  public synchronized static void updateOrInsertCommonParam(@NonNull String paramKey, @NonNull String paramValue) {
    if (commonParams == null) {
      commonParams = new HashMap<>();
    }
    commonParams.put(paramKey, paramValue);
  }

  @Override
  public synchronized Response intercept(Chain chain) throws IOException {
    Request request = rebuildRequest(chain.request());
    Response response = chain.proceed(request);
    // 输出返回结果
    try {
      Charset charset;
      charset = Charset.forName("UTF-8");
      ResponseBody responseBody = response.peekBody(Long.MAX_VALUE);
      Reader jsonReader = new InputStreamReader(responseBody.byteStream(), charset);
      BufferedReader reader = new BufferedReader(jsonReader);
      StringBuilder sbJson = new StringBuilder();
      String line = reader.readLine();
      do {
 sbJson.append(line);
 line = reader.readLine();
      } while (line != null);
      LogUtil.e("response: " + sbJson.toString());
    } catch (Exception e) {
      e.printStackTrace();
      LogUtil.e(e.getMessage(), e);
    }
//    savecookies(response, request.url().toString());
    return response;
  }


  public static byte[] toByteArray(RequestBody body) throws IOException {
    Buffer buffer = new Buffer();
    body.writeTo(buffer);
    InputStream inputStream = buffer.inputStream();
    ByteArrayOutputStream output = new ByteArrayOutputStream();
    byte[] bufferWrite = new byte[4096];
    int n;
    while (-1 != (n = inputStream.read(bufferWrite))) {
      output.write(bufferWrite, 0, n);
    }
    return output.toByteArray();
  }

  private Request rebuildRequest(Request request) throws IOException {
    Request newRequest;
    if ("POST".equals(request.method())) {
      newRequest = rebuildPostRequest(request);
    } else if ("GET".equals(request.method())) {
      newRequest = rebuildGetRequest(request);
    } else {
      newRequest = request;
    }
    LogUtil.e("requestUrl: " + newRequest.url().toString());
    return newRequest;
  }

  
  private Request rebuildPostRequest(Request request) {
//    if (commonParams == null || commonParams.size() == 0) {
//      return request;
//    }
    Map signParams = new HashMap<>(); // 假设你的项目需要对参数进行签名
    RequestBody originalRequestBody = request.body();
    assert originalRequestBody != null;
    RequestBody newRequestBody;
    if (originalRequestBody instanceof FormBody) { // 传统表单
      FormBody.Builder builder = new FormBody.Builder();
      FormBody requestBody = (FormBody) request.body();
      int fieldSize = requestBody == null ? 0 : requestBody.size();
      for (int i = 0; i < fieldSize; i++) {
 builder.add(requestBody.name(i), requestBody.value(i));
 signParams.put(requestBody.name(i), requestBody.value(i));
      }
      if (commonParams != null && commonParams.size() > 0) {
 signParams.putAll(commonParams);
 for (String paramKey : commonParams.keySet()) {
   builder.add(paramKey, commonParams.get(paramKey));
 }
      }
      // ToDo 此处可对参数做签名处理 signParams
      
      newRequestBody = builder.build();
    } else if (originalRequestBody instanceof MultipartBody) { // 文件
      MultipartBody requestBody = (MultipartBody) request.body();
      MultipartBody.Builder multipartBodybuilder = new MultipartBody.Builder();
      if (requestBody != null) {
 for (int i = 0; i < requestBody.size(); i++) {
   MultipartBody.Part part = requestBody.part(i);
   multipartBodybuilder.addPart(part);

   

   

   

   MediaType mediaType = part.body().contentType();
   if (mediaType == null) {
     String normalParamKey;
     String normalParamValue;
     try {
normalParamValue = getParamContent(requestBody.part(i).body());
Headers headers = part.headers();
if (!TextUtils.isEmpty(normalParamValue) && headers != null) {
  for (String name : headers.names()) {
    String headerContent = headers.get(name);
    if (!TextUtils.isEmpty(headerContent)) {
      String[] normalParamKeyContainer = headerContent.split("name="");
      if (normalParamKeyContainer.length == 2) {
 normalParamKey = normalParamKeyContainer[1].split(""")[0];
 signParams.put(normalParamKey, normalParamValue);
 break;
      }
    }
  }
}
     } catch (Exception e) {
e.printStackTrace();
     }
   }
 }
      }
      if (commonParams != null && commonParams.size() > 0) {
 signParams.putAll(commonParams);
 for (String paramKey : commonParams.keySet()) {
   // 两种方式添加公共参数
   // method 1
   multipartBodybuilder.addFormDataPart(paramKey, commonParams.get(paramKey));
   // method 2
//   MultipartBody.Part part = MultipartBody.Part.createFormData(paramKey, commonParams.get(paramKey));
//   multipartBodybuilder.addPart(part);
 }
      }
      // ToDo 此处可对参数做签名处理 signParams
      
      newRequestBody = multipartBodybuilder.build();
    } else {
      try {
 JSonObject jsonObject;
 if (originalRequestBody.contentLength() == 0) {
   jsonObject = new JSonObject();
 } else {
   jsonObject = new JSonObject(getParamContent(originalRequestBody));
 }
 if (commonParams != null && commonParams.size() > 0) {
   for (String commonParamKey : commonParams.keySet()) {
     jsonObject.put(commonParamKey, commonParams.get(commonParamKey));
   }
 }
 // ToDo 此处可对参数做签名处理
 
 newRequestBody = RequestBody.create(originalRequestBody.contentType(), jsonObject.toString());
 LogUtil.e(getParamContent(newRequestBody));

      } catch (Exception e) {
 newRequestBody = originalRequestBody;
 e.printStackTrace();
      }
    }
//    可根据需求添加或修改header,此处制作示意
//    return request.newBuilder()
// .addHeader("header1", "header1")
// .addHeader("header2", "header2")
// .method(request.method(), newRequestBody)
// .build();
    return request.newBuilder().method(request.method(), newRequestBody).build();
  }

  
  private String getParamContent(RequestBody body) throws IOException {
    Buffer buffer = new Buffer();
    body.writeTo(buffer);
    return buffer.readUtf8();
  }

  
  private Request rebuildGetRequest(Request request) {
    if (commonParams == null || commonParams.size() == 0) {
      return request;
    }
    String url = request.url().toString();
    int separatorIndex = url.lastIndexOf("?");
    StringBuilder sb = new StringBuilder(url);
    if (separatorIndex == -1) {
      sb.append("?");
    }
    for (String commonParamKey : commonParams.keySet()) {
      sb.append("&").append(commonParamKey).append("=").append(commonParams.get(commonParamKey));
    }
    Request.Builder requestBuilder = request.newBuilder();
    return requestBuilder.url(sb.toString()).build();
  }
}

该拦截器示例代码提供了插入公共参数及对添加header功能(该功能在代码中被注释掉,如需要,放开即可)。对Request的拦截处理在rebuildRequest(Request request) 方法中完成,该方法只处理了GET与POST请求,内部有较为详尽的注释,较为复杂的是文件传输,有些需要注意的事项也做了尽可能完善的说明;对响应数据的处理,代码示例中只做了结果输出处理,仅仅做个示范。

拦截器部分没有过多需要做说明的地方,比较简单,本文的示例可直接使用。如有疑问,欢迎留言。

后续将抽时间,对Retrofit做流程上的简单梳理,了解各个配置及部分细节实现,比如该文中的Chain实例

完整示例: https://github.com/670832188/TestApp

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持考高分网。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/156362.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号