过滤器执行概述:
基本环境
- JDK 1.8
- SpringBoot 2.5.6
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
Servlet原生方式
- 新建过滤器
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import java.io.IOException;
@Slf4j
@WebFilter(urlPatterns = "/*", filterName = "AFilter", initParams = {
@WebInitParam(name = "encoding", value = "UTF-8-A")
})
public class AFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
String encoding = filterConfig.getInitParameter("encoding");
log.info("初始化 AFilter 参数 encoding = {}", encoding);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
log.info("AFilter 前...");
//放行
filterChain.doFilter(servletRequest, servletResponse);
log.info("AFilter 后...");
}
@Override
public void destroy() {
log.info("销毁 AFilter");
}
}
- 在启动类上、配置Servlet组件扫描@ServletComponentScan
配置类方式
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.*;
import java.io.IOException;
@Slf4j
@Configuration
public class WebMvcConfig {
@Bean
public FilterRegistrationBean<Filter> filterConfigurerA() {
// 定义一个过滤器的注册bean
FilterRegistrationBean<Filter> filterFilterRegistrationBean = new FilterRegistrationBean<>();
// 初始化自定义filter
Filter filterConfigurerA = new Filter() {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
String encoding = filterConfig.getInitParameter("encoding");
log.info("初始化 filterConfigurerA 参数 encoding = {}", encoding);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
log.info("filterConfigurerA 前...");
//放行
filterChain.doFilter(servletRequest, servletResponse);
log.info("filterConfigurerA 后...");
}
@Override
public void destroy() {
log.info("销毁 filterConfigurerA");
}
};
// 注册过滤器到ioc容器中
filterFilterRegistrationBean.setFilter(filterConfigurerA);
// 设置过滤器规则
filterFilterRegistrationBean.addUrlPatterns("/*");
// 设置过滤器名字
filterFilterRegistrationBean.setName("filterConfigurerA");
// 设置参数
filterFilterRegistrationBean.addInitParameter("encoding", "GBK-A");
// 设置执行顺序 数字越小越先执行
filterFilterRegistrationBean.setOrder(1);
// 返回
return filterFilterRegistrationBean;
}
}
该方式不需要使用@ServletComponentScan注解,并且可以设置过滤器的执行顺序,但是与Servlet原生的方式混合使用之后,就不能控制它们一起的执行顺序了。
- 不建议与Servlet原生方式混用。
- 也可能是博主能力有限,还未探究出它们混用时的顺序控制,也欢迎与博主在评论区进行讨论。
组件配置方式
package com.ara.filter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import java.io.IOException;
@Slf4j
@Component
@Order(-2)
public class BFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
String encoding = filterConfig.getInitParameter("encoding");
log.info("初始化 BFilter 参数 encoding = {}", encoding);
//log.info("采用@Component和@Order(-3)可以与配置类一同设置顺序,但是不能设置初始化参数");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
log.info("BFilter 前...");
//放行
filterChain.doFilter(servletRequest, servletResponse);
log.info("BFilter 后...");
}
@Override
public void destroy() {
log.info("销毁 BFilter");
}
}
该方式也不需要使用@ServletComponentScan注解,并且可以与配置类方式混用,而且其执行顺序会按照它们的Order值进行执行,Order值越小的就越先执行。
缺点:
- 该方式就不便于设置其加载的参数值。
总结
不建议使用Servlet原生的方式:
- 因为这是SpringBoot项目,我们应该善于利用其容器的便利性(也就是使用配置类方式和组件配置方式)。
- 使用Spring容器时,我们会更好的管理其执行顺序问题。
适配性:
- 如果需要设置过滤器的启动参数,就建议采用配置类的方式。
- 如果不需要设置过滤器的启动参数,就可随意选择了。
注意:
- 在本文中所描述的过滤器顺序是指在请求时,过滤器的执行顺序。
- 加载和销毁的顺序是不一定的,这个好像也控制不了(这个博主暂时没有仔细研究过,欢迎讨论),我们一般也无需关心。