首页 > 解决方案 > Spring CommonsRequestLoggingFilter 解决方法来记录请求/响应负载

问题描述

我有一个使用 JSON 作为请求/回复格式的 RESTful API,我想记录客户端发送的有效负载和 API 发送的响应。

(我的 pom.xml 中定义的 Spring Boot 版本是 2.2.1.RELEASE)

Spring 提供了一个非常方便的过滤器来做到这一点:

@Bean
public CommonsRequestLoggingFilter logFilter() {
  CommonsRequestLoggingFilter filter = new CommonsRequestLoggingFilter();
  filter.setIncludeQueryString(true);
  filter.setIncludePayload(true);
  filter.setMaxPayloadLength(10000);
  filter.setIncludeHeaders(false);

  return filter;
}

但它不起作用:没有记录有效负载!

如果我深入研究扩展类中有趣的部分代码AbstractRequestLoggingFilter.doFilterInternal

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
    throws ServletException, IOException {

  [...]

  if (isIncludePayload() && isFirstRequest && !(request instanceof ContentCachingRequestWrapper)) {
    requestToUse = new ContentCachingRequestWrapper(request, getMaxPayloadLength());
  }

  [...]
}

它用于ContentCachingRequestWrapper解决有效负载是 Stream 的事实,因此只能使用一次。

该构造初始化一个 ByteArrayOutputStream 来缓存有效负载:

public ContentCachingRequestWrapper(HttpServletRequest request, int contentCacheLimit) {
  super(request);
  this.cachedContent = new ByteArrayOutputStream(contentCacheLimit);
  this.contentCacheLimit = contentCacheLimit;
}

但它不会将流的内容复制到 var 中,cachedContent除非您调用方法writeRequestParametersToCachedContentgetParameterValues例如通过),但这种情况从来都不是这样,因此流保持为 0。

问题:

  1. 为什么流没有在构造函数中复制?

  2. 是否有一种解决方法可以不因为ContentCachingRequestWrapper有问题而重新实现所有内容?

谢谢

标签: javaspringspring-mvc

解决方案


推荐阅读