记录@Controller请求Spring Boot [英] Logging @Controller Requests Spring Boot

查看:106
本文介绍了记录@Controller请求Spring Boot的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to log my @Controller request (both request name and data ) using spring @Aspect in spring boot . The issue is that when using @Valid with no valid data the method is not execute since the argument resolving happened before.

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

I have also tried the following solutions ,but they didn't worked for me:

  1. 实现过滤器-需要缓存流并实现自己的Servlet流+禁用使用ThreadContext的能力,以便在逻辑中的所有日志中标识请求.
  2. Interceptor-我试图添加Interceptor,这有两个问题,首先是扩展了WebMvcAutoConfiguration.EnableWebMvcConfiguration或WebMvcConfigurationSupport,导致自动配置第二次无法工作以获取数据,我需要在以后的阶段中添加它,因为在预处理中没有我仍然可以使用ThreadContext和@InitBinder,但是我仍然会遇到第一个问题,不是很干净的解决方案.
  1. Implementing Filter - It required to cache the Stream and Implement your own Servlet Stream + It disable the abbility to use ThreadContext in order to identify the request in all logs in logic.
  2. Interceptor - I was trying to add Interceptor this has two problems first extends WebMvcAutoConfiguration.EnableWebMvcConfiguration or WebMvcConfigurationSupport cause the Autoconfig not to work secondly in order to get the data I need to add it in a later phase since in pre handle it not readed yet .I can use ThreadContext and @InitBinder for that I guess but it still leave me with the first problem and very not clean solution.

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

If anyone has other idea or good suggestion on how to use @Aspect with @Valid it will be very helpful . Thanks

推荐答案

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

To log request and response headers and body you can register your log filter:

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;
    }
}

这篇关于记录@Controller请求Spring Boot的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆