servlet容器-请求响应日志跟踪工具

 往往我们记录http请求响应日志时,都习惯性用log.info等方式,随着业务代码量增加,代码可读性非常糟糕。这时我们可以借助servlet拦截器帮助我们来实现统一日志跟踪

 直接上代码

package com.lmx.demo.filter;

import com.google.common.base.Charsets;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StreamUtils;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.*;
import java.util.List;

/**
 * http报文日志拦截器
 */
@Slf4j
public class HttpLogTraceFilter implements Filter {

    private List<String> ignoreUrlList;

    @Override
    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        String uri = httpRequest.getRequestURI().trim().toLowerCase();
        log.info("uri ={}", uri);
        if (isIgnore(uri)) {
            chain.doFilter(request, response);
        } else {
            byte[] byteData = StreamUtils.copyToByteArray(request.getInputStream());
            String reqBody = new String(byteData, Charsets.UTF_8);

            ServletOutputStreamWrap servletOutputStreamWrap = new ServletOutputStreamWrap();
            LogWrapServletResponse servletResponseWrapper = new LogWrapServletResponse(response, servletOutputStreamWrap);
            LogWrapServletRequest logWrapServletRequest = new LogWrapServletRequest(request, byteData);

            log.info("reqBody={}", reqBody);
            chain.doFilter(logWrapServletRequest, servletResponseWrapper);
            String resp = servletOutputStreamWrap.get();
            log.info("respBody={}", resp);

            response.setContentType("application/json;charset=utf-8");
            PrintWriter printWriter = response.getWriter();
            printWriter.print(resp);
            printWriter.flush();
            printWriter.close();
        }
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {
        String ignoreUrl = arg0.getInitParameter("ignoreUrl");
        if (ignoreUrl == null) {
            this.ignoreUrlList = Lists.newArrayList();
        } else {
            /**
             * 忽略的uri,多个用逗号分隔
             */
            this.ignoreUrlList = Lists.newArrayList(Splitter.on(",").split(ignoreUrl));
        }
    }

    boolean isIgnore(String uri) {
        for (String s : ignoreUrlList) {
            if (uri.contains(s)) {
                return true;
            }
        }
        return false;
    }

    public class LogWrapServletRequest extends HttpServletRequestWrapper {
        private byte[] req;

        public LogWrapServletRequest(ServletRequest request, byte[] req) {
            super((HttpServletRequest) request);
            this.req = req;
        }

        public ServletInputStream getInputStream() {
            return new ServletInputStreamWrap(new ByteArrayInputStream(req));
        }


    }

    public static class ServletInputStreamWrap extends ServletInputStream {

        private final InputStream sourceStream;


        public ServletInputStreamWrap(InputStream sourceStream) {
            this.sourceStream = sourceStream;
        }


        @Override
        public int read() throws IOException {
            return this.sourceStream.read();
        }

        @Override
        public void close() throws IOException {
            super.close();
            this.sourceStream.close();
        }

    }

    public static class LogWrapServletResponse extends HttpServletResponseWrapper {
        private ServletOutputStreamWrap servletOutputStreamWrap;

        public LogWrapServletResponse(ServletResponse response, ServletOutputStreamWrap servletOutputStreamWrap) {
            super((HttpServletResponse) response);
            this.servletOutputStreamWrap = servletOutputStreamWrap;
        }

        public ServletOutputStreamWrap getServletOutputStreamWrap() {
            return servletOutputStreamWrap;
        }

        public ServletOutputStream getOutputStream() throws IOException {
            return servletOutputStreamWrap;
        }
    }

    @Slf4j
    public static class ServletOutputStreamWrap extends ServletOutputStream {
        private List<Byte> list = Lists.newArrayList();

        public ServletOutputStreamWrap() {
        }

        @Override
        public void write(int b) throws IOException {
            list.add((byte) b);
        }

        public String get() {
            byte[] resp = new byte[list.size()];
            for (int i = 0; i < list.size(); i++) {
                resp[i] = list.get(i);
            }
            try {
                return new String(resp, Charsets.UTF_8.toString());
            } catch (UnsupportedEncodingException e) {
                log.error("", e);
                return "";
            }
        }
    }
}

配置拦截器

springMVC配置web.xml

springboot通过FilterRegistyBean注入

日志效果

2019-09-26 10:48:05.162 [http-apr-8080-exec-6] INFO 
                c.q.filter.HttpLogTraceFilter - uri =/xxx/xxxx.json
2019-09-26 10:48:05.162 [http-apr-8080-exec-6] INFO 
                c.q.filter.HttpLogTraceFilter - reqBody={"id":252,"date":"2019-09-26"}
2019-09-26 10:48:05.176 [http-apr-8080-exec-6] INFO 
                c.q.filter.HttpLogTraceFilter - respBody={"result":0,"message":""}
发布了22 篇原创文章 · 获赞 12 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/lmx1989219/article/details/101516529
今日推荐