• SpringBoot 拦截器 统一日志 记录用户请求返回日志


    你请求我接口,传了什么参数,我返回了什么值给你,全部记下来。防止扯皮

    需求:记录每次用户请求Controller的Body参数,

    思路:在每个Controller 该当中记录,容易漏记,如果在拦截器里面记的话,可以统一处理

    问题:在postHandle 里面记,request.getInputStream() 取出来是空的,放在preHandle里面,就进不到 Controller 里面了。报:I/O error while reading input message; nested exception is java.io.IOException: Stream closed

    原因:在拦截器已经读取了请求体中的内容,这时候请求的流中已经没有了数据,就是说HttpServletRequest请求体中的内容一旦读取就不不存在了,所以直接读取是不行的

    方案:对httprequest进行修饰,自定义的包装类来实现

    添加 RequestLogFilter

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Component;
    
    import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import javax.servlet.http.HttpServletRequest;
    import java.io.IOException;
    
     
    @Component
    @WebFilter(filterName = "requestLogFilter",urlPatterns = {"/*"}, 
    initParams = {@WebInitParam(name = "ignoredUrl", value = ".css;.js;.jpg;.png;.gif;.ico;.html"),
    @WebInitParam(name = "filterPath", value = "/user/login#/user/registerUser")}) public class RequestLogFilter implements OncePerRequestFilter { private Logger logger = LoggerFactory.getLogger(this.getClass()); @Override protected void doFilterInternal(HttpServletRequest servletRequest, HttpServletResponse servletResponse, FilterChain filterChain) throws ServletException, IOException { RequestLogWrapper requestWapper = null; if (servletRequest instanceof HttpServletRequest) { HttpServletRequest request = (HttpServletRequest) servletRequest; if (!request.getRequestURI().toLowerCase().contains("swagger")
    && !request.getRequestURI().toLowerCase().contains("upload")) { //排除swagger、上传文件等接口 requestWapper
    = new RequestLogWrapper(request); } } ResponseLogWrapper responseLogWrapper = new ResponseLogWrapper(servletResponse); //获取请求中的流如何,将取出来的字符串,再次转换成流,然后把它放入到新request对象中 // 在chain.doFiler方法中传递新的request对象 if (requestWapper == null) { filterChain.doFilter(servletRequest, servletResponse); } else { filterChain.doFilter(requestWapper, responseLogWrapper); } //打印返回响应日志 String result = new String(responseLogWrapper.getResponseData()); ServletOutputStream outputStream = servletResponse.getOutputStream(); outputStream.write(result.getBytes()); outputStream.flush(); outputStream.close(); String queryStr = StrUtil.isEmpty(servletRequest.getQueryString()) ? "" : "?" + servletRequest.getQueryString(); logger.info("{}{} Response =>\r\n{}", servletRequest.getRequestURI(), queryStr, result); } @Override public void destroy() { logger.info(">>>> RequestLogFilter destroy <<<<"); } }

    添加 RequestLogWapper

    import cn.hutool.core.util.StrUtil; 
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import javax.servlet.ReadListener;
    import javax.servlet.ServletInputStream;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletRequestWrapper;
    
    import java.io.*;
    import java.nio.charset.Charset;
    import java.nio.charset.StandardCharsets;
    
    
    public class RequestLogWrapper extends HttpServletRequestWrapper {
    
        private Logger logger = LoggerFactory.getLogger(this.getClass());
    
        private String requestBody;
    
        public String getRequestBody() {
            return requestBody;
        }
    
        public RequestLogWrapper(HttpServletRequest request) throws IOException {
            super(request);
            requestBody = getBodyString(request);
            String queryStr = StrUtil.isEmpty(request.getQueryString()) ? "" : "?" + request.getQueryString();
            logger.info("{}{}\r\n{}", request.getRequestURI(), queryStr, requestBody);
        }
    
        @Override
        public ServletInputStream getInputStream() throws IOException {
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(requestBody.getBytes(StandardCharsets.UTF_8));
            ServletInputStream servletInputStream = new ServletInputStream() {
                @Override
                public boolean isFinished() {
                    return false;
                }
    
                @Override
                public boolean isReady() {
                    return false;
                }
    
                @Override
                public void setReadListener(ReadListener readListener) {
                }
    
                @Override
                public int read() throws IOException {
                    return byteArrayInputStream.read();
                }
            };
            return servletInputStream;
        }
    
        @Override
        public BufferedReader getReader() throws IOException {
            return new BufferedReader(new InputStreamReader(getInputStream()));
        }
    
        public String getBodyString(HttpServletRequest request) {
            StringBuilder sb = new StringBuilder();
            InputStream inputStream = null;
            BufferedReader reader = null;
            try {
                inputStream = request.getInputStream();
                reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
                String line = "";
                while ((line = reader.readLine()) != null) {
                    sb.append(line);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (inputStream != null) {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (reader != null) {
                    try {
                        reader.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return sb.toString();
        }
    }

    ResponseLogWrapper

    import javax.servlet.ServletOutputStream;
    import javax.servlet.WriteListener;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpServletResponseWrapper;
    import java.io.*;
    
    
    public class ResponseLogWrapper extends HttpServletResponseWrapper {
    
    
        private ByteArrayOutputStream buffer = null;//输出到byte array
        private ServletOutputStream out = null;
        private PrintWriter writer = null;
    
        public ResponseLogWrapper(HttpServletResponse resp) throws IOException {
            super(resp);
            buffer = new ByteArrayOutputStream();// 真正存储数据的流
            out = new WapperedOutputStream(buffer);
            writer = new PrintWriter(new OutputStreamWriter(buffer, this.getCharacterEncoding()));
        }
    
        /** 重载父类获取outputstream的方法 */
        @Override
        public ServletOutputStream getOutputStream() throws IOException {
            return out;
        }
    
        /** 重载父类获取writer的方法 */
        @Override
        public PrintWriter getWriter() throws UnsupportedEncodingException {
            return writer;
        }
    
        /** 重载父类获取flushBuffer的方法 */
        @Override
        public void flushBuffer() throws IOException {
            if (out != null) {
                out.flush();
            }
            if (writer != null) {
                writer.flush();
            }
        }
    
        @Override
        public void reset() {
            buffer.reset();
        }
    
        /** 将out、writer中的数据强制输出到WapperedResponse的buffer里面,否则取不到数据 */
        public byte[] getResponseData() throws IOException {
            flushBuffer();
            return buffer.toByteArray();
        }
    
        /** 内部类,对ServletOutputStream进行包装 */
        private class WapperedOutputStream extends ServletOutputStream {
            private ByteArrayOutputStream bos = null;
    
            public WapperedOutputStream(ByteArrayOutputStream stream) throws IOException {
                bos = stream;
            }
    
            @Override
            public void write(int b) throws IOException {
                bos.write(b);
            }
    
            @Override
            public void write(byte[] b) throws IOException {
                bos.write(b, 0, b.length);
            }
    
            @Override
            public boolean isReady() {
                return false;
            }
    
            @Override
            public void setWriteListener(WriteListener listener) {
    
            }
        }
    }

    参考资源:

    https://www.jianshu.com/p/ba2d5101ad90

    https://blog.csdn.net/qq_38132283/article/details/107685797

  • 相关阅读:
    Storm集群环境搭建
    如何使用Python进行投资收益和风险分析
    [项目源码] JavaWeb校园宿舍管理系统
    (null) entry in command string: null chmod 0644
    Ubuntu设置代理服务器
    ZooKeeper异常:Error connecting service It is probably not running
    MySQL绿色版安装
    Pig关系型运算符例子
    pig分组统计例子
    java服务端项目开发规范
  • 原文地址:https://www.cnblogs.com/vipsoft/p/15825907.html
Copyright © 2020-2023  润新知