• 【Spring Boot 使用Filter统一处理请求数据转换】


    背景知识

    Spring Boot Filter 使用场景

    1. 身份验证和授权
      场景描述: 在用户访问应用程序的敏感资源之前,需要验证用户的身份并授权用户访问特定的内容。
      实现方式: 使用Filter拦截请求,检查HTTP请求中的身份验证令牌(如JWT),并确定用户是否具有执行操作的权限。
    2. 日志记录和审计
      场景描述: 记录应用程序的请求和响应数据,用于监控、调试或遵守法规要求的审计。
      实现方式: 实现一个Filter来捕获请求的细节(如请求路径、查询参数、用户代理等)和响应的信息,然后将这些信息记录到日志系统中。
    3. 请求预处理
      场景描述: 在请求到达控制器之前,对请求进行预处理,例如设置请求上下文、执行数据格式转换。
      实现方式: 在Filter中对请求头或请求体进行必要的修改或添加额外的请求信息。
    4. 响应自定义
      场景描述: 对服务器的响应进行自定义处理,如添加额外的HTTP头部信息或对响应数据进行处理。
      实现方式: 在Filter中修改HttpServletResponse对象,添加如CORS头部、缓存控制等。
    5. 异常处理
      场景描述: 集中处理请求处理过程中抛出的异常,而不是在每个控制器中分别处理。
      实现方式: 实现一个Filter来捕获和处理请求处理链中发生的异常,返回一个统一的错误响应结构。
    6. 服务限流与安全
      场景描述: 限制请求的频率或数量,防止恶意攻击或服务过载。
      实现方式: 在Filter中实现限流逻辑,如令牌桶或漏桶算法,拒绝超出限制的请求。
    7. 跨域资源共享(CORS)
      场景描述: 允许或限制不同域之间的资源请求。
      实现方式: 通过Filter设置响应头部来控制CORS策略,例如Access-Control-Allow-Origin。
    8. 性能监控
      场景描述: 监控应用程序的性能,如请求的处理时间。
      实现方式: 在Filter中记录请求的开始和结束时间,计算处理时长,并可能将这些数据发送到性能监控系统。
      Spring Boot中的Filter为开发者提供了一个强大的工具,可以在不改变现有控制器逻辑的情况下,全局地处理HTTP请求和响应。它们通常用于处理跨多个请求和响应的横切关注点。

    请求预处理技术实现

    1. 创建自定义Filter类

    • 内容: 定义一个实现javax.servlet.Filter接口的类。在这个类中,你将覆写doFilter方法以便在请求到达Controller之前对数据进行预处理。

    示例代码

    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    import java.io.IOException;
    
    public class CustomRequestFilter implements Filter {
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            // Filter初始化时调用,可以用来配置一些资源
        }
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                throws IOException, ServletException {
            // 将ServletRequest转换为HttpServletRequest
            HttpServletRequest httpRequest = (HttpServletRequest) request;
    
            // 创建自定义的请求包装器
            CustomHttpServletRequestWrapper requestWrapper = new CustomHttpServletRequestWrapper(httpRequest);
    
            // 继续过滤器链,传入自定义包装器
            chain.doFilter(requestWrapper, response);
        }
    
        @Override
        public void destroy() {
            // Filter销毁时调用,可以用来释放资源
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    2. 创建自定义请求包装器

    • 内容: 定义一个继承自javax.servlet.http.HttpServletRequestWrapper的类,用于包装原始的HttpServletRequest,并对请求体中的数据进行转换。

    示例代码

    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletRequestWrapper;
    import java.io.BufferedReader;
    import java.io.ByteArrayInputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    
    public class CustomHttpServletRequestWrapper extends HttpServletRequestWrapper {
    
        private final byte[] requestBody;
    
        public CustomHttpServletRequestWrapper(HttpServletRequest request) {
            super(request);
            // 从原始请求中读取数据,并进行转换处理
            // 示例中仅读取数据,实际使用时可在此处进行转换
            requestBody = readBytesFromRequest(request);
        }
    
        @Override
        public BufferedReader getReader() throws IOException {
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(requestBody);
            return new BufferedReader(new InputStreamReader(byteArrayInputStream));
        }
    
        // 辅助方法:从HttpServletRequest中读取请求体数据为byte[]
        private byte[] readBytesFromRequest(HttpServletRequest request) {
            // 实现从原始请求中读取数据的逻辑
            // ...
            return new byte[0];
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    3. 注册Filter

    • 内容: 在Spring Boot中,你需要注册自定义的Filter,以便框架将其加入到过滤器链中。

    示例代码

    import org.springframework.boot.web.servlet.FilterRegistrationBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class FilterConfig {
    
        @Bean
        public FilterRegistrationBean<CustomRequestFilter> customFilter() {
            FilterRegistrationBean<CustomRequestFilter> registrationBean = new FilterRegistrationBean<>();
            registrationBean.setFilter(new CustomRequestFilter());
            registrationBean.addUrlPatterns("/api/*"); // 设置Filter的URL模式
            return registrationBean;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    使用这种方式,你可以在CustomHttpServletRequestWrapper中对所有传入的请求数据进行统一的预处理和转换,而不需要在每个Controller方法中单独处理。记得在实现读取和转换逻辑时处理好异常情况,并确保线程安全。

  • 相关阅读:
    从 JDK 8 到 JDK 18,Java 垃圾回收的十次进化
    【LeetCode】No.44. Wildcard Matching -- Java Version
    sequence如何接收来自driver的transaction
    Hive安装配置 - 本地模式
    雅思学习总结
    将conda虚拟环境添加到JNB
    网络安全(黑客)—自学
    【Nginx】彻底卸载Nginx以及安装Nginx的详细教程
    c++模板进阶
    大数据到底是好是坏?_光点科技
  • 原文地址:https://blog.csdn.net/jzg5845201314/article/details/136189882