當網絡請求都是基於一個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;
}
文畢,好好學習,天天向上