我们在使用retrofit联网开发的过程中,会遇到API每一次请求数据都会带有相同的公共参数。
例如:
然而,我们请求有post与get两种方式,我再百度的过程中基本都是用的get请求方式,可能大多都是为了测试方便。一般开发过程中我还是建议用post来请求数据。在这儿我们就多扯一点两者的区别。
GET:GET请求的数据会附再URL之后(就是把数据放置在HTTP协议头中),以?分割URL和传输数据,参数之间&相连,比如:http://music.163.com/#/song?id=436514312&autoplay=true&market=baiduhd。较深的这部分就是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 中插入键值对参数。
在 header 中插入键值对 Map 集合,批量插入。
在 header 中插入 headerLine 字符串,字符串需要符合 -1 != headerLine.indexOf(“:”) 的规则,即可以解析成键值对。
同上,headerLineList: List 为参数,批量插入 headerLine。
插入键值对参数到 url query 中。
插入键值对参数 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/