SpringBoot 配置过滤器 Filter
相关地址:
- Spring Servlet 文档:https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/web/servlet
- 示例项目 Github:https://github.com/my-dlq/blog-example/tree/master/springboot/springboot-filter-example
系统环境:
- Jdk 版本:jdk 8
- SpringBoot 版本:2.2.1.RELEASE
一、什么是过滤器
javax.servlet.Filter 是一个接口,可以动态地拦截请求和响应信息,以变换或使用包含在请求或响应中的信息。
二、过滤器使用场景
- 数据压缩
- 记录日志
- 数据统计
- 数据格式转换
- 数据设置默认值
- 权限认证、黑白名单
- 数据加密/解密、签名效验
三、过滤器流程原理

在一个 web 应用中,可以开发编写多个 Filter,这些 Filter 组合起来称之为一个 Filter 链。在用户发起请求后,请求信息会根据过滤器链中过滤器的顺序进入各个过滤器,每经过一层过滤器时,需要通过这些滤器验证逻辑通过后放行,才能进入下一个过滤器,直至到服务器获取资源。等到服务器获取资源成功后进行响应给过滤器,然后再倒序的方式,经过一层层过滤器,最后对用户进行响应。
四、过滤器分类
Servlet 2.5:
- REQUEST:用户直接访问页面时,WEB 容器将会调用过滤链。
- FORWARD:目标资源是通过 RequestDispatcher 的 forward 访问时,该过滤器将被调用。
- INCLUDE:目标资源是通过 RequestDispatcher 的 include 方法调用时,过滤器将被调用。
- ERROR:目标资源是通过声明式异常处理机制调用时,过滤链将被调用。
Servlet 3.0:
- ASYNC:支持异步处理。
五、过滤器中实现的方法
- public void doFilter (ServletRequest, ServletResponse, FilterChain)
该方法完成实际的过滤操作,当客户端请求方法与过滤器设置匹配的 URL 时,Servlet 容器将先调用过滤器的 doFilter 方法。FilterChain 用户访问后续过滤器。
- public void init(FilterConfig filterConfig)
web 应用程序启动时,web 服务器将创建Filter 的实例对象,并调用其init方法,完成对象的初始化功能(filter对象只会创建一次,init方法也只会执行一次)。开发人员通过init方法的参数,做一些初始化操作,例如读取配置文件等。
- public void destroy()
Servlet 容器在销毁过滤器实例前调用该方法,在该方法中释放Servlet过滤器占用的资源。
六、两种创建过滤器方式
方式一:过滤器注解方式
创建步骤:
- (1)、创建过滤器类实现 Filter 接口,并在类的上面添加 @WebFilter 注解。
- (2)、过滤器类上添加 @Order() 注解来制定过滤器的顺序。
- (3)、SpringBoot 启动类上添加 @ServletComponentScan 注解。
实现过滤器接口,并添加 @WebFilter 与 @Order 注解,配置过滤器:
@Order(1)@WebFilter(filterName = "myFilter", urlPatterns = {"*"})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() {}}启动类添加 @ServletComponentScan 注解:
@SpringBootApplication@ServletComponentScanpublic class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); }}方式二:过滤器注册 Bean 方式
创建步骤:
- (1)、创建过滤器类实现 Filter 接口。
- (2)、创建过滤器配置类,里面创建一个过滤器注册 Bean,将之前创建的过滤器注册到其中。
创建过滤器类实现 Filter 接口:
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() {}}创建过滤器配置类,里面创建一个过滤器注册 Bean,将之前创建的过滤器注册到其中:
@Beanpublic FilterRegistrationBean customFilter(){ FilterRegistrationBean<MyCustomFilter1> filterBean = new FilterRegistrationBean<>(); filterBean.setFilter(new MyCustomFilter1()); filterBean.setName("FilterController"); filterBean.addUrlPatterns("/*"); return filterBean;}七、注解方式创建过滤器
1、参数说明
@WebFilter 能配置很多过滤器参数,下面是部分参数介绍:
| 参数名称 | 参数类型 | 参数描述 |
|---|---|---|
| filterName | String | Filter 名称 |
| displayName | String | Filter 的显示的名称 |
| asyncSupported | boolean | 设置 Filter 是否支持异步模式 |
| initParams | WebInitParam[] | 可以在初始化时配置一些参数 |
| servletNames | String[] | 设置对哪些 Servlet 进行过滤 |
| urlPatterns | String[] | 指定拦截的路径 |
| value | String[] | 和urlPatterns属性作用相同,都是指定拦截的路径,两种配置其一即可 |
| dispatcherTypes | DispatcherType[] | 设置 Filter 对哪种方式的请求进行过滤,支持的属性任如下: ASYNC、 ERROR、FORWARD、INCLUDE、REQUEST (默认过滤所有方式的请求) |
2、使用示例
(1)、创建 Controller 类
import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;
@RestControllerpublic class TestController {
@GetMapping("/aa/hello") public String hello1(){ return "hello world! aa"; }
@GetMapping("/bb/hello") public String hello2(){ return "hello world! bb"; }
@GetMapping("/cc/hello") public String hello3(){ return "hello world! cc"; }
}(2)、创建 Filter 类
import javax.servlet.*;import java.io.IOException;import javax.servlet.FilterChain;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.annotation.WebFilter;import org.springframework.core.annotation.Order;
/** * 自定义过滤器(注解方式) */@Order(1)@WebFilter(filterName = "myFilter", urlPatterns = {"/aa/*", "/bb/*"}, description = "自定义过滤器")public class MyCustomFilter2 implements Filter {
@Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("过滤器初始化"); }
@Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("before ..."); // 过滤器放行 filterChain.doFilter(servletRequest, servletResponse); System.out.println("after ..."); }
@Override public void destroy() { System.err.println("过滤器销毁"); }
}(3)、创建启动类
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.boot.web.servlet.ServletComponentScan;
@SpringBootApplication@ServletComponentScanpublic class Application {
public static void main(String[] args) { SpringApplication.run(Application.class, args); }
}八、过滤器注册 Bean 方式创建过滤器
1、方法参数说明
| 方法名称 | 方法描述 |
|---|---|
| setName() | 设置过滤器名称 |
| setFilter() | 设置要注册的过滤器 |
| setOrder() | 设置过滤器的顺序位置 |
| setAsyncSupported() | 设置 Filter 是否支持异步模式 |
| addUrlPatterns() | 增加拦截的拦截 |
| setUrlPatterns() | 设置拦截的路径 |
| addServletNames() | 为过滤器增加servlet名称 |
| setServletNames() | 设置注册过滤器的servlet名称 |
| setInitParameters() | 设置初始化参数 |
| addInitParameter() | 增加初始化参数 |
| setMatchAfter() | 设置是否在ServletContext的任何声明的过滤器映射之后匹配过滤器映射 |
| setDispatcherTypes() | 设置 Filter 对哪种方式的请求进行过滤,支持的属性任如下: ASYNC、 ERROR、FORWARD、INCLUDE、REQUEST (默认过滤所有方式的请求) |
2、创建步骤
- (1)、创建过滤器类实现
Filter接口。 - (2)、创建过滤器配置类,里面创建一个过滤器注册
Bean,将之前创建的过滤器注册到其中。
3、使用示例
(1)、创建 Controller 类
import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;
@RestControllerpublic class TestController {
@GetMapping("/aa/hello") public String hello1(){ return "hello world! aa"; }
@GetMapping("/bb/hello") public String hello2(){ return "hello world! bb"; }
@GetMapping("/cc/hello") public String hello3(){ return "hello world! cc"; }
}(2)、创建 Filter 类
import javax.servlet.*;import javax.servlet.FilterConfig;import java.io.IOException;
/** * 自定义过滤器(配置 Bean 方式) */public class MyCustomFilter1 implements Filter {
@Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("过滤器初始化"); }
@Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("before ..."); // 过滤器放行 filterChain.doFilter(servletRequest, servletResponse); System.out.println("after ..."); }
@Override public void destroy() { System.err.println("过滤器销毁"); }
}(3)、创建 Filter 配置类
import org.springframework.boot.web.servlet.FilterRegistrationBean;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;
@Configurationpublic class FilterConfig {
/** * 代码方式注册Bean * @return */ @Bean public FilterRegistrationBean customFilter(){ FilterRegistrationBean<MyCustomFilter1> filterBean = new FilterRegistrationBean<>(); filterBean.setFilter(new MyCustomFilter1()); filterBean.setName("FilterController"); filterBean.addUrlPatterns("/cc/*","/bb/*"); return filterBean; }
}(4)、创建启动类
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.boot.web.servlet.ServletComponentScan;
@SpringBootApplication@ServletComponentScanpublic class Application {
public static void main(String[] args) { SpringApplication.run(Application.class, args); }
}
