美文网首页
Spring MVC利用过滤器打印日志

Spring MVC利用过滤器打印日志

作者: 艺术类架构师 | 来源:发表于2019-08-06 14:12 被阅读0次

    在微服务架构体系中,利用SpringMVC打印单服务日志的实现形式有多种方式,本人了解的如下几种。

    1.继承DispatcherServlet.

    2.利用拦截器。

    3.利用过滤器。

    本章直接介绍用过滤器实现简单的打印请求上的输入输出日志,废话不多说了,直接贴干货吧,代码简单易懂!

    import com.alibaba.fastjson.JSONObject;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.io.IOUtils;
    import org.apache.commons.lang3.exception.ExceptionUtils;
    import org.springframework.http.HttpMethod;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.MediaType;
    import org.springframework.stereotype.Component;
    import org.springframework.util.ObjectUtils;
    import org.springframework.web.filter.OncePerRequestFilter;
    import org.springframework.web.util.ContentCachingRequestWrapper;
    import org.springframework.web.util.ContentCachingResponseWrapper;
    
    import javax.servlet.DispatcherType;
    import javax.servlet.FilterChain;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.util.*;
    
    import static java.nio.charset.StandardCharsets.UTF_8;
    
    /**
     * 在过滤器中打印输入输出日志
     * @Author
     * @Date 2019-08-06
     */
    @Component
    @Slf4j
    public class LoggingFilter extends OncePerRequestFilter {
    
        ObjectMapper objectMapper=new ObjectMapper();
    
        /**
         * 支持打印的MediaType
         */
        private static final Set<MediaType> supportMediaTypes=new HashSet<>();
        {
            supportMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
            supportMediaTypes.add(MediaType.APPLICATION_JSON);
            supportMediaTypes.add(MediaType.TEXT_HTML);
            supportMediaTypes.add(MediaType.TEXT_PLAIN);
            supportMediaTypes.add(MediaType.APPLICATION_ATOM_XML);
    
        }
    
        final  List<String> resourceRequestsURI = Arrays.asList(
                "/css/", "/js/", "/scss/", "/fonts/",
                ".css", ".js", ".scss", ".eot",
                ".svg", ".ttf", ".woff", ".otf", ".ico", ".png");
    
        final List<String> swaggerRequestURI = Arrays.asList(
                "/v2/api-docs", "/swagger-resources","swagger-ui");
    
        @Override
        protected void doFilterInternal( HttpServletRequest httpServletRequest,
                                         HttpServletResponse httpServletResponse,
                                         FilterChain filterChain)  {
    
           try {
    
               doLog(httpServletRequest,httpServletResponse,filterChain);
           }
           catch (Exception e){
               log.error("do log filter has a error:{} ", ExceptionUtils.getRootCause(e));
           }
        }
    
        void doLog(final HttpServletRequest httpServletRequest,
                   final HttpServletResponse httpServletResponse,
                   final FilterChain filterChain) throws IOException, ServletException {
    
            ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper(httpServletRequest);
            ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(httpServletResponse);
    
            filterChain.doFilter(requestWrapper, responseWrapper);
    
            String requestUrl = requestWrapper.getRequestURL().toString();
            String requestId=UUID.randomUUID().toString();
            HttpMethod httpMethod = HttpMethod.valueOf(requestWrapper.getMethod());
    
            log.info(" request id is: {},http method is:{}",requestId,httpMethod.name());
            log.info("request id is: {},requestUrl  is:{}",requestId, requestUrl);
    
            Enumeration<String> parameterEnum=requestWrapper.getParameterNames();
            if(!ObjectUtils.isEmpty(parameterEnum)) {
                log.info("request id is: {},request param   is:{}",requestId,getRequestParamJSON(requestWrapper));
    
            }
            log.info("request id is: {},request header  is:{}", requestId,getRequestHeader(requestWrapper));
    
    
            if(HttpMethod.valueOf(httpServletRequest.getMethod())!=HttpMethod.GET) {
                if(supportMediaTypes.contains(MediaType.valueOf(httpServletRequest.getContentType()))) {
                    log.info("request id is: {},request body  is:\n{}",requestId, new String(requestWrapper.getContentAsByteArray()));
                }
            }
            HttpStatus responseStatus = HttpStatus.valueOf(responseWrapper.getStatusCode());
            log.info("request id is: {},response status is:{}",requestId ,responseStatus.value());
            String responseBody = IOUtils.toString(responseWrapper.getContentInputStream(), UTF_8);
    
    
            if(httpServletRequest.isAsyncSupported()){
                log.info("request id is: {}, response payLoad is:\n{}",requestId, responseBody);
            }
            else if(!isAsyncStarted(httpServletRequest)&&httpServletRequest.getDispatcherType()!= DispatcherType.ASYNC) {
                log.info("request id is: {},response body is:{}",requestId ,objectMapper.readTree(responseBody));
            }
    
            else {
                log.info("request id is: {}, cause by request is async:response body is:{}", requestId,"empty");
    
            }
            responseWrapper.copyBodyToResponse();
        }
    
        @Override
        protected boolean shouldNotFilter(HttpServletRequest request)  {
    
            String requestUrl=request.getRequestURL().toString();
            return  isResourceUrl(requestUrl)||isSwaggerResource(requestUrl);
        }
    
        /**
         * 请求参数列表
         * @param requestWrapper
         * @return
         */
        private JSONObject getRequestParamJSON(ContentCachingRequestWrapper requestWrapper){
            Enumeration<String> parameterEnum=requestWrapper.getParameterNames();
            JSONObject paramJsonObject=new JSONObject();
            if(!ObjectUtils.isEmpty(parameterEnum)) {
                while (parameterEnum.hasMoreElements()) {
                    String name= parameterEnum.nextElement();
                    String []value=requestWrapper.getParameterValues(name);
                    paramJsonObject.put(name,value);
    
                }
            }
            return  paramJsonObject;
        }
    
        /**
         *
         * @param requestWrapper
         * @return 请求头参数列表
         */
        private JSONObject getRequestHeader(ContentCachingRequestWrapper requestWrapper){
    
            Enumeration headerNames = requestWrapper.getHeaderNames();
            JSONObject headerJsonObject=new JSONObject();
            while (headerNames.hasMoreElements()) {
                String headerName = (String) headerNames.nextElement();
                headerJsonObject.put(headerName,requestWrapper.getHeader(headerName));
            }
            return  headerJsonObject;
        }
    
        private boolean isResourceUrl(String url) {
            return resourceRequestsURI.stream().anyMatch(e->url.contains(e));
        }
    
        private boolean isSwaggerResource(String url) {
            return swaggerRequestURI.stream().anyMatch(e->url.contains(e));
    
        }
    }
    

    附带继承DispatchServlet实现日志打印

    package com.application.config;
    
    import com.fasterxml.jackson.databind.JsonNode;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.node.BaseJsonNode;
    import com.fasterxml.jackson.databind.node.JsonNodeFactory;
    import com.fasterxml.jackson.databind.node.ObjectNode;
    import org.apache.tomcat.util.http.fileupload.IOUtils;
    import org.slf4j.LoggerFactory;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.MediaType;
    import org.springframework.web.servlet.DispatcherServlet;
    import org.springframework.web.util.ContentCachingRequestWrapper;
    import org.springframework.web.util.ContentCachingResponseWrapper;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.util.Collection;
    import java.util.Enumeration;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.logging.Logger;
    
    public class CustLoggingDispatcherServlet extends DispatcherServlet {
    
        private static final org.slf4j.Logger logger = LoggerFactory.getLogger("logging");
    
        private static final ObjectMapper mapper = new ObjectMapper();
    
        @Override
        protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
            ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper(request);
            ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(response);
            //创建一个 json 对象,用来存放 http 日志信息
            ObjectNode rootNode = mapper.createObjectNode();
            rootNode.put("uri", requestWrapper.getRequestURI());
            rootNode.put("clientIp", requestWrapper.getRemoteAddr());
            rootNode.set("requestHeaders", mapper.valueToTree(getRequestHeaders(requestWrapper)));
            String method = requestWrapper.getMethod();
            rootNode.put("method", method);
            try {
                super.doDispatch(requestWrapper, responseWrapper);
            } finally {
                if(method.equals("GET")) {
                    rootNode.set("request", mapper.valueToTree(requestWrapper.getParameterMap()));
                }
                else {
                    JsonNode newNode = mapper.readTree(requestWrapper.getContentAsByteArray());
                    rootNode.set("request", newNode);
                }
    
                if(response.getContentType().equals(MediaType.APPLICATION_JSON.getType())
                        &&response.getContentType().equals( MediaType.APPLICATION_JSON_UTF8.getType())) {
                    JsonNode newNode = mapper.readTree(responseWrapper.getContentInputStream());
                    rootNode.set("response", newNode);
                }
                else{
                    JsonNode newNode = JsonNodeFactory.instance.textNode(new String(responseWrapper.getContentAsByteArray()));
                    rootNode.set("response", newNode);
    
                }
    
                responseWrapper.copyBodyToResponse();
    
                rootNode.set("responseHeaders", mapper.valueToTree(getResponsetHeaders(responseWrapper)));
                logger.info(rootNode.toString());
            }
        }
    
        private Map<String, Object> getRequestHeaders(HttpServletRequest request) {
            Map<String, Object> headers = new HashMap<>();
            Enumeration<String> headerNames = request.getHeaderNames();
            while (headerNames.hasMoreElements()) {
                String headerName = headerNames.nextElement();
                headers.put(headerName, request.getHeader(headerName));
            }
            return headers;
    
        }
    
        private Map<String, Object> getResponsetHeaders(ContentCachingResponseWrapper response) {
            Map<String, Object> headers = new HashMap<>();
            Collection<String> headerNames = response.getHeaderNames();
            for (String headerName : headerNames) {
                headers.put(headerName, response.getHeader(headerName));
            }
            return headers;
        }
    }
    
    @Bean
        public ServletRegistrationBean dispatcherRegistration() {
            return new ServletRegistrationBean(dispatcherServlet());
        }
        @Bean(name = DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
        public DispatcherServlet dispatcherServlet() {
            return new CustLoggingDispatcherServlet();
        }
    

    相关文章

      网友评论

          本文标题:Spring MVC利用过滤器打印日志

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