# Spring Boot记录完整请求响应日志

3 min read
文章目录

前言

在排查错误时通常都需要通过日志来查看接口的请求参数和响应结果来定位和分析问题,一般我们都会使用一个Filter来做一些简单的请求日志记录,但是默认情况下 Spring Boot 是不支持记录请求体响应体的,因为请求体和响应体都是以流的方式对外提供调用,如果在Filter中把请求体和响应体读完了,就会使后续的应用读不到流数据导致异常。

实现思路

如果要记录请求体响应体的话,需要将流使用完之后缓存在内存中,以供后续使用,这个实现起来好像还挺复杂,需要包装HttpServletRequestHttpServletResponse两个类,然后对其中的IO接口做处理,大概代码如下:

@Bean
public OncePerRequestFilter contentCachingRequestFilter() {
// 配置一个Filter
return new OncePerRequestFilter() {
@Override
protected void doFilterInternal(final HttpServletRequest request, final HttpServletResponse response, final FilterChain filterChain) throws ServletException, IOException {
// 包装HttpServletRequest,把输入流缓存下来
CachingRequestWrapper wrappedRequest = new CachingRequestWrapper(request);
// 包装HttpServletResponse,把输出流缓存下来
CachingResponseWrapper wrappedResponse = new CachingResponseWrapper(response);
filterChain.doFilter(wrappedRequest, wrappedResponse);
LOGGER.info("http request:{}", wrappedRequest.getContent());
LOGGER.info("http response:{}", wrappedResponse.getContent());
}
};
}

使用 spring 内置包装类

有了上面一步的思路应该可以实现记录请求体响应体内容了,然而没必要,spring官方已经提供了两个类来做这件事,就是ContentCachingRequestWrapperContentCachingResponseWrapper,使用方法也差不多,代码示例:

@Bean
public OncePerRequestFilter contentCachingRequestFilter() {
// 配置一个Filter
return new OncePerRequestFilter() {
@Override
protected void doFilterInternal(final HttpServletRequest request, final HttpServletResponse response, final FilterChain filterChain) throws ServletException, IOException {
// 包装HttpServletRequest,把输入流缓存下来
ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(request);
// 包装HttpServletResponse,把输出流缓存下来
ContentCachingResponseWrapper wrappedResponse = new ContentCachingResponseWrapper(response);
filterChain.doFilter(wrappedRequest, wrappedResponse);
LOGGER.info("http request:{}", new String(wrappedRequest.getContentAsByteArray()));
LOGGER.info("http response:{}", new String(wrappedResponse.getContentAsByteArray()));
// 注意这一行代码一定要调用,不然无法返回响应体
wrappedResponse.copyBodyToResponse();
}
};
}

附录

本文完整代码放在github


More Posts

# Spring Boot整合feign

3 min read

feign 是一个非常好用的 http 客户端工具,它是一种声明式的 http 客户端,只需要声明好接口即可调用,不需要关注底层的请求细节。 通常情况下都是在 Spring Cloud 项目中使用,这里我把它单独整合到 Spring Boot 中,用来替代RestTemplate,提高项目可维护性。

阅读

评论区