首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >使用springboot自带的请求、响应缓存实现请求响应打印

使用springboot自带的请求、响应缓存实现请求响应打印

原创
作者头像
shigen
修改2024-12-24 14:25:19
修改2024-12-24 14:25:19
6501
举报

在日常的开发中,日志往往是我们用来排查问题的重要依据,请求和响应也是其中重要的组成部分。也看到了很多业务系统记录日志的方式:

  1. 统一一个 Template 模版,模版中执行方法,在执行前后分别记录入参和执行结果
  2. 自定义注解,记录接口入参、出参

今天带来的方式是基于 springboot 自带的请求缓存 ContentCachingRequestWrapper 和响应缓存 ContentCachingResponseWrapper 实现日志的详细记录,避免重复造轮子。

新建请求过滤器

代码语言:java
复制
@Slf4j
public class ContentCachingFilter extends OncePerRequestFilter {

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

        // 包装请求和响应
        ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper(request);
        ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(response);

        try {
            // 执行过滤器链
            filterChain.doFilter(requestWrapper, responseWrapper);
        } finally {
            // 从包装器中获取缓存的内容
            String method = request.getMethod();

            String requestString;
            if (StringUtils.equals(method, "GET")) {
                requestString = JSON.toJSONString(requestWrapper.getParameterMap());
            } else {
                requestString = new String(requestWrapper.getContentAsByteArray(),
                    request.getCharacterEncoding());
            }

            byte[] responseBody = responseWrapper.getContentAsByteArray();
            String responseBodyString = new String(responseBody, response.getCharacterEncoding());
            log.info("RequestUri:{}, Method:{}, Request: {}, Response: {}", request.getRequestURI(),
                method, requestString, responseBodyString);
            // 确保响应被写回客户
            responseWrapper.copyBodyToResponse();
        }
    }
}

注册过滤器

代码语言:java
复制
@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean<ContentCachingFilter> loggingFilter() {
        FilterRegistrationBean<ContentCachingFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new ContentCachingFilter());
        registrationBean.addUrlPatterns("/*");
        return registrationBean;
    }
}

最终的实现效果如下:

  • GET 请求带参数/不带参数
代码语言:java
复制
RequestUri:/api/test, Method:GET, Request: {"name":["AA"]}, Response: 47d39ffa-1b17-4aef-bbc2-0673b89883d0-AA
RequestUri:/api/test, Method:GET, Request: {}, Response: 59fe2ab5-4cac-4e1f-9e1b-88c95f7ba952-null
  • POST 请求
代码语言:java
复制
RequestUri:/script/execute, Method:POST, Request: {
    "scriptContent": "xxxxx"
}, Response: {"success":false,"errorCode":"SYSTEM_ERROR","errorMsg":"xxx","needRetry":false}

可以看到请求响应都被完整的记录了。这种实现就是足够的简单、高效,对于业务代码的侵入性小。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 新建请求过滤器
  • 注册过滤器
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档