原文連接:建立OkHttp自定義Loghtml
本文重點講解如何在使用OkHttp做爲網絡請求框架的前提下,如何自定義一個適合本身項目的Http Log,從而提高網絡Api開發、調試效率。java
只有對Http協議有基本的瞭解,才能更好的調試網絡接口。git
男女主一次偶然的機會,開始信件傳情,但他們的信件並非直接寄給對方,而是先寄到某個地點A,由地點A的主人轉發。(好吧,這是《北京趕上西雅圖之不二情書》的情節)。咱們來看男主發信的過程:github
顯然,女主收到信後回覆信件也是一樣的流程。json
咱們如今將Http協議的消息結構和故事主人公收發信的過程作一個類比:
api
由前面的分析可知,Http請求消息由三部分組成:服務器
Http響應體跟請求體格式大體同樣。網絡
OkHttp的一大特色就是能夠在發出請求體和收到響應體之間添加任意個數任意任意功能的攔截器,對請求體或者響應體進行操做。仍是用《北京趕上西雅圖之不二情書》的故事來講,那麼地點A的主人就是充當攔截器的角色,在故事中他不只轉發信件,還閱讀了信件的內容。session
Log的信息和劃分兩類,一類是跟業務相關的信息,一類是與業務無關。app
業務相關包括:
請求地址url;
請求頭:token、sessionId;
請求體:POST提交的內容;
響應頭:token/sessionId;
響應體:服務器返回數據;
業務無關包括:
網絡狀態碼:200爲正常反應;
網絡請求時間:從發出網絡請求到響應所消耗的時間;
網絡協議:http一、http2等;
網絡Method:POST、GET等;
不論是業務相關的數據仍是業務無關的數據,都是來自於Http請求體和響應體的消息結構中。
以公司項目的測試服務器自動登陸接口,log效果以下:
POST
acid->1075
userId->-1
network code->200
url->http://mobileapi.app100688440.twsapp.com/app/open/open.do?ACID=1075&userId=-1&vendorId=7999&VERS=6.5.1&fromType=1110
time->84.473
request headers->sessionId:
request->{"data":{"pagenum":0,"uid":-1,"flag":"00000000"},"requeststamp":"20161212151841836466"}
body->{"code":200,"responsestamp":"20161212151841836466","data":{"uid":-1,"nickname":"遊客258","uploadUrl":"http://mobileapi.app100688440.twsapp.com/uploadservlet","wxUrl":"http://wx.app100688440.twsapp.com","isEmcee":0,"canLive":0,"goodnum":0,"index":{},"revGift":{},"msgRemind":{},"freshmanMission":{},"account":{},"onlineLimit":"600","userSecretKey":"brjefjzw37ocw46"}}複製代碼
log解釋:
POST:此接口使用POST方法;
acid:標識此接口的id,每一個接口有惟一的acid,根據acid可查詢到此接口的功能,例如此接口acid = 1075爲自動登陸接口;
userId:用戶id
network code:返回200證實服務器響應成功;
url:此接口請求的url地址;
time:爲響應時間,若是某接口響應時間過長,排除網絡環境的緣由,就能夠跟服務端商量是否可優化;
request header:此項目須要傳sessionId;
request:此處打印Post方法的請求體,若後臺返回參數錯誤,檢查此行log便可;
body:後臺數據返回,採用json格式;
/** * 添加Log */
public class LogInterceptor implements Interceptor {
private static final String TAG = "LogInterceptor";
private static final Charset UTF8 = Charset.forName("UTF-8"); //urf8編碼
@Override
public Response intercept(Chain chain) throws IOException { //實現Interceptor接口方法
Log.d(TAG,"before chain,request()");
Request request = chain.request(); //獲取request
String acid = request.url().queryParameter("ACID"); //在url中獲取ACID的參數值;
Response response;
try {
long t1 = System.nanoTime();
response = chain.proceed(request); //OkHttp鏈式調用
long t2 = System.nanoTime();
double time = (t2 - t1) / 1e6d; //用請求後的時間減去請求前的時間獲得耗時
String userId = request.url().queryParameter("userId");
String type = "";
if (request.method().equals("GET")) { //判斷Method類型
type = "GET";
} else if (request.method().equals("POST")) {
type = "POST";
} else if (request.method().equals("PUT")) {
type = "PUT";
} else if (request.method().equals("DELETE")) {
type = "DELETE";
}
BufferedSource source = response.body().source();
source.request(Long.MAX_VALUE); // Buffer the entire body.
Buffer buffer = source.buffer();
String logStr = "\n--------------------".concat(TextUtils.isEmpty(acid) ? "" : acid).concat(" begin--------------------\n")
.concat(type)
.concat("\nacid->").concat(TextUtils.isEmpty(acid) ? "" : acid)
.concat("\nuserId->").concat(TextUtils.isEmpty(userId) ? "" : userId)
.concat("\nnetwork code->").concat(response.code() + "")
.concat("\nurl->").concat(request.url() + "")
.concat("\ntime->").concat(time + "")
.concat("\nrequest headers->").concat(request.headers() + "")
.concat("request->").concat(bodyToString(request.body()))
.concat("\nbody->").concat(buffer.clone().readString(UTF8)); //響應體轉String
Log.i(TAG, logStr);
} catch (Exception e) {
Log.d(TAG,e.getClass().toString()+", error:acid = "+acid); //網絡出錯,log 出錯的acid
throw e; //不攔截exception,由上層處理網絡錯誤
}
return response;
}
/** * 請求體轉String * @param request * @return */
private static String bodyToString(final RequestBody request) {
try {
final Buffer buffer = new Buffer();
request.writeTo(buffer);
return buffer.readUtf8();
} catch (final IOException e) {
return "did not work";
}
}
}複製代碼
若是不想本身編寫代碼,也可使用開源項目okhttp-logging-interceptor,支持:1.設置Log的等級;2.使用自定義Log。此開源項目也僅是一個Interceptor。但我的以爲log的樣式並不適合調試使用。同時log的內容比較通用,若想突出對應項目的信息,建議仍是自定義Http Log。
此Interceptor配合OkHttp使用,關於Okhttp+Retrofit+Rxjava的整合,可查看RxJava+Retrofit+OkHttp封裝