zoukankan      html  css  js  c++  java
  • Okhttp拦截器统一异常处理并多次读取response.body().string()

    参考: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;
        }
    }
  • 相关阅读:
    Python3小练习2——(汉诺塔的移动),递归
    Python3小练习1——(ax*x+ bx + c = 0的解)
    SSRS数据导出Excel多出空白列
    ETL 压缩文件(makecab) 并邮件发送
    关于System.Web.Script.Serialization命名空间的引用
    如何通过VIsual Studio安装程序修改VS2017?
    如何其他服务器能够连接自己本机的数据库?
    SSAS表格模型部署问题
    表格模型——安装实例
    Leetcode 76题:最小覆盖子串 滑动窗口经典题
  • 原文地址:https://www.cnblogs.com/duguxiaobiao/p/12092231.html
Copyright © 2011-2022 走看看