Spring Boot 框架下的过滤器

打印 上一主题 下一主题

主题 853|帖子 853|积分 2559

1. 过滤器的基础概念

1.1 什么是过滤器?



  • Servlet 规范的一部门,定义在 javax.servlet.Filter 接口中。
  • 在 HTTP 请求到达目标资源(如 Controller)之前或相应返回客户端之前,拦截并对其进行预处理或后处理。
1.2 过滤器的焦点方法

javax.servlet.Filter 接口定义了以下三个方法:


  • init(FilterConfig filterConfig)

    • 在过滤器初始化时调用,通常用于加载资源或初始化设置。

  • doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

    • 焦点方法,用于拦截和处理请求或相应。
    • 调用 chain.doFilter(request, response) 体现将请求传递给下一个过滤器或目标资源。

  • destroy()

    • 在过滤器烧毁时调用,用于释放资源。


2. Spring Boot 项目中如何使用过滤器

在 Spring Boot 中,可以通过以下两种方式注册过滤器:
2.1 自动注册过滤器

通过 @Component 注解将过滤器注册为 Spring Bean,Spring Boot 会自动加载并将其添加到过滤器链中。
示例代码:
  1. import org.springframework.stereotype.Component;
  2. import javax.servlet.*;
  3. import javax.servlet.http.HttpServletRequest;
  4. import java.io.IOException;
  5. @Component
  6. public class MyFilter implements Filter {
  7.     @Override
  8.     public void init(FilterConfig filterConfig) {
  9.         System.out.println("过滤器初始化");
  10.     }
  11.     @Override
  12.     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
  13.             throws IOException, ServletException {
  14.         HttpServletRequest httpRequest = (HttpServletRequest) request;
  15.         System.out.println("请求路径:" + httpRequest.getRequestURI());
  16.         chain.doFilter(request, response); // 继续传递请求
  17.     }
  18.     @Override
  19.     public void destroy() {
  20.         System.out.println("过滤器销毁");
  21.     }
  22. }
复制代码
解释:


  • @Component

    • 将该类注册为 Spring Bean,Spring Boot 自动将其作为过滤器加载。
    • 默认拦截所有请求(/*)。

  • doFilter 方法

    • HttpServletRequest 用于获取请求的详细信息(如路径、参数)。
    • chain.doFilter 体现继续将请求传递给下一个过滤器或目标资源。


2.2 手动注册过滤器

通过 FilterRegistrationBean 手动注册过滤器,可以指定 URL 匹配规则和执行顺序。
示例代码:
  1. import org.springframework.boot.web.servlet.FilterRegistrationBean;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.context.annotation.Configuration;
  4. @Configuration
  5. public class FilterConfig {
  6.     @Bean
  7.     public FilterRegistrationBean<MyFilter> registerMyFilter() {
  8.         FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>();
  9.         registrationBean.setFilter(new MyFilter()); // 注册过滤器
  10.         registrationBean.addUrlPatterns("/api/*");  // 仅拦截 /api/ 开头的请求
  11.         registrationBean.setOrder(1);
  12.               // 设置执行顺序,值越小优先级越高
  13.         return registrationBean;
  14.     }
  15. }
复制代码
解释:


  • FilterRegistrationBean

    • 用于手动注册过滤器,提供灵活的设置选项。

  • addUrlPatterns

    • 定义过滤器的作用范围,好比这里仅拦截 /api/* 的请求。

  • setOrder

    • 定义过滤器的执行顺序,值越小优先级越高。


3. 使用 Spring 提供的扩展过滤器

Spring 提供了一个扩展类 OncePerRequestFilter,它是对标准过滤器的加强,用于确保在一次请求中只执行一次过滤逻辑(防止重复过滤)。
示例代码:
  1. import org.springframework.web.filter.OncePerRequestFilter;
  2. import javax.servlet.FilterChain;
  3. import javax.servlet.ServletException;
  4. import javax.servlet.http.HttpServletRequest;
  5. import javax.servlet.http.HttpServletResponse;
  6. import java.io.IOException;
  7. public class MyOncePerRequestFilter extends OncePerRequestFilter {
  8.     @Override
  9.     protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
  10.             throws ServletException, IOException {
  11.         System.out.println("请求路径:" + request.getRequestURI());
  12.         filterChain.doFilter(request, response); // 继续传递请求
  13.     }
  14. }
复制代码
注册方式: 可以通过 @Component 或 FilterRegistrationBean 注册,方式与标准过滤器一致。
解释:


  • OncePerRequestFilter

    • 确保在一次请求中只执行一次过滤器逻辑。

  • doFilterInternal

    • 处理请求的焦点方法,逻辑和标准 Filter 的 doFilter 类似。

4. 过滤器的执行顺序 

在 Spring Boot 中,多个过滤器的执行顺序由以下规则决定: 
4.1 自动注册的过滤器

示例:
  1. @Component
  2. @Order(1) // 优先级最高
  3. public class FirstFilter implements Filter {
  4.     ...
  5. }
  6. @Component
  7. @Order(2) // 优先级次之
  8. public class SecondFilter implements Filter {
  9.     ...
  10. }
复制代码


  • 默认按加载顺序执行。
  • 可以通过 @Order 注解设置优先级(值越小优先级越高)。
4.2 手动注册的过滤器

示例:
  1. registrationBean.setOrder(1);
复制代码


  • 使用 FilterRegistrationBean#setOrder 方法设置优先级。

5. 常见过滤器应用场景



  • 用户认证和授权

    • 检查请求头中是否携带有效的 Token。
    • 验证用户权限。

  • 请求日志记录
    示例:
    1. @Override
    2. public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
    3.         throws IOException, ServletException {
    4.     HttpServletRequest httpRequest = (HttpServletRequest) request;
    5.     System.out.println("请求路径:" + httpRequest.getRequestURI());
    6.     chain.doFilter(request, response);
    7. }
    复制代码

    • 记录请求的详细信息(如路径、IP 地址、参数)。

  • 跨域处理
    示例:
    1. @Override
    2. public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
    3.         throws IOException, ServletException {
    4.     HttpServletResponse httpResponse = (HttpServletResponse) response;
    5.     httpResponse.setHeader("Access-Control-Allow-Origin", "*");
    6.     httpResponse.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
    7.     chain.doFilter(request, response);
    8. }
    复制代码

    • 在相应头中添加跨域支持信息。

  • 加解密

    • 对请求体进行解密,对相应体进行加密。


6. 注意事项



  • 避免业务逻辑的复杂化

    • 过滤器应专注于全局性逻辑(如日志、认证),复杂的业务逻辑应放在 Service 层处理。

  • 避免重复过滤

    • 使用 OncePerRequestFilter 防止在同一个请求中多次执行过滤器逻辑。

  • 路径匹配规则

    • 通过 addUrlPatterns 或在 doFilter 中手动判定,确保过滤器只作用于必要的路径。

  • 资源拦截控制

    • 清除静态资源(如 .css, .js)的拦截,避免对静态资源应用不必要的逻辑。

7.一个请求在整个Spring Boot Web 应用中的处理流程

以一个常见的 Spring Boot Web 应用为例,处理一个请求大概会经过多个环节:
  1. [客户端请求]
  2.    ↓
  3. [Filter1 -> Filter2 -> ... -> FilterN] // 过滤器链
  4.    ↓
  5. [Servlet Container] // DispatcherServlet
  6.    ↓
  7. [Spring MVC 拦截器(Interceptor)] // 可选
  8.    ↓
  9. [Controller / RestController 方法]
  10.    ↓
  11. [视图解析或返回响应]
  12.    ↑
  13. [FilterN -> ... -> Filter1] // 响应回程,也可以在过滤器里做后置处理
  14.    ↑
  15. [客户端接收响应]
复制代码


  • 过滤器链先于 Spring MVC 的拦截器执行。
  • 在 Filter.doFilter 中,假如调用 chain.doFilter(request, response),请求才会进入下一个过滤器或目标 Servlet。
  • 相应返回时,也会逆向经过过滤器链,为我们提供后置处理的时机。
 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

小秦哥

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表