我试图登录我@Controller
使用弹簧请求(包括请求名称和数据) @Aspect
春天开机。 问题是,当使用@Valid
没有有效数据的方法不执行,因为参数解决所发生之前。
我也曾尝试以下解决方案,但他们并没有为我工作:
- 执行滤镜 - 它需要缓存流和实现自己的Servlet +流禁用它,以确定在逻辑所有日志请求使用ThreadContext的abbility。
- 拦截器 - 我尝试添加拦截这有两个问题,第一个扩展WebMvcAutoConfiguration.EnableWebMvcConfiguration或WebMvcConfigurationSupport导致自动配置不是为了得到我需要将其添加在以后的阶段,因为在预处理它尚未readed数据其次工作。我可以使用ThreadContext和
@InitBinder
的,我猜,但它仍然留给我的第一个问题,非常不干净的解决方案。
如果任何人有关于如何使用@Valid使用@Aspect其他想法或好的建议这将是非常有益的。 谢谢
我可以用下面的代码来获得我的目标。
@ControllerAdvice
@Component
public class ControllerLogger {
@InitBinder
private void initBinder(WebDataBinder binder,WebRequest webRequest) {
//log the request and data here .
}
}
要登录请求和响应头和身体,你可以注册你的日志过滤器:
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;
}
}