博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
OkHttp中Interceptor拦截器之公共参数请求封装
阅读量:7207 次
发布时间:2019-06-29

本文共 6001 字,大约阅读时间需要 20 分钟。

###前言 之前在面试的时候遇到这样的一个问题,那就是如果app中所有的请求都要加入一些参数(例如 版本号、手机号、登录用户名、token等。。。)那么怎么做才能实现,而不至于在每次请求的时候都去进行添加这些请求头。其实这个问题,刚开始我是拒绝的(之前没有遇到过这样的需求)。当时只是想着可以使用okhttp体用的拦截器Interceptor来进行实现,但是具体的实现还是来到了今天。 ###Interceptor说明 在okhttp-wiki里面专门有一篇介绍Interceptor的()里面有这样的一句话

Interceptors are a powerful mechanism that can monitor, rewrite, and retry calls. 拦截器是一种强大的机制,可以监视、重写和重试调用

#####Interceptor几大作用

  • Application Interceptors 应用拦截器
  • Network Interceptors 网络拦截器
  • Choosing between application and network interceptors 在应用和网络拦截器之间做选择
  • Rewriting Requests 重写请求
  • Rewriting Responses 重写响应

具体的作用简介这里不再赘述,这里推荐一篇翻译的文章()

###进入主题 先来看下我们的需求 ####需求约束

  • 1、API Base Url : http://111.111.111.11:8082/xxxxx/xx(类似)

  • 2、客户端请求API的数据格式为json形式:

    {    "publicParams":{},    "key1":value,    "key2":value}复制代码

    其中publicParams为公共参数,每个API接口必须传递

  • 3、公共参数(每次请求都需要携带)

字段 类型 说明
imei string 移动设备身份(非必须)
model 手机型号、设备名称
|    la     |  string       |   系统语言      ||    resolution     |  string       |   分辨率(格式:1920*1080)      ||    densityScaleFactor     |  string       |   密度比例 ||    sdk     |  int       |   SDK版本号 ||    os     |  string       |   系统源代码控制值 |复制代码

###解决方法 我们就是利用Interceptor拦截器,对每次的网络请求进行拦截,然后拿到请求url,并对url进行改造来加入我们需要的公共参数,进行和请求参数的拼接,然后构造request,通过chain.proceed(request)进行改造。 ####第一步

  • 构建一个CommonParamsInterceptor.class类继承自Interceptor
  • 复写intercept(Chain chain)方法,我们需要用到chain.request()来获取到request对象
  • request里面的方法

这里我们只需要用到url()方法(主要获取到api地址和请求参数,并进行改造),用到method()方法来判断get请求和post请求。 这个时候我们看下代码怎么进行编写吧。

@Override    public Response intercept(Chain chain) throws IOException {        //获取到request        Request request = chain.request();        //获取到方法        String method = request.method();        //公共参数hasmap        try {            //添加公共参数            HashMap
commomParamsMap = new HashMap<>(); commomParamsMap.put(Constants.IMEI, DeviceUtils.getIMEI(mContext)); commomParamsMap.put(Constants.MODEL, DeviceUtils.getModel()); commomParamsMap.put(Constants.LANGUAGE, DeviceUtils.getLanguage()); commomParamsMap.put(Constants.os, DeviceUtils.getBuildVersionIncremental()); commomParamsMap.put(Constants.RESOLUTION, DensityUtil.getScreenW(mContext) + "*" + DensityUtil.getScreenH(mContext)); commomParamsMap.put(Constants.SDK, DeviceUtils.getBuildVersionSDK() + ""); commomParamsMap.put(Constants.DENSITY_SCALE_FACTOR, mContext.getResources().getDisplayMetrics().density + ""); //get请求的封装 if (method.equals("GET")) { //获取到请求地址api HttpUrl httpUrlurl = request.url(); HashMap
rootMap = new HashMap<>(); //通过请求地址(最初始的请求地址)获取到参数列表 Set
parameterNames = httpUrlurl.queryParameterNames(); for (String key : parameterNames) { //循环参数列表 if (Constants.PARM.equals(key)) { //判断是否有匹配的字段 这个类似于 /xxx/xxx?p={} 匹配这个p String oldParamsJson = httpUrlurl.queryParameter(Constants.PARM); if (oldParamsJson != null) { //因为有的是没有这个p={
"page":0} 而是直接/xxx/index的 HashMap
p = mGson.fromJson(oldParamsJson, HashMap.class); //原始参数 if (p != null) { for (Map.Entry
entry : p.entrySet()) { rootMap.put(entry.getKey(), entry.getValue()); } } } } else { rootMap.put(key, httpUrlurl.queryParameter(key)); } } //String oldParamJson = httpUrlurl.queryParameter(Constants.PARM);// if (oldParamJson != null) {//// } //把原来请求的和公共的参数进行组装 rootMap.put("publicParams", commomParamsMap); //重新组装 String newJsonParams = mGson.toJson(rootMap); //装换成json字符串 String url = httpUrlurl.toString(); int index = url.indexOf("?"); if (index > 0) { url = url.substring(0, index); } url = url + "?" + Constants.PARM + "=" + newJsonParams; //拼接新的url request = request.newBuilder().url(url).build(); //重新构建请求 //post请求的封装 } else if (method.equals("POST")) {// FormBody.Builder builder = new FormBody.Builder();// builder.addEncoded("phone","phone"); RequestBody requestBody = request.body(); HashMap
rootMap = new HashMap<>(); if (requestBody instanceof FormBody) { for (int i = 0; i < ((FormBody) requestBody).size(); i++) { rootMap.put(((FormBody) requestBody).encodedName(i), ((FormBody) requestBody).encodedValue(i)); } } else { //buffer流 Buffer buffer = new Buffer(); requestBody.writeTo(buffer); String oldParamsJson = buffer.readUtf8(); rootMap = mGson.fromJson(oldParamsJson, HashMap.class); //原始参数 rootMap.put("publicParams", commomParamsMap); //重新组装 String newJsonParams = mGson.toJson(rootMap); //装换成json字符串 request = request.newBuilder().post(RequestBody.create(JSON, newJsonParams)).build(); } } } catch (JsonSyntaxException e) { e.printStackTrace(); } //最后通过chain.proceed(request)进行返回 return chain.proceed(request); }复制代码

####第二步 当我们把自定义的Interceptor构建完成之后,我们需要在Okhttp中进行使用。

return new OkHttpClient.Builder()                //HeadInterceptor 实现了Intercepter  用来网Request  Header添加一些相关数据  如APP版本 token信息//                .addInterceptor(new HttpLoggingInterceptor())                //添加自定义的拦截器,完成公共参数的封装                .addInterceptor(new CommonParamsInterceptor(gson,application))                .connectTimeout(10, TimeUnit.SECONDS)//链接超时                .readTimeout(10, TimeUnit.SECONDS)//设置读取超时                .build();复制代码

这个时候就可以了,我们来看下拦截之前和加入拦截器之后的请求url,看看是否起到了作用。 这个时候我们debug一下看下就明白了。 我们可以看到下图中上面的参数是只有一个,但是第二行就已经改变了,添加过了我们需要的公共参数,并且还有我们请求的参数。符合我们的要求。

###参考文章

转载地址:http://sylum.baihongyu.com/

你可能感兴趣的文章
CGI(通用网关接口)
查看>>
Cocos2d-x教程(28)-ttf 字体库的使用
查看>>
Mysql group by,order by,dinstict优化
查看>>
Notepad++ 经常使用快捷键 (MEMO)
查看>>
nyoj116士兵杀死(两)段树单点更新
查看>>
《Programming WPF》翻译 第3章 2.处理输入
查看>>
cdoj 1252 24点游戏 dfs
查看>>
【问题汇总】ListView的FooterView设置可见性的问题
查看>>
JAVA中int、String的类型转换
查看>>
[翻译]opengl扩展教程2
查看>>
命令行上的narrowing(随着输入逐步减少备选项)工具
查看>>
基于Hadoop 2.6.0运行数字排序的计算
查看>>
J2EE的13个规范之(二) JDBC 及其使用
查看>>
【iOS开发-74】解决方式:Xcode6下利用preference保存数据,终于的plist文件在哪里?...
查看>>
JSTL fmt 格式化时间
查看>>
WCF学习之旅—WCF概述(四)
查看>>
PHP AJAXFORM提交图片上传并显示图片源代码
查看>>
CentOS安装mysql*.rpm提示conflicts with file from package的解决的方法
查看>>
PostgreSQL代码分析,查询优化部分,canonicalize_qual
查看>>
PHPSession-完全PHP5之session篇
查看>>