参考:https://blog.csdn.net/a624806998/article/details/73863606
引言: 写这篇文章,因为在自己编写实现Http日志拦截器的时候,在拦截器中使用 response.body().string() 获取了返回的数据,但是在经过拦截器后,针对输出处理的时候,会再次调用 response.body().string(),这里就会导致流已关闭的异常。
参考上面的链接,修改了在拦截器中的response中的数据获取。保证了下一步的输出流的处理获取操作。
下面的就是能使用的的Http拦截器代码
package com.ztkj.common.log.interceptors; import com.alibaba.fastjson.JSON; import com.ztkj.common.log.aspect.bean.HttpHandlerBean; import com.ztkj.common.log.aspect.bean.LinkTrackingBean; import com.ztkj.common.log.aspect.threadlocals.LinkTrackingThreadLocal; import okhttp3.*; import okio.Buffer; import okio.BufferedSource; import org.apache.commons.lang3.exception.ExceptionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.EOFException; import java.io.IOException; import java.net.URLDecoder; import java.nio.charset.Charset; import java.nio.charset.UnsupportedCharsetException; import java.util.List; import java.util.Map; import java.util.UUID; /** * okhttp 拦截器定义: 统计请求信息以及耗时 * * @author hzb-ztkj */ public class HttpLogInterceptor implements Interceptor { private static final Logger logger = LoggerFactory.getLogger(HttpLogInterceptor.class); private static final Charset UTF8 = Charset.forName("UTF-8"); /** * 拦截过程中 收集 http请求输入、输出等信息,日志输出打印 * * @param chain * @return * @throws IOException */ @Override public Response intercept(Chain chain) throws IOException { //获取当前请求 Request request = chain.request(); //根据请求类型分析 HttpHandlerBean httpHandlerBean = new HttpHandlerBean(); //从http request中获取请求信息 httpHandlerBean.setUrl(request.url().toString()); //设置请求头信息 Headers headers = request.headers(); Map<String, List<String>> stringListMap = headers.toMultimap(); httpHandlerBean.setParamHeaderStr(JSON.toJSONString(stringListMap)); //设置请求body信息 RequestBody requestBody = request.body(); if (requestBody != null) { httpHandlerBean.setParamStr(getParam(requestBody)); } //设置请求方式 httpHandlerBean.setRequestMode(request.method()); Response response = null; try { response = chain.proceed(request); //设置状态码 httpHandlerBean.setCode(response.code() + ""); //设置响应头信息 Map<String, List<String>> responseHeaderMap = response.headers().toMultimap(); httpHandlerBean.setResultHeaderStr(JSON.toJSONString(responseHeaderMap)); //设置响应信息 ResponseBody responseBody = response.body(); if (responseBody != null) { //httpHandlerBean.setResultStr(JSON.toJSONString(responseBody.string())); httpHandlerBean.setResultStr(getResponseBody(responseBody)); } //设置用时信息 httpHandlerBean.setSendTime(response.sentRequestAtMillis()); httpHandlerBean.setReceiveTime(response.receivedResponseAtMillis()); //设置唯一性id LinkTrackingBean linkTrackingBean = LinkTrackingThreadLocal.get(); if (linkTrackingBean == null) { httpHandlerBean.setRequestId(UUID.randomUUID().toString()); } else { httpHandlerBean.setRequestId(linkTrackingBean.getRequestId()); httpHandlerBean.setUserId(linkTrackingBean.getUserId()); httpHandlerBean.setProductId(linkTrackingBean.getProductId()); } //响应消息 httpHandlerBean.setMessage(response.message()); } catch (Exception e) { logger.error("处理请求异常,异常原因:{}", ExceptionUtils.getStackTrace(e)); httpHandlerBean.setMessage(ExceptionUtils.getStackTrace(e)); } //输出,打印日志 logger.info(httpHandlerBean.httpLogPrint()); return response; } private String getResponseBody(ResponseBody responseBody) throws Exception { BufferedSource source = responseBody.source(); source.request(Long.MAX_VALUE); Buffer buffer = source.buffer(); Charset charset = UTF8; MediaType contentType = responseBody.contentType(); if (contentType != null) { try { charset = contentType.charset(UTF8); } catch (UnsupportedCharsetException e) { logger.error("将http数据写入流异常,异常原因:{}", ExceptionUtils.getStackTrace(e)); } } if (!isPlaintext(buffer)) { return null; } if (responseBody.contentLength() != 0) { String result = buffer.clone().readString(charset); return result; } return null; } private boolean isPlaintext(Buffer buffer) throws EOFException { try { Buffer prefix = new Buffer(); long byteCount = buffer.size() < 64 ? buffer.size() : 64; buffer.copyTo(prefix, 0, byteCount); for (int i = 0; i < 16; i++) { if (prefix.exhausted()) { break; } int codePoint = prefix.readUtf8CodePoint(); if (Character.isISOControl(codePoint) && !Character.isWhitespace(codePoint)) { return false; } } return true; } catch (EOFException e) { return false; } } /** * 读取参数 * * @param requestBody * @return */ private String getParam(RequestBody requestBody) { Buffer buffer = new Buffer(); String logparm; try { requestBody.writeTo(buffer); logparm = buffer.readUtf8(); logparm = URLDecoder.decode(logparm, "utf-8"); } catch (IOException e) { e.printStackTrace(); return ""; } return logparm; } }