小编给大家分享一下SpringBoot中过滤器Filter怎么用,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!
创新互联是一家集网站建设,砀山企业网站建设,砀山品牌网站建设,网站定制,砀山网站建设报价,网络营销,网络优化,砀山网站推广为一体的创新建站企业,帮助传统企业提升企业形象加强企业竞争力。可充分满足这一群体相比中小企业更为丰富、高端、多元的互联网需求。同时我们时刻保持专业、时尚、前沿,时刻以成就客户成长自我,坚持不断学习、思考、沉淀、净化自己,让我们为更多的企业打造出实用型网站。
在正式开始之前,有必要先简单看一下什么是Filter(过滤器),以及这个有什么用
Filter,过滤器,属于Servlet规范,并不是Spring独有的。其作用从命名上也可以看出一二,拦截一个请求,做一些业务逻辑操作,然后可以决定请求是否可以继续往下分发,落到其他的Filter或者对应的Servlet
简单描述下一个http请求过来之后,一个Filter的工作流程:
首先进入filter,执行相关业务逻辑
若判定通行,则进入Servlet逻辑,Servlet执行完毕之后,又返回Filter,最后在返回给请求方
判定失败,直接返回,不需要将请求发给Servlet
插播一句:上面这个过程,和AOP中的
@Around环绕切面的作用差不多
接下来我们搭建一个web应用方便后续的演示,借助SpringBoot搭建一个web应用属于比较简单的活;
创建一个maven项目,pom文件如下
org.springframework.boot spring-boot-starter-parent 2.1.7 UTF-8 UTF-8 Finchley.RELEASE 1.8 org.springframework.boot spring-boot-starter-web com.alibaba fastjson 1.2.45 org.springframework.boot spring-boot-maven-plugin spring-milestones Spring Milestones https://repo.spring.io/milestone false
在SpringBoot项目中,如果需要自定义一个Filter,并没有什么特殊的地方,直接实现接口即可,比如下面一个输出请求日志的拦截器
@Slf4j
@WebFilter
public class ReqFilter implements Filter {
public ReqFilter() {
System.out.println("init reqFilter");
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
log.info("url={}, params={}", req.getRequestURI(), JSON.toJSONString(req.getParameterMap()));
chain.doFilter(req, response);
}
@Override
public void destroy() {
}
}实现一个自定义的Filter容易,一般有两个步骤
实现 Filter 接口
在doFilter方法中添加业务逻辑,如果允许访问继续,则执行chain.doFilter(req, response);; 不执行上面这一句,则访问到此为止
接下来的一个问题就是如何让我们自定义的Filter生效,在SpringBoot项目中,有两种常见的使用方式
@WebFilter
包装Bean: FilterRegistrationBean
这个注解属于Servlet3+,与Spring也没有什么关系,所以问题来了,当我在Filter上添加了这个注解之后,Spring怎么让它生效呢?
配置文件中显示使用注解 @ServletComponentScan
@ServletComponentScan
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
}WebFilter常用属性如下,其中urlPatterns最为常用,表示这个filter适用于哪些url请求(默认场景下全部请求都被拦截)
| 属性名 | 类型 | 描述 |
|---|---|---|
| filterName | String | 指定过滤器的 name 属性,等价于 |
| value | String[] | 该属性等价于 urlPatterns 属性。但是两者不应该同时使用。 |
| urlPatterns | String[] | 指定一组过滤器的 URL 匹配模式。等价于 |
| servletNames | String[] | 指定过滤器将应用于哪些 Servlet。取值是 @WebServlet 中的 name 属性的取值,或者是 web.xml 中 |
| dispatcherTypes | DispatcherType | 指定过滤器的转发模式。具体取值包括:ASYNC、ERROR、FORWARD、INCLUDE、REQUEST。 |
| initParams | WebInitParam[] | 指定一组过滤器初始化参数,等价于 |
| asyncSupported | boolean | 声明过滤器是否支持异步操作模式,等价于 |
| description | String | 该过滤器的描述信息,等价于 |
| displayName | String | 该过滤器的显示名,通常配合工具使用,等价于 |
上面一种方式比较简单,后面会说到有个小问题,指定Filter的优先级比较麻烦,
下面是使用包装bean注册方式
@Bean public FilterRegistrationBeanorderFilter() { FilterRegistrationBean filter = new FilterRegistrationBean<>(); filter.setName("reqFilter"); filter.setFilter(new ReqFilter()); // 指定优先级 filter.setOrder(-1); return filter; }
上面整完,就可以开始测试使用过滤器了,在进入实测环节之前,先来看两个常见的问题
Filter作为Servelt的组件,怎么与SpringBoot中的Bean交互
多个Filter之间的优先级怎么确定
如果有小伙伴使用SpringMVC + web.xml方式来定义Filter,就会发现自定义的Filter中无法通过@Autowired方式来注入Spring的bean
我之前使用的是spring4 Servlet2+ ,存在上面的问题,如果有不同观点请留言告诉我,感谢
SpringBoot中可以直接注入依赖的Bean,从上面的第二种注册方式可以看到,Spring将Filter封装成了一个Bean对象,因此可以直接注入依赖的Bean
下面定义一个AuthFilter,依赖了自定义的DemoBean
@Data
@Component
public class DemoBean {
private long time;
public DemoBean() {
time = System.currentTimeMillis();
}
public void show() {
System.out.println("demo bean!!! " + time);
}
}
@Slf4j
@WebFilter
public class AuthFilter implements Filter {
@Autowired
private DemoBean demoBean;
public AuthFilter() {
System.out.println("init autFilter");
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
log.info("in auth filter! {}", demoBean);
// 测试,用header中的 tx-demo 来判断是否为认证的请求
HttpServletRequest req = (HttpServletRequest) request;
String auth = req.getHeader("tx-demo");
if ("yihuihui".equals(auth)) {
// 只有认证的请求才允许访问,请求头中没有这个时,不执行下面的的方法,则表示请求被过滤了
// 在测试优先级时打开下面的注释
// chain.doFilter(request, response);
} else {
chain.doFilter(request, response);
}
}
@Override
public void destroy() {
}
}Filter的优先级指定,通过我的实际测试,@Order注解没有用,继承 Ordered接口也没有用,再不考虑web.xml的场景下,只能通过在注册Bean的时候指定优先级
实例如下,三个Filter,两个通过@WebFilter注解方式注册,一个通过FilterRegistrationBean方式注册
@Slf4j
@Order(2)
@WebFilter
public class AuthFilter implements Filter, Ordered {
...
}
@Slf4j
@Order(1)
@WebFilter
public class ReqFilter implements Filter, Ordered {
...
}
@Slf4j
public class OrderFilter implements Filter {
}
@ServletComponentScan
@SpringBootApplication
public class Application {
@Bean
public FilterRegistrationBean orderFilter() {
FilterRegistrationBean filter = new FilterRegistrationBean<>();
filter.setName("orderFilter");
filter.setFilter(new OrderFilter());
filter.setOrder(-1);
return filter;
}
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
} 上面定义了三个Filter,我们主要验证下优先级,如果@Order注解生效,那么执行的先后顺序应该是
OrderFilter -> ReqFilter -> AuthFilter
如果不是上面的顺序,那么说明@Order注解没有用
@RestController
public class IndexRest {
@GetMapping(path = {"/", "index"})
public String hello(String name) {
return "hello " + name;
}
}
(上文截图源码来自: org.apache.catalina.core.ApplicationFilterFactory#createFilterChain)
上面是测试时关键链路的断点截图,从数组中可以看出 AuthFilter的优先级大于ReqFilter, 下面实际的输出也说明了@Order注解不能指定Filter的优先级(不知道为什么网络上有大量使用Order来指定Filer优先级的文章!!!)

接下来我们的问题就是WebFilter注解来注册的Filter的优先级是怎样的呢,我们依然通过debug来看,关键代码路径为: org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#selfInitialize

OrderFiler是我们手动注册并设置优先级为-1
ReqFilter, AuthFilter通过 WebFillter方式注册,默认优先级为2147483647,相同优先级的情况下,根据名字先后顺序来决定
本文主要介绍了过滤器Filter的使用方式,以及常见的两个问题解答,文中内容穿插了一点源码的分析截图,并未深入,如有兴趣的同学可以根据文中提的几个关键位置探索一番
下面简单小结下文中内容
自定义Filter的实现
实现Filter接口
doFilter方法中,显示调用chain.doFilter(request, response);表示请求继续;否则表示请求被过滤
注册生效
@ServletComponentScan自动扫描带有@WebFilter注解的Filter
创建Bean: FilterRegistrationBean 来包装自定义的Filter
在SpringBoot中Filter可以和一般的Bean一样使用,直接通过Autowired注入其依赖的Spring Bean对象
通过创建FilterRegistrationBean的时候指定优先级,如下
@Bean public FilterRegistrationBeanorderFilter() { FilterRegistrationBean filter = new FilterRegistrationBean<>(); filter.setName("orderFilter"); filter.setFilter(new OrderFilter()); filter.setOrder(-1); return filter; }
此外格外注意, @WebFilter声明的Filter,优先级为2147483647(最低优先级)
@Order注解不能指定Filter优先级
@Order注解不能指定Filter优先级
@Order注解不能指定Filter优先级
以上是“SpringBoot中过滤器Filter怎么用”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注创新互联行业资讯频道!