我正在尝试在Spring MVC应用程序中实现用于记录请求和响应的过滤器。
我使用以下代码:
@Component
public class LoggingFilter extends OncePerRequestFilter {
private static final Logger LOGGER = LoggerFactory.getLogger(LoggingFilter.class);
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper(request);
ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(response);
LOGGER.debug(REQUEST_MESSAGE_FORMAT, requestWrapper.getRequestURI(), requestWrapper.getMethod(), requestWrapper.getContentType(),
new ServletServerHttpRequest(requestWrapper).getHeaders(), IOUtils.toString(requestWrapper.getInputStream(), UTF_8));
filterChain.doFilter(requestWrapper, responseWrapper);
LOGGER.debug(RESPONSE_MESSAGE_FORMAT, responseWrapper.getStatus(), responseWrapper.getContentType(),
new ServletServerHttpResponse(responseWrapper).getHeaders(), IOUtils.toString(responseWrapper.getContentInputStream(), UTF_8));
}
}
字符串
因此,我的请求和响应按预期记录。以下是日志:
2016-10-08 19:10:11.212 DEBUG 11072 --- [qtp108982313-19] by.kolodyuk.logging.LoggingFilter
----------------------------
ID: 1
URI: /resources/1
Http-Method: GET
Content-Type: null
Headers: {User-Agent=[curl/7.41.0], Accept=[*/*], Host=[localhost:9015]}
Body:
--------------------------------------
2016-10-08 19:10:11.277 DEBUG 11072 --- [qtp108982313-19] by.kolodyuk.logging.LoggingFilter
----------------------------
ID: 1
Response-Code: 200
Content-Type: application/json;charset=UTF-8
Headers: {}
Body: {"id":"1"}
--------------------------------------
型
然而,返回的是空响应。下面是curl
的输出:
$ curl http://localhost:9015/resources/1 --verbose
* Trying ::1...
* Connected to localhost (::1) port 9015 (#0)
> GET /resources/1 HTTP/1.1
> User-Agent: curl/7.41.0
> Host: localhost:9015
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Sat, 08 Oct 2016 17:10:11 GMT
< Content-Type: application/json;charset=UTF-8
< Content-Length: 0
<
* Connection #0 to host localhost left intact
型
有什么想法吗?
3条答案
按热度按时间envsm3lx1#
经过几个小时的努力,我终于找到了解决办法。
简言之,应该在filter方法的最后调用
ContentCachingResponseWrapper.copyBodyToResponse()
。ContentCachingResponseWrapper
通过从响应输出流中阅读响应体来缓存响应体。因此,流变为空。要将响应写回输出流,应使用ContentCachingResponseWrapper.copyBodyToResponse()
。xfb7svmp2#
终于解决了这个问题。这里是完美的解决方案:
字符串
ut6juiuv3#
我喜欢使用的模式是将其分为2个过滤器:一个用于提取原始主体,另一个用于记录日志。感觉更SRP。
字符串
然后我们创建另一个过滤器来完成日志记录部分:
型
将它们分开的一个好处是其他类(例如Spring AOP拦截器或Spring控制器)也可以访问/使用HTTP主体。