springboot filter实现请求响应全链路拦截

2025-04-10 04:50

本文主要是介绍springboot filter实现请求响应全链路拦截,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《springbootfilter实现请求响应全链路拦截》这篇文章主要为大家详细介绍了SpringBoot如何结合Filter同时拦截请求和响应,从而实现​​日志采集自动化,感兴趣的小伙伴可以跟随小...

一、为什么你需要这个过滤器?​

日志痛点:

  • 请求参数散落在各处?
  • 响应数据无法统一记录?
  • 日志与业务代码严重耦合?

​​解决方案​​: 一个Filter同时拦截请求和响应,实现​​日志采集自动化​​!

​​二、核心实现:一个Filter搞定双向数据流​​

过滤器设计亮点​​

  • 请求参数捕获​​:GET/POST参数统一解析
  • 响应结果截取​​:支持jsON/XML等文本响应
  • 零代码侵入​​:不修改业务代码即可植入监控
  • ​​JDK1.8完美兼容​​:无任何新特性依赖

​​三、完整代码实现​​

​​1. 过编程滤器核心代码(可直接复制)​​

import org.springframework.web.filter.OncePerRequestFilter;
import Javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class RequestResponseLogFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, 
                                    HttpServletResponse response, 
                                    FilterChain filterChain)
            throws ServletException, IOException {
        
        // 包装请求响应对象
        ContentCachingRequestWrapper wrappedRequest = 
            new ContentCachingRequestWrapper(request);
        ContentCachingResponseWrapper wrappedResponse = 
            new ContentCachingResponseWrapper(response);

        try {
            // 执行后续过滤器链
            编程filterChain.doFilter(wrappedRequest, wrappedResponse);
            
            // 记录日志(核心逻辑)
            logRequest(wrappedRequest);
            logResponse(wrappedResponse);
            
        } finally {
            // 必须执行响应回写
            wrappedResponse.copyBodyToResponse();
        }
    }

    // 请求日志方法
    private void logRequest(ContentCachingRequestWrapper request) {
        String method = request.getMethod();
        String url = request.getRequestURL().toString();
        String params = getRequestParams(request);
        
        System.out.printf("[请求] %s %s | 参数android=%s%n", method, url, params);
    }

    // 响应日志方法
    private void logResponse(ContentCachingResponseWrapper response) throws IOException {
        int status = response.getStatus();
        String body = getResponseBody(response);
        
        System.out.androidprintf("[响应] 状态码=%d | 内容=%s%n", status, body);
    }

    
    // 获取请求参数工具方法
    private String getRequestParams(ContentCachingRequestWrapper request) {
   编程     try {
            if ("GET".equalsIgnoreCase(request.getMethod())) {
                return request.getQueryString();
            } else {
                byte[] body = request.getContentAsByteArray();
                return new String(body, request.getCharacterEncoding());
            }
        } catch (Exception e) {
            return "[参数解析失败]";
        }
    }

    // 获取响应内容工具方法
    private String getResponseBody(ContentCachingResponseWrapper response) throws IOException {
        byte[] content = response.getContentAsByteArray();
        return new String(content, response.getCharacterEncoding());
    }

    @Override
    public void init(FilterConfig filterConfig) {}

    @Override
    public void destroy() {}
}

四、过滤器添加三步走​​

​​1. 添加依赖(Maven配置)​​

<!-- 核心包装类 -->
<dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-catalina</artifactId>
    <version>9.0.65</version>
</dependency>

​​2. web.xml配置​​(传统项目)

<filter>
    <filter-name>RequestResponseLogFilter</filter-name>
    <filter-class>com.example.RequestResponseLogFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>RequestResponseLogFilter</filter-name>
    <url-pattern>/*</url-pattern> <!-- 拦截所有请求 -->
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>

​​​​3. Spring Boot集成​​(新项目推荐)

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

五、运行效果演示​​

[REQUEST] POST http://api/user/login | 参数=username=admin&password=123456 | 时间=Wed Oct 05 14:30:00 CST 2023
[RESPONSE] 状态码=200 | 响应内容={"code":0,"msg":"登录成功"} | 耗时=120ms

六、必须注意的6大事项​​

1.内存溢出风险​​

拦截大文件上传时(>1MB)会占用大量内存

解决方案:限制缓存大小

// 在构造方法中设置最大缓存
new ContentCachingRequestWrapper(request, 1024 * 1024); // 1MB

2.​​编码兼容性问题​​

请求参数乱码常因缺少编码设置导致

强制设置编码(在Filter头部添加)

request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");

3.​​响应流二次读取​​

原始响应流只能读取一次,必须使用包装类

错误写法:直接使用原始response.getWriter()

4.敏感信息泄露​​

密码等字段需过滤(正则替换示例)

params.replaceAll("password=\\w+", "password=​**​*");

5.性能损耗控制​​

高并发场景建议异步记录日志

CompletableFuture.runAsync(() -> log.info(logContent));

6.HTTPS支持​​

确保Tomcat配置正确:

<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
           SSLEnabled="true" scheme="https" secure="true"/>

七、进阶玩法​​

组合使用​​:

搭配Spring AOP实现方法级日志

结合Redis实现请求限流

数据分析​​:

-- 日志分析SQL示例
SELECT 
    request_uri, 
    COUNT(*) as total,
    AVG(response_time) as avg_time 
FROM Access_log 
WHERE status >= 500 
GROUP BY request_uri;

总结​​

一个优秀的Filter就像「数字监控摄像头」,默默记录系统运行轨迹。通过本文的方案,你可以:

  • 统一管理所有请求响应日志
  • 零成本实现全链路追踪
  • 灵活扩展监控维度

到此这篇关于springboot filter实现请求响应全链路拦截的文章就介绍到这了,更多相关springboot filter请求拦截内容请搜索China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程China编程(www.chinasem.cn)!

这篇关于springboot filter实现请求响应全链路拦截的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1154155

相关文章

idea maven编译报错Java heap space的解决方法

《ideamaven编译报错Javaheapspace的解决方法》这篇文章主要为大家详细介绍了ideamaven编译报错Javaheapspace的相关解决方法,文中的示例代码讲解详细,感兴趣的... 目录1.增加 Maven 编译的堆内存2. 增加 IntelliJ IDEA 的堆内存3. 优化 Mave

Java String字符串的常用使用方法

《JavaString字符串的常用使用方法》String是JDK提供的一个类,是引用类型,并不是基本的数据类型,String用于字符串操作,在之前学习c语言的时候,对于一些字符串,会初始化字符数组表... 目录一、什么是String二、如何定义一个String1. 用双引号定义2. 通过构造函数定义三、St

SpringBoot利用@Validated注解优雅实现参数校验

《SpringBoot利用@Validated注解优雅实现参数校验》在开发Web应用时,用户输入的合法性校验是保障系统稳定性的基础,​SpringBoot的@Validated注解提供了一种更优雅的解... 目录​一、为什么需要参数校验二、Validated 的核心用法​1. 基础校验2. php分组校验3

Python实现AVIF图片与其他图片格式间的批量转换

《Python实现AVIF图片与其他图片格式间的批量转换》这篇文章主要为大家详细介绍了如何使用Pillow库实现AVIF与其他格式的相互转换,即将AVIF转换为常见的格式,比如JPG或PNG,需要的小... 目录环境配置1.将单个 AVIF 图片转换为 JPG 和 PNG2.批量转换目录下所有 AVIF 图

Java Predicate接口定义详解

《JavaPredicate接口定义详解》Predicate是Java中的一个函数式接口,它代表一个判断逻辑,接收一个输入参数,返回一个布尔值,:本文主要介绍JavaPredicate接口的定义... 目录Java Predicate接口Java lamda表达式 Predicate<T>、BiFuncti

Pydantic中model_validator的实现

《Pydantic中model_validator的实现》本文主要介绍了Pydantic中model_validator的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价... 目录引言基础知识创建 Pydantic 模型使用 model_validator 装饰器高级用法mo

Spring Security基于数据库的ABAC属性权限模型实战开发教程

《SpringSecurity基于数据库的ABAC属性权限模型实战开发教程》:本文主要介绍SpringSecurity基于数据库的ABAC属性权限模型实战开发教程,本文给大家介绍的非常详细,对大... 目录1. 前言2. 权限决策依据RBACABAC综合对比3. 数据库表结构说明4. 实战开始5. MyBA

AJAX请求上传下载进度监控实现方式

《AJAX请求上传下载进度监控实现方式》在日常Web开发中,AJAX(AsynchronousJavaScriptandXML)被广泛用于异步请求数据,而无需刷新整个页面,:本文主要介绍AJAX请... 目录1. 前言2. 基于XMLHttpRequest的进度监控2.1 基础版文件上传监控2.2 增强版多

Spring Security方法级安全控制@PreAuthorize注解的灵活运用小结

《SpringSecurity方法级安全控制@PreAuthorize注解的灵活运用小结》本文将带着大家讲解@PreAuthorize注解的核心原理、SpEL表达式机制,并通过的示例代码演示如... 目录1. 前言2. @PreAuthorize 注解简介3. @PreAuthorize 核心原理解析拦截与

一文详解JavaScript中的fetch方法

《一文详解JavaScript中的fetch方法》fetch函数是一个用于在JavaScript中执行HTTP请求的现代API,它提供了一种更简洁、更强大的方式来处理网络请求,:本文主要介绍Jav... 目录前言什么是 fetch 方法基本语法简单的 GET 请求示例代码解释发送 POST 请求示例代码解释