主要是用来打印请求参数,请求地址和返回
json
的拦截器封装
最近研究了Retrofit感觉不错,但是如果有自己封装的框架应该更好点,会更适合自己的开发。用这个写了个小demo发现个问题,封装后找不到打印和请求参数的地方了,后来想到了拦截器,分析后封装了个,这个拦截器只有打印功能,隐藏在发布版可以直接去掉这个类
import android.util.Log;
import java.io.IOException;
import java.nio.charset.Charset;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSource;
import static okhttp3.internal.Util.UTF_8;
public class LoggerInterceptor implements Interceptor {
public static final String TAG = "NetWorkLogger";
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
printRequestMessage(request);
Response response = chain.proceed(request);
printResponseMessage(response);
return response;
}
/**
* 打印请求消息
*
* @param request 请求的对象
*/
private void printRequestMessage(Request request) {
if (request == null) {
return;
}
Log.i(TAG, "Url : " + request.url().url().toString());
Log.i(TAG, "Method: " + request.method());
Log.i(TAG, "Heads : " + request.headers());
RequestBody requestBody = request.body();
if (requestBody == null) {
return;
}
try {
Buffer bufferedSink = new Buffer();
requestBody.writeTo(bufferedSink);
Charset charset = requestBody.contentType().charset();
charset = charset == null ? Charset.forName("utf-8") : charset;
Log.i(TAG, "Params: " + bufferedSink.readString(charset));
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 打印返回消息
*
* @param response 返回的对象
*/
private void printResponseMessage(Response response) {
if (response == null || !response.isSuccessful()) {
return;
}
ResponseBody responseBody = response.body();
long contentLength = responseBody.contentLength();
BufferedSource source = responseBody.source();
try {
source.request(Long.MAX_VALUE); // Buffer the entire body.
} catch (IOException e) {
e.printStackTrace();
}
Buffer buffer = source.buffer();
Charset charset = UTF_8;
MediaType contentType = responseBody.contentType();
if (contentType != null) {
charset = contentType.charset();
}
if (contentLength != 0) {
String result = buffer.clone().readString(charset);
Log.i(TAG, "Response: " + result);
}
}
}
当然其中也有不少小坑,参考了部分博客总算解决了。比较要注意的就是打印返回值的时候,如果直接获取值打印的话,就会讲流关闭,下次就不能再去取了,最总结果就是在回调的时候你不能去获取返回值。解决方法也不难,就是先clone
一份,然后再去获取值,打印出来就好了,比较麻烦的就是ResponseBody
不能直接去clone
,要去内部获取source
再去clone
读取
使用比较简单,直接上代码
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(new LoggerInterceptor())
.build();
这个暂时不能设置为网络拦截器,否则返回的JSON
会乱码,猜测可能是网络拦截器所在的位置还没有处理好,暂时还不是可读取的格式,或者是还在压缩状态,有兴趣的同学可以研究下
如果是使用Retrofit,直接讲client
添加为CallFactory
就可以了:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://192.168.1.73:8081/Apis/")
.addConverterFactory(GsonConverterFactory.create())
.callFactory(okHttpClient1)
.build();