记录@Controller请求Spring Boot

时间:2015-02-25 15:50:23

标签: spring spring-mvc logging spring-boot

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

我也尝试过以下解决方案,但它们对我没有用处:

  1. 实现过滤器 - 它需要缓存Stream并实现自己的Servlet Stream +它禁用使用ThreadContext的能力,以便在逻辑中的所有日志中识别请求。
  2. 拦截器 - 我试图添加拦截器这有两个问题首先扩展WebMvcAutoConfiguration.EnableWebMvcConfiguration或WebMvcConfigurationSupport导致Autoconfig不能再次工作以获取我需要在稍后阶段添加它的数据,因为在预处理它没有我已经知道了。我可以使用ThreadContext和@InitBinder,但它仍然让我遇到第一个问题而且不是很干净的解决方案。
  3. 如果有人对如何在@Valid中使用@Aspect有其他想法或好建议,那将非常有帮助。 谢谢

2 个答案:

答案 0 :(得分:2)

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

@ControllerAdvice
@Component
public class ControllerLogger {

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

答案 1 :(得分: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;
    }
}