美文网首页
打印http request body 和 response b

打印http request body 和 response b

作者: 何德何能者 | 来源:发表于2018-07-07 16:28 被阅读985次

    1、request 的inputStream和response 的outputStream默认情况下是只能读一次, 不可重复读;
    这就导致要获取请求体或者响应体信息时必须要声明包裹类wrapper; spring为此提供了两个对应的包裹类
    ContentCachingRequestWrapper和ContentCachingResponseWrapper使得这两个流信息可重复读;

    因此可以利用这两个类读取请求和响应信息,输出到日志

    import lombok.extern.slf4j.Slf4j;
    import org.slf4j.MDC;
    import org.springframework.core.Ordered;
    import org.springframework.stereotype.Component;
    import org.springframework.web.filter.OncePerRequestFilter;
    import org.springframework.web.util.ContentCachingRequestWrapper;
    import org.springframework.web.util.ContentCachingResponseWrapper;
    import org.springframework.web.util.WebUtils;
    
    import javax.servlet.FilterChain;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.UnsupportedEncodingException;
    import java.util.Enumeration;
    import java.util.UUID;
    
    /**
     * @Author: xxx
     * @Description:
     * @Date: created in 13:46 2018/7/7
     */
    @Component
    @Slf4j
    public class WebLogFilter extends OncePerRequestFilter implements Ordered {
    
        // put filter at the end of all other filters to make sure we are processing after all others
        private int order = Ordered.LOWEST_PRECEDENCE - 8;
    
        public static final String SPLIT_STRING_M = "=";
    
        public static final String SPLIT_STRING_DOT = ", ";
    
        @Override
        public int getOrder() {
            return order;
        }
    
        @Override
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
            //日志trade
            MDC.clear();
            MDC.put("trade_id", UUID.randomUUID().toString().replaceAll("-",""));
            ContentCachingRequestWrapper wrapperRequest = new ContentCachingRequestWrapper(request);
            ContentCachingResponseWrapper wrapperResponse = new ContentCachingResponseWrapper(response);
            String urlParams = getRequestParams(request);
            filterChain.doFilter(wrapperRequest, wrapperResponse);
    
            String requestBodyStr = getRequestBody(wrapperRequest);
            log.info("params[{}]|body:{}", urlParams, requestBodyStr);
    
            String responseBodyStr = getResponseBody(wrapperResponse);
    
            log.info("resp body:{}", responseBodyStr);
            wrapperResponse.copyBodyToResponse();
        }
    
        /**
         * 打印请求参数
         * @param request
         */
        private String getRequestBody(ContentCachingRequestWrapper request) {
            ContentCachingRequestWrapper wrapper = WebUtils.getNativeRequest(request, ContentCachingRequestWrapper.class);
            if(wrapper != null) {
                byte[] buf = wrapper.getContentAsByteArray();
                if(buf.length > 0) {
                    String payload;
                    try {
                        payload = new String(buf, 0, buf.length, wrapper.getCharacterEncoding());
                    } catch (UnsupportedEncodingException e) {
                        payload = "[unknown]";
                    }
                    return payload.replaceAll("\\n","");
                }
            }
            return "";
        }
    
        /**
         * 打印请求参数
         * @param response
         */
        private String getResponseBody(ContentCachingResponseWrapper response) {
            ContentCachingResponseWrapper wrapper = WebUtils.getNativeResponse(response, ContentCachingResponseWrapper.class);
            if(wrapper != null) {
                byte[] buf = wrapper.getContentAsByteArray();
                if(buf.length > 0) {
                    String payload;
                    try {
                        payload = new String(buf, 0, buf.length, wrapper.getCharacterEncoding());
                    } catch (UnsupportedEncodingException e) {
                        payload = "[unknown]";
                    }
                    return payload;
                }
            }
            return "";
        }
    
        /**
         * 获取请求地址上的参数
         * @param request
         * @return
         */
        public static String getRequestParams(HttpServletRequest request) {
            StringBuilder sb = new StringBuilder();
            Enumeration<String> enu = request.getParameterNames();
            //获取请求参数
            while (enu.hasMoreElements()) {
                String name = enu.nextElement();
                sb.append(name + SPLIT_STRING_M).append(request.getParameter(name));
                if(enu.hasMoreElements()) {
                    sb.append(SPLIT_STRING_DOT);
                }
            }
            return sb.toString();
        }
    }
    

    2、利用slf4j的MDC跟踪请求信息, 打印完整的请求处理日志;主要代码如下

            //日志trade
            MDC.clear();
            //给本次请求分配一个唯一的tradeId
            MDC.put("trade_id", UUID.randomUUID().toString().replaceAll("-",""));
    

    并在日志配置文件里加上trade_id的信息,如下

    [%X{trade_id}]%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
    

    到此完成日志跟踪功能, 效果如下

    [16fbd9304e23492cab3ccabb6a85d0c0]2018-07-07 16:18:49.130  INFO 13712 --- [nio-8188-exec-1] ren.xx.xx.filter.WebLogFilter       : params[ggii=44]|body:{    "account":"xxxxx",  "v_code":"056036"}
    [16fbd9304e23492cab3ccabb6a85d0c0]2018-07-07 16:18:49.131  INFO 13712 --- [nio-8188-exec-1] ren.xx.xx.filter.WebLogFilter       : resp body:{"code":1,"msg":"请输入正确的验证码","data":"","success":false}
    

    相关文章

      网友评论

          本文标题:打印http request body 和 response b

          本文链接:https://www.haomeiwen.com/subject/clfguftx.html