OKHttp使用拦截器(Interceptor)POST与GET方法,统一封装传公共参数

我们在使用retrofit联网开发的过程中,会遇到API每一次请求数据都会带有相同的公共参数。
例如:

  • 用户ID : 1111111
  • 设备唯一ID:132131290
  • 客户端版本号:2.3.0
  • 等一些参数……

然而,我们请求有postget两种方式,我再百度的过程中基本都是用的get请求方式,可能大多都是为了测试方便。一般开发过程中我还是建议用post来请求数据。在这儿我们就多扯一点两者的区别。

GET:GET请求的数据会附再URL之后(就是把数据放置在HTTP协议头中),以?分割URL和传输数据,参数之间&相连,比如:http://music.163.com/#/song?id=436514312&autoplay=true&market=baiduhd。较深的这部分就是URL的传输数据。

  1. GET方式提交数据最多只能1024字节,因为GET是通过URL提交数据,所以GET提交的数据量就跟URL的长度有直接关系了。而实际上,URL不存在参数上线的问题,HTTP协议规范没有对URL长度的限制。这个显示是特定的浏览器及服务器对它的限制。IE对URL长度的限制是2083字节(2K+35)。对于其他浏览器,如Netscape、FireFox等,理论上没有长度限制,其限制取决于操作系统的支持。注意这是限制是整个URL长度,而不仅仅是你的参数值数据长度。

POST:POST则是把提交的数据放置在HTTP包的包体中。HTTP协议规范也没有进行大小限制,POST数据是没有限制的,起限制作用的是服务器的处理程序的处理能力。

1.POST的安全性要比GET的安全性高。注意:这里所说的安全性和上面GET提到的“安全”不是同个概念。上面“安全”的含义仅仅是不作数据修改,而这里安全的含义是真正的Security的含义,比如:通过GET提交数据,用户名和密码将明文出现在URL上,因为(1)登录页面有可能被浏览器缓存,(2)其他人查看浏览器的历史纪录,那么别人就可以拿到你的账号和密码了,除此之外,使用GET提交数据还可能会造成Cross-site request forgery攻击。


总结一下,GET就是从服务器中获取/查询资源信息,POST一般用于向服务器提交数据来更新资源信息,再FORM(表单)中,Method默认为“GET”,实质上,GET和POST只是发送机制不同,并不是一个取一个发!

参考原文地址:http://www.cnblogs.com/hyddd/archive/2009/03/31/1426026.html

根据以上的概述:就知道我们为什么要用POST请求,而不用GET请求。

回归主题,用什么方法来统一实现传公共参数。

实现

如果使用 OkHttp 作为 http request client, 这件事情就变得简单多了。OkHttp 提供了强大的拦截器组件 (Interceptor):

Interceptors are a powerful mechanism that can monitor, rewrite, and retry calls.

OKHttp的拦截器功能之一就是将要发出的请求进行拦截,改造然后再发出。BasicParamsInterceptor 实现了 okhttp3.Interceptor 接口。

  • addParam(String key, String value)

    post 请求,且 body type 为 x-www-form-urlencoded 时,键值对公共参数插入到 body 参数中,其他情况插入到 url query 参数中。

  • addParamsMap(Map paramsMap)

    同上,不过这里用键值对 Map 作为参数批量插入。

  • addHeaderParam(String key, String value)

在 header 中插入键值对参数。

  • addHeaderParamsMap(Map headerParamsMap)

在 header 中插入键值对 Map 集合,批量插入。

  • addHeaderLine(String headerLine)

在 header 中插入 headerLine 字符串,字符串需要符合 -1 != headerLine.indexOf(“:”) 的规则,即可以解析成键值对。

  • addHeaderLinesList(List headerLinesList)

同上,headerLineList: List 为参数,批量插入 headerLine。

  • addQueryParam(String key, String value)

插入键值对参数到 url query 中。

  • addQueryParamsMap(Map queryParamsMap)

插入键值对参数 map 到 url query 中,批量插入。

BasicParamsInterceptor代码:

package com.zy.blogs.blogssample.util;

import android.text.TextUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import okhttp3.FormBody;
import okhttp3.Headers;
import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okio.Buffer;

/**
 * 

* 作者:zhouyuan on 2017/1/4 14:16 *

* 邮箱:[email protected] *

* github地址: https://github.com/jkyeo/okhttp-basicparamsinterceptor */ public class BasicParamsInterceptor implements Interceptor { Map queryParamsMap = new HashMap<>(); Map paramsMap = new HashMap<>(); Map headerParamsMap = new HashMap<>(); List headerLinesList = new ArrayList<>(); private BasicParamsInterceptor() { } @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); Request.Builder requestBuilder = request.newBuilder(); // process header params inject if (headerParamsMap != null && headerParamsMap.size() > 0) { Set keys = headerParamsMap.keySet(); for (String headerKey : keys) { requestBuilder.addHeader(headerKey, headerParamsMap.get(headerKey)).build(); } } Headers.Builder headerBuilder = request.headers().newBuilder(); if (headerLinesList.size() > 0) { for (String line : headerLinesList) { headerBuilder.add(line); } requestBuilder.headers(headerBuilder.build()); } // process header params end // process queryParams inject whatever it's GET or POST if (queryParamsMap.size() > 0) { request = injectParamsIntoUrl(request.url().newBuilder(), requestBuilder, queryParamsMap); } // process post body inject if (paramsMap.size() > 0) { if (canInjectIntoBody(request)) { FormBody.Builder formBodyBuilder = new FormBody.Builder(); for (Map.Entry entry : paramsMap.entrySet()) { formBodyBuilder.add((String) entry.getKey(), (String) entry.getValue()); } RequestBody formBody = formBodyBuilder.build(); String postBodyString = bodyToString(request.body()); postBodyString += ((postBodyString.length() > 0) ? "&" : "") + bodyToString(formBody); requestBuilder.post(RequestBody.create(MediaType.parse("application/x-www-form-urlencoded;charset=UTF-8"), postBodyString)); } } request = requestBuilder.build(); return chain.proceed(request); } private boolean canInjectIntoBody(Request request) { if (request == null) { return false; } if (!TextUtils.equals(request.method(), "POST")) { return false; } RequestBody body = request.body(); if (body == null) { return false; } MediaType mediaType = body.contentType(); if (mediaType == null) { return false; } if (!TextUtils.equals(mediaType.subtype(), "x-www-form-urlencoded")) { return false; } return true; } // func to inject params into url private Request injectParamsIntoUrl(HttpUrl.Builder httpUrlBuilder, Request.Builder requestBuilder, Map paramsMap) { if (paramsMap.size() > 0) { Iterator iterator = paramsMap.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry entry = (Map.Entry) iterator.next(); httpUrlBuilder.addQueryParameter((String) entry.getKey(), (String) entry.getValue()); } requestBuilder.url(httpUrlBuilder.build()); return requestBuilder.build(); } return null; } private static String bodyToString(final RequestBody request) { try { final RequestBody copy = request; final Buffer buffer = new Buffer(); if (copy != null) copy.writeTo(buffer); else return ""; return buffer.readUtf8(); } catch (final IOException e) { return "did not work"; } } public static class Builder { BasicParamsInterceptor interceptor; public Builder() { interceptor = new BasicParamsInterceptor(); } public Builder addParam(String key, String value) { interceptor.paramsMap.put(key, value); return this; } public Builder addParamsMap(Map paramsMap) { interceptor.paramsMap.putAll(paramsMap); return this; } public Builder addHeaderParam(String key, String value) { interceptor.headerParamsMap.put(key, value); return this; } public Builder addHeaderParamsMap(Map headerParamsMap) { interceptor.headerParamsMap.putAll(headerParamsMap); return this; } public Builder addHeaderLine(String headerLine) { int index = headerLine.indexOf(":"); if (index == -1) { throw new IllegalArgumentException("Unexpected header: " + headerLine); } interceptor.headerLinesList.add(headerLine); return this; } public Builder addHeaderLinesList(List headerLinesList) { for (String headerLine : headerLinesList) { int index = headerLine.indexOf(":"); if (index == -1) { throw new IllegalArgumentException("Unexpected header: " + headerLine); } interceptor.headerLinesList.add(headerLine); } return this; } public Builder addQueryParam(String key, String value) { interceptor.queryParamsMap.put(key, value); return this; } public Builder addQueryParamsMap(Map queryParamsMap) { interceptor.queryParamsMap.putAll(queryParamsMap); return this; } public BasicParamsInterceptor build() { return interceptor; } } }

具体使用方法:

          BasicParamsInterceptor basicParamsInterceptor =
                    new BasicParamsInterceptor.Builder()
                            .addHeaderParam("User-Agent", "xxxxxxxxxxx")
                            .addHeaderParam("Accept", "application/json")
                            .addParam("_t", time)
                            .addParam("_tsp", tsp)
                            .build();

            OkHttpClient.Builder builder = new OkHttpClient.Builder();

            builder.addInterceptor(basicParamsInterceptor);

OkHttpClient okHttpClient = builder.build();
            mRetrofit = new Retrofit.Builder()
                    .baseUrl(ApiStores.BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .client(okHttpClient)
                    .build();

该文,与原文有出入。

具体原文看:http://www.jkyeo.com/2016/04/18/BasicParamsInterceptor-%E4%B8%BA-OkHttp-%E8%AF%B7%E6%B1%82%E6%B7%BB%E5%8A%A0%E5%85%AC%E5%85%B1%E5%8F%82%E6%95%B0/

你可能感兴趣的:(android)