Spring Boot过滤器的那些事:从配置到应用场景

开发 前端
过滤器由 Servlet 提供,基于函数回调实现链式对网络请求和响应的拦截与修改。由于基于 Servlet,几乎可以拦截 Web 服务器管理的所有资源(JSP、图片文件、HTML 文件、CSS 文件等)。

1. 什么是过滤器

过滤器是 Web 三大组件之一,也是项目中常用的工具。本文主要介绍过滤器的概念及在 Spring Boot 中的常用使用方法。

过滤器由 Servlet 提供,基于函数回调实现链式对网络请求和响应的拦截与修改。由于基于 Servlet,几乎可以拦截 Web 服务器管理的所有资源(JSP、图片文件、HTML 文件、CSS 文件等)。

定义过滤器需要实现javax.servlet.Filter接口。过滤器不是 Servlet,无法直接生成对客户端的响应,只能拦截已有请求并预处理不需要或不一致的信息资源。

2. 过滤器流程原理

图片

在 Web 应用中,可以开发编写多个过滤器,这些过滤器组合称为过滤器链。用户发起请求后,请求信息会按过滤器链中过滤器的顺序依次进入每个过滤器。经过每层过滤器时,需通过过滤器的校验逻辑并放行才能进入下一层过滤器,直至服务器获取资源。

服务器成功获取资源并响应过滤器后,会按反向顺序经过层层过滤器,最终响应用户。

3. 过滤器分类

Servlet 2.5:

  • REQUEST: 用户直接访问页面时,WEB 容器会调用过滤器链。
  • FORWARD: 通过 RequestDispatcher 的 forward 访问目标资源时调用此过滤器。
  • INCLUDE: 通过 RequestDispatcher 的 include 方法调用目标资源时调用。
  • ERROR: 通过声明式异常处理机制调用目标资源时调用过滤器链。

Servlet 3.0:

  • ASYNC: 支持异步处理。

4. 过滤器中需要实现的方法

  • public void doFilter(ServletRequest, ServletResponse, FilterChain): 实现实际过滤操作。当客户端请求方法与过滤器设置的 URL 匹配时,Servlet 容器会先调用过滤器的 doFilter 方法。FilterChain 用于访问后续过滤器。
  • public void init(FilterConfig filterConfig): Web 应用启动时,Web 服务器创建过滤器实例对象并调用其 init 方法完成对象初始化(过滤器对象仅创建一次,init 方法仅执行一次)。开发者可通过 init 方法参数执行读取配置文件等初始化操作。
  • public void destroy(): Servlet 容器销毁过滤器实例前调用此方法。用于释放过滤器占用的资源。

5. 创建过滤器的两种方式

方法一:注解方式

创建步骤:

  • 实现Filter接口,添加@WebFilter@Order注解配置过滤器:
@Order(1)
@WebFilter(filterName = "myFilter", urlPatterns = {"*"})
public class MyCustomFilter1 implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {}

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) {}

    @Override
    public void destroy() {}
}
  • 在启动类添加@ServletComponentScan注解:
@SpringBootApplication
@ServletComponentScan
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

方法二:将过滤器注册为 Bean

创建步骤:

  • 创建实现 Filter 接口的过滤器类:
public class MyCustomFilter2 implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {}

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain){}

    @Override
    public void destroy() {}
}
  • 创建过滤器配置类,注册过滤器:
@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean customFilter(){
        FilterRegistrationBean<MyCustomFilter1> filterBean = new FilterRegistrationBean<>();
        filterBean.setFilter(new MyCustomFilter1());
        filterBean.setName("FilterController");
        filterBean.addUrlPatterns("/*");
        return filterBean;
    }
}

6. 注解方式的参数说明与使用示例

(1)参数说明

@WebFilter可配置多个参数,部分参数说明如下:

参数名称

参数类型

参数描述

filterName

String

过滤器的名称

displayName

String

要显示的过滤器名称

asyncSupported

boolean

设置过滤器是否支持异步模式

initParams

WebInitParam[]

你可以在初始化时配置一些参数

servletNames

String[]

设置要过滤的 Servlets

urlPatterns

String[]

指定要拦截的路径

value

String[]

urlPatterns 属性与 urlPatterns 属性的作用相同,两者都指定要拦截的路径

dispatcherTypes

DispatcherType[]

设置过滤器过滤的请求类型,支持以下属性:ASYNC, ERROR, FORWARD, INCLUDE, REQUEST(默认情况下,它过滤所有类型的请求)

(2)使用示例

  • 创建 Controller 类
@RestController
publicclass TestController {

    @GetMapping("/a/hello")
    public String hello1(){
        return"hello world! a";
    }

    @GetMapping("/b/hello")
    public String hello2(){
        return"hello world! b";
    }

    @GetMapping("/c/hello")
    public String hello3(){
        return"hello world! c";
    }
}
  • 创建过滤器类
@Order(1)
@WebFilter(filterName = "myFilter", urlPatterns = {"/a/*", "/b/*"}, description = "自定义过滤器")
publicclass MyCustomFilter2 implements Filter {

    @Override
    public void init(FilterConfig filterConfig) {
        System.out.println("过滤器初始化");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
        throws IOException, ServletException {
        System.out.println("请求处理前...");
        chain.doFilter(request, response);  // 放行请求
        System.out.println("请求处理后...");
    }

    @Override
    public void destroy() {
        System.err.println("过滤器销毁");
    }
}
  • 创建启动类
@SpringBootApplication
@ServletComponentScan
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

7. 过滤器注册 Bean 方式的参数说明与使用示例

(1)方法参数说明

方法名称

方法描述

setName()

设置过滤器的名称。

setFilter()

设置要注册的过滤器。

setOrder()

设置过滤器的顺序位置。

setAsyncSupported()

设置过滤器是否支持异步模式。

addUrlPatterns()

添加拦截的路径。

setUrlPatterns()

设置拦截的路径。

addServletNames()

添加过滤器的 servlet 名称。

setServletNames()

设置注册过滤器的 servlet 名称。

setInitParameters()

设置初始化参数。

addInitParameter()

添加初始化参数。

setMatchAfter()

设置是否在 Servlet 上下文中声明的任何过滤器映射之后匹配过滤器映射。

setDispatcherTypes()

设置过滤器过滤的请求类型。支持的属性如下:ASYNC, ERROR, FORWARD, INCLUDE, REQUEST(默认情况下,它过滤所有类型的请求)。

(2)使用示例

  • 创建 Controller 类
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
publicclass TestController {

    @GetMapping("/a/hello")
    public String hello1(){
        return"hello world! a";
    }

    @GetMapping("/b/hello")
    public String hello2(){
        return"hello world! b";
    }

    @GetMapping("/c/hello")
    public String hello3(){
        return"hello world! c";
    }

}
  • 创建过滤器类
public class MyCustomFilter1 implements Filter {

    @Override
    public void init(FilterConfig filterConfig) {
        System.out.println("过滤器初始化");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
        throws IOException, ServletException {
        System.out.println("请求处理前...");
        chain.doFilter(request, response);  // 放行请求
        System.out.println("请求处理后...");
    }

    @Override
    public void destroy() {
        System.err.println("过滤器销毁");
    }
}
  • 创建过滤器配置类
@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean customFilter(){
        FilterRegistrationBean<MyCustomFilter1> filterBean = new FilterRegistrationBean<>();
        filterBean.setFilter(new MyCustomFilter1());
        filterBean.setName("FilterController");
        filterBean.addUrlPatterns("/c/*","/b/*");
        return filterBean;
    }
}
  • 创建启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;

@SpringBootApplication
@ServletComponentScan
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

8. 过滤器使用场景

(1)日志记录

过滤器可记录请求和响应的关键信息,便于排查问题和分析系统运行状态。例如记录请求 URL、参数、响应状态码等。

(2)数据统计

用于采集各类数据指标,如统计请求次数、响应时间分布等,为系统优化提供依据。

(3)数据格式转换

不同系统交互时,过滤器可转换数据格式,例如将 JSON 转为 XML。

(4)为数据设置默认值

检查输入数据,为缺失字段设置默认值,保证数据完整性。

(5)权限认证、黑白名单

实现用户权限认证和访问控制,限制特定 IP 或用户的访问。

(6)数据加解密、签名验证

对敏感数据加解密以保证安全,同时进行签名验证确保数据完整性。

责任编辑:武晓燕 来源: 程序猿技术充电站
相关推荐

2020-10-29 07:16:26

布隆过滤器场景

2023-04-26 08:32:45

Redis布隆过滤器

2009-06-18 10:13:00

Hibernate过滤

2009-07-08 16:07:04

Servlet过滤器配

2021-01-14 08:13:39

Spring Clou应用内置过滤器

2022-02-16 23:58:41

Spring过滤器验证码

2024-10-09 15:54:38

布隆过滤器函数

2017-04-12 14:43:01

Spring ClouZuul过滤器

2023-01-26 01:41:27

核心全局过滤器

2021-07-05 15:22:03

Servlet过滤器客户端

2022-11-28 11:45:30

Go应用场景

2024-01-05 09:04:35

隆过滤器数据结构哈希函数

2022-02-21 23:58:49

Spring过滤器顺序值

2009-07-08 17:33:37

Servlet过滤器

2024-11-04 08:45:48

布隆过滤器元数据指纹值

2017-05-04 22:30:17

Zuul过滤器微服务

2009-07-08 15:30:56

Servlet过滤器

2009-09-29 13:55:23

Hibernate设置

2009-07-14 09:09:08

Swing模型过滤器

2011-06-29 16:14:59

Qt 事件 过滤器
点赞
收藏

51CTO技术栈公众号