当网络请求都是基于一个URL,所有的接口都是同一个地址,而请求不同接口数据则是通过command字段进行配置,然后所有的请求参数都是需要自己写一个bean类,再转成json格式放入请求body里发给后台,而不是通过表单form-body发送,所以配置一些公共参数,如sessionId、timestamp等就有点麻烦,每个bean类都要加这些参数,或者写个基类BaseRequestBean,基类当中配置公共参数,这是一种解决方案,但我不想这么做,那么只能通过okhttp配置拦截器设置公共参数;以下进入主题:
拦截器配置步骤
1、拦截器CommonSignParamsInterceptor类继承于okhttp3.Interceptor类,重写父类方法intercept
2、自定义一个private HashMap<String,String> getCommanParams()方法,在该方法当中,通过HashMap对象,以键值对方式设置公共参数
3、在intercept方法当中获取请求体,调用getCommanParams方法,重新配置请求体并发送请求
遇到的问题,当公共参数放在请求头header或者是form-body当中配置可能放便些,如下:
@Override
public Response intercept(@NonNull Chain chain) throws IOException {
Response response;
Request originRequest = chain.request();
Request.Builder newRequest = originRequest.newBuilder();
RequestBody body = originRequest.body();
//添加请求头参数,调用addHeader(key,value)方法
newRequest.addHeader("header-key",
new JSONObject(getCommonParams()).toString());
if (body == null) {
body = EMPTY_BODY;
newRequest.post(body);
} else if(body instanceof FormBody){
//添加表单参数form-body
FormBody oldBody = (FormBody) body;
FormBody.Builder newFormBodyBuilder = new FormBody.Builder();
for (int i = 0; i < oldBody.size(); i++) {
newFormBodyBuilder.add(oldBody.name(i), oldBody.value(i));
}
//添加公共参数
for (Map.Entry<String, String> entry : getCommonParams().entrySet()) {
newFormBodyBuilder.add(entry.getKey(), entry.getValue());
}
FormBody newFormBody = newFormBodyBuilder.build();
newRequest.post(newFormBody);
}
response = chain.proceed(newRequest.build());
return response;
}
通过以上代码发现,添加请求头作为公共参数最简单,直接调用newRequest.addHeader就行,而添加表单参数也不难,只是简单的将原请求参数取出放入新的FormBody.Builder对象即可;那么还有一种情况,就是本文主题,如何将公共参数放入请求体body的json对象当中?
通过阅读源码,okhttp3.logging.HttpLoggingInterceptor发现,该拦截器是这样打印请求内容的,包括header等等请求信息:
if (!logBody || !hasRequestBody) {
logger.log("--> END " + request.method());
} else if (bodyHasUnknownEncoding(request.headers())) {
logger.log("--> END " + request.method() + " (encoded body omitted)");
} else {
Buffer buffer = new Buffer();
requestBody.writeTo(buffer);
Charset charset = UTF8;
MediaType contentType = requestBody.contentType();
if (contentType != null) {
charset = contentType.charset(UTF8);
}
logger.log("");
if (isPlaintext(buffer)) {
logger.log(buffer.readString(charset));
logger.log("--> END " + request.method()
+ " (" + requestBody.contentLength() + "-byte body)");
} else {
logger.log("--> END " + request.method() + " (binary "
+ requestBody.contentLength() + "-byte body omitted)");
}
}
通过以上源码可发现,else里面,将requestBody通过writeTo方法写入到buffer当中,再buffer内容读出,这就可先将原请求体和内容取出,取出之后,才能修改并加公共参数;具体实现代码跟源码方式大同小异,代码如下:
@Override
public Response intercept(@NonNull Chain chain) throws IOException {
Response response;
Request originRequest = chain.request();
Request.Builder newRequest = originRequest.newBuilder();
RequestBody body = originRequest.body();
//添加请求头参数,调用addHeader(key,value)方法
//newRequest.addHeader("header-key",
// new JSONObject(getCommonParams()).toString());
if (body == null) {
//------------
} else if(body instanceof FormBody){
//添加表单参数form-body
} else if(body instanceof MultipartBody){
//..........非本文主题
} else {
Buffer buffer = new Buffer();
body.writeTo(buffer);
Charset charset = Charset.forName("UTF-8");
MediaType contentType = body.contentType();
if (contentType != null) {
charset = contentType.charset(charset);
if (charset != null) {
//读取原请求参数内容
String requestParams = buffer.readString(charset);
try {
//重新拼凑请求体
JSONObject jsonObject = new JSONObject(requestParams);
for (Map.Entry<String, String> entry : getCommonParams().entrySet()) {
jsonObject.put(entry.getKey(), entry.getValue());
}
RequestBody newBody = RequestBody.create(body.contentType(), jsonObject.toString());
newRequest.post(newBody);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}
response = chain.proceed(newRequest.build());
return response;
}
文毕,好好学习,天天向上