【问题标题】:Logging @Controller Requests Spring Boot记录 @Controller 请求 Spring Boot
【发布时间】:2015-02-25 15:50:22
【问题描述】:

我正在尝试在 spring boot 中使用 spring @Aspect 记录我的 @Controller 请求(请求名称和数据)。 问题是,当使用 @Valid 且没有有效数据时,该方法不会执行,因为之前发生了参数解析。

我也尝试了以下解决方案,但它们对我不起作用:

  1. 实现过滤器 - 需要缓存 Stream 并实现自己的 Servlet Stream + 它禁用使用 ThreadContext 的能力,以便在逻辑中识别所有日志中的请求。
  2. 拦截器 - 我试图添加拦截器,这有两个问题首先扩展 WebMvcAutoConfiguration.EnableWebMvcConfiguration 或 WebMvcConfigurationSupport 导致自动配置无法工作,其次是为了获取我需要在稍后阶段添加它的数据,因为在预处理中它不是尚未阅读。我想我可以使用 ThreadContext 和 @InitBinder,但它仍然给我留下了第一个问题并且非常不干净的解决方案。

如果有人对如何将@Aspect 与@Valid 一起使用有其他想法或好的建议,那将非常有帮助。 谢谢

【问题讨论】:

  • 您想简单地记录请求吗?另外,您的意思是记录任何请求参数等?
  • 你可以从 spring boot 中添加执行器来获取请求的日志记录。您还可以添加CommonsRequestLoggingFilter 来记录所有传入请求。使用WebMvcConfigurationSupport 是错误的配置和拦截方式,您应该改用WebConfigurerAdapter
  • 我想同时记录请求路径和有效负载。
  • 执行器日志不打印请求 json + 我想使用自己的记录器并将请求注入所有逻辑日志。

标签: spring spring-mvc logging spring-boot


【解决方案1】:

我能够使用以下代码实现目标。

@ControllerAdvice
@Component
public class ControllerLogger {

    @InitBinder
    private void initBinder(WebDataBinder binder,WebRequest webRequest) {
        //log the request and data here .
    }
}

【讨论】:

    【解决方案2】:

    要记录请求和响应的标头和正文,您可以注册您的日志过滤器:

    package demo;
    
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.PrintStream;
    import java.io.PrintWriter;
    import java.util.Collections;
    import java.util.Scanner;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    import javax.servlet.DispatcherType;
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletOutputStream;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpServletResponseWrapper;
    import org.apache.commons.io.output.TeeOutputStream;
    import org.springframework.boot.context.embedded.FilterRegistrationBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.mock.web.DelegatingServletOutputStream;
    
    @Configuration
    public class HttpServerConfig {
    
        private final static Logger LOG = Logger.getLogger(HttpServerConfig.class.getName());
    
        @Bean
        public FilterRegistrationBean logFilterRegistration() {
            FilterRegistrationBean registration = new FilterRegistrationBean();
            registration.setDispatcherTypes(DispatcherType.REQUEST);
            registration.setFilter(new Filter() {
                @Override
                public void init(FilterConfig fc) throws ServletException {
                    LOG.info("Init LOG Request Filter");
                }
    
                private void logRequest(HttpServletRequest httpReq) throws IOException {
                    // log request headers
                    LOG.info("### Request Headers:");
                    for (String header : Collections.list(httpReq.getHeaderNames())) {
                        LOG.log(Level.INFO, "\t* {0}: {1}", new Object[]{header, httpReq.getHeader(header)});
                    }
                    // log request body
                    Scanner qs = new Scanner(httpReq.getInputStream()).useDelimiter("\\A");
                    String qb = qs.hasNext() ? qs.next() : "[empty body]";
                    LOG.log(Level.INFO, "### Request body: `{0}` ###", qb);
                }
    
                private void logResponse(HttpServletResponse httpResp, ByteArrayOutputStream baos) {
                    // log response headers
                    LOG.log(Level.INFO, "### Response [{0}] Headers:", httpResp.getStatus());
                    for (String header : httpResp.getHeaderNames()) {
                        LOG.log(Level.INFO, "\t* {0}: {1}", new Object[]{header, httpResp.getHeader(header)});
                    }
                    // log response body
                    LOG.log(Level.INFO, "### Response body: `{0}` ###", baos.toString());
                }
    
                @Override
                public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
                    logRequest((HttpServletRequest) req);
    
                    HttpServletResponse httpResp = (HttpServletResponse) resp;
                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    final PrintStream ps = new PrintStream(baos);
                    chain.doFilter(req, new HttpServletResponseWrapper(httpResp) {
                        @Override
                        public ServletOutputStream getOutputStream() throws IOException {
                            return new DelegatingServletOutputStream(new TeeOutputStream(super.getOutputStream(), ps));
                        }
    
                        @Override
                        public PrintWriter getWriter() throws IOException {
                            return new PrintWriter(new DelegatingServletOutputStream(new TeeOutputStream(super.getOutputStream(), ps)));
                        }
                    });
                    logResponse(httpResp, baos);
    
                }
    
                @Override
                public void destroy() {
                    LOG.info("Destroy LOG Request Filter");
                }
            });
            return registration;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2018-04-01
      • 2021-10-16
      • 2020-07-05
      • 2019-04-11
      • 2018-05-25
      • 2019-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多