文章采集功能(一个APP必备的日志功能,不是直接使用.body)
优采云 发布时间: 2021-11-02 23:05文章采集功能(一个APP必备的日志功能,不是直接使用.body)
日志采集是APP的必备功能,可以方便开发者快速定位和解决问题,那么在使用okhttp时我们应该如何添加日志功能呢?
直接干货
private class LogInterceptor implements Interceptor {
@Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Log.v(TAG, "request:" + request.toString());
long t1 = System.nanoTime();
okhttp3.Response response = chain.proceed(chain.request());
long t2 = System.nanoTime();
Log.v(TAG, String.format(Locale.getDefault(), "Received response for %s in %.1fms%n%s",
response.request().url(), (t2 - t1) / 1e6d, response.headers()));
okhttp3.MediaType mediaType = response.body().contentType();
String content = response.body().string();
Log.i(TAG, "response body:" + content);
return response.newBuilder()
.body(okhttp3.ResponseBody.create(mediaType, content))
.build();
}
}
...
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(new LogInterceptor())
.build();
首先我们实现了一个*敏*感*词*LogInterceptor,它做了三件事:打印请求内容->执行请求->打印响应内容,过程简单明了。但是有一个地方需要注意。调用 response.body().string() 方法后,响应中的流将被关闭。我们需要通过response.peekBody()方法创建一个新的响应供应用层处理 复制一个ResponseBody,使用这个临时的ResponseBody来打印body的内容,而不是直接使用response.body().string()(这个方法在header的content-length不确定的时候会报错,谢谢推送键盘男kkmike999的修正)。快手的同学已经打完代码,再次验证,
为什么是这样?谈话很便宜,给我看代码。先看 response.body().string() 的实现
public final String string() throws IOException {
return new String(bytes(), charset().name());
}
string() 调用 bytes() 来获取内容
public final byte[] bytes() throws IOException {
//省略部分代码
BufferedSource source = source();
byte[] bytes;
try {
bytes = source.readByteArray();
} finally {
Util.closeQuietly(source);
}
//省略部分代码
return bytes;
}
在bytes()方法中,首先获取BufferedSource,然后读取BufferedSource中的内容,最后关闭BufferedSource中的文件流。似乎没有问题。等等,我们在*敏*感*词*中关闭了BufferedSource中的文件流,而ResponseBody中并没有对应的数据缓存,所以我们在*敏*感*词*之外获取body的内容失败,一切终于水落石出。
可以看到,我们相当于在*敏*感*词*中手动处理了网络请求的整个过程,也就是说在*敏*感*词*中可以做很多事情,比如虚拟返回结果等,这些不是内容本文。.
更新
使用Logging Interceptor可以轻松实现日志功能,请参考详情
参考内容:
[1]。