Spring Web 中自带记录请求参数的轮子:AbstractRequestLoggingFilter,并提供了一个默认实现类:CommonsRequestLoggingFilter。
如果不想使用默认的 CommonsRequestLoggingFilter,可以新建一个类:HttpRequestLoggingFilter,继承 AbstractRequestLoggingFilter,重写其 beforeRequest() 和 afterRequest 抽象方法,并将该 Filter 注册为 Spring Bean 即可。
注意事项:
- 将 includeQueryString 和 includePayload 配置设置为 true,这两个配置默认为 false,否则只会记录请求 URI,不会记录请求参数。
- 使用 Ordered 接口或者 @Order 注解调整 HttpRequestLoggingFilter 在 FilterChain 中的顺序。不影响其他业务的前提下,可以将该 Filter 的顺序往前调。
- 设置合适的 maxPayloadLength,单位为字节。如果设置得太大,每次请求都会开辟 maxPayloadLength 字节的内存;如果设置得太小,request payload (body) 会被截断。
扩展:在 Controller 执行代码报错后,可以在 HttpRequestLoggingFilter 中打印请求参数,方便后续排查问题。
@Slf4j
public class HttpRequestLoggingFilter extends AbstractRequestLoggingFilter implements Ordered {
private int order;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
boolean isFirstRequest = !isAsyncDispatch(request);
HttpServletRequest requestToUse = request;
if (isIncludePayload() && isFirstRequest && !(request instanceof ContentCachingRequestWrapper)) {
requestToUse = new ContentCachingRequestWrapper(request, getMaxPayloadLength());
}
boolean shouldLog = shouldLog(requestToUse);
if (shouldLog && isFirstRequest) {
beforeRequest(requestToUse, createMessage(requestToUse, "", ""));
}
try {
filterChain.doFilter(requestToUse, response);
} finally {
Throwable exception = fetchException(request);
shouldLog = shouldLog || exception != null;
if (shouldLog && !isAsyncStarted(requestToUse)) {
String message = createMessage(requestToUse, "", "");
if (exception != null) {
log.info("Error request message: " + message);
} else {
log.debug(message);
}
}
}
}
@Override
protected void beforeRequest(HttpServletRequest request, String message) {
log.debug(message);
}
@Override
protected void afterRequest(HttpServletRequest request, String message) {
}
@Override
protected boolean shouldLog(HttpServletRequest request) {
return log.isDebugEnabled();
}
@Override
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
private Throwable fetchException(HttpServletRequest request) {
Throwable exception = (Throwable) request.getAttribute(ErrorAttributes.ERROR_ATTRIBUTE);
if (exception == null) {
exception = (Throwable) request.getAttribute(DispatcherServlet.EXCEPTION_ATTRIBUTE);
}
return exception;
}
}