手把手教你SpringBoot过滤器N种注册方式

作者:江南一点雨 时间:2023-08-08 08:28:45 

要说在 Spring Boot 中注册过滤器有三种方式,你都能想到哪些呢?今天松哥就来和大家聊一聊 Spring Boot 中注册过滤器的三种方式!

其实本来是想和大家聊 Spring Security 过滤器链的问题的,结果看源码看着看着就跑题了,索性就先和大家聊一聊 Spring Boot 中注册过滤器的三种方式,算是给 后面的 Spring Security 打一点基础。

1.@WebFilter

通过 @WebFilter 注解来标记一个过滤器,这种方式相信大家很容易想到。这是将 Servlet 中的那一套东西直接拿到 Spring Boot 上用。

具体做法就是通过 @WebFilter 注解来标记一个 Filter,如下:


@WebFilter(urlPatterns = "/*")
public class MyFilter implements Filter {

@Override
 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
   System.out.println("-----doFilter-----");
   chain.doFilter(request, response);
 }
}

在 @WebFilter 注解中可以配置过滤器的拦截规则。这个注解要生效,还需要我们在项目启动类上配置 @ServletComponentScan 注解,如下:


@SpringBootApplication
@ServletComponentScan
public class FilterdemoApplication {

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

}

@ServletComponentScan 注解虽然名字带了 Servlet,但是实际上它不仅仅可以扫描项目中的 Servlet 容器,也可以扫描 Filter 和 Listener。

这是我们在 Spring Boot 中使用过滤器的第一种方式,在实际项目中,这种方式使用较少,因为这种方式有一个很大的弊端就是无法指定 Filter 的优先级,如果存在多个 Filter 时,无法通过 @Order 指定优先级。

2.@Bean

第二种方式就是将过滤器配置成 Bean,注册到 Spring 容器中去。这种方法不再需要 @ServletComponentScan 注解,只要一个 Bean 即可,如下:


@Component
public class MyFilter implements Filter {

@Override
 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
   System.out.println("-----doFilter-----");
   chain.doFilter(request, response);
 }
}

这种方式看起来很方便,一个注解将 Filter 纳入到 Spring 容器中即可。而且这种方式还有一个优势,就是如果存在多个 Filter,可以通过 @Order 注解指定多个 Filter 的优先级,像下面这样:


@Component
@Order(-1)
public class MyFilter implements Filter {

@Override
 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
   System.out.println("-----doFilter-----");
   chain.doFilter(request, response);
 }
}

虽然解决了优先级问题,但是大家发现这种方式好像没有办法设置 Filter 的拦截规则!是的,直接定义 Bean 的话,默认的拦截规则就是 /* 即拦截所有请求,开发者无法进行自定义配置。

那么有没有办法即配置拦截规则,又配置优先级呢?接下来介绍的第三种方案可以鱼与熊掌兼得。

3.FilterRegistrationBean

第三种方案还是将 Filter 封装成一个 Bean,但这个 Bean 是 FilterRegistrationBean,通过 FilterRegistrationBean 我们既可以配置 Filter 的优先级,也可以配置 Filter 的拦截规则。

一般在项目中,我们都是使用 FilterRegistrationBean 来配置过滤器,一起来看一个案例:


@Configuration
public class FilterConfiguration {
 @Bean
 FilterRegistrationBean<MyFilter> myFilterFilterRegistrationBean() {
   FilterRegistrationBean<MyFilter> bean = new FilterRegistrationBean<>();
   bean.setFilter(new MyFilter());
   bean.setOrder(-1);
   bean.setUrlPatterns(Arrays.asList("/*"));
   return bean;
 }
 @Bean
 FilterRegistrationBean<MyFilter2> myFilterFilterRegistrationBean2() {
   FilterRegistrationBean<MyFilter2> bean = new FilterRegistrationBean<>();
   bean.setFilter(new MyFilter2());
   bean.setOrder(-2);
   bean.setUrlPatterns(Arrays.asList("/hello"));
   return bean;
 }
}

4.扩展

FilterRegistrationBean 到底是什么来头呢?这里也和大家分享下。

Spring Boot 为了方便大家向 Servlet 容器中注册 Servlet、Filter 以及 Listener,提供了一个 Bean 注册的抽象类 RegistrationBean,如下:


public abstract class RegistrationBean implements ServletContextInitializer, Ordered {
private int order = Ordered.LOWEST_PRECEDENCE;
private boolean enabled = true;
@Override
public final void onStartup(ServletContext servletContext) throws ServletException {
String description = getDescription();
if (!isEnabled()) {
 logger.info(StringUtils.capitalize(description) + " was not registered (disabled)");
 return;
}
register(description, servletContext);
}
protected abstract String getDescription();
protected abstract void register(String description, ServletContext servletContext);
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public boolean isEnabled() {
return this.enabled;
}
public void setOrder(int order) {
this.order = order;
}
@Override
public int getOrder() {
return this.order;
}

}

RegistrationBean 实现了 ServletContextInitializer 接口,在 Servlet 启动时,RegistrationBean#onStartup 方法会被调用,进而完成 Filter、Servlet 以及 Listener 的注册。

enabled 属性可以理解为一个开关,设置为 false 相当于关闭组件注册。

RegistrationBean 有众多的实现类,我们之前使用的 FilterRegistrationBean 只是其中之一:

手把手教你SpringBoot过滤器N种注册方式

实现类的作用一目了然:

  • ervletListenerRegistrationBean 用来注册 * 。

  • ServletRegistrationBean 用来注册 Servlet。

  • DispatcherServletRegistrationBean 用来注册 DispatcherServlet。

  • FilterRegistrationBean 用来注册过滤器。

  • DelegatingFilterProxyRegistrationBean 则用来注册 DelegatingFilterProxy,DelegatingFilterProxy 在 Spring Security、Spring Session、Shiro 等整合时非常有用。

5.小结

今天就和小伙伴们分享一下 Spring Boot 中过滤器的三种注册方式,顺带和大家分享了一下 FilterRegistrationBean 的继承体系,小伙伴们可以根据 FilterRegistrationBean 的继承体系中的实现类,自行尝试一下 Servlet 和 Listener 的注册方式~本文案例下载地址:https://github.com/lenve/javaboy-code-samples

来源:https://mp.weixin.qq.com/s/PtMbe0nhpeqQfrmWgo2zFg

标签:SpringBoot,过滤器,注册
0
投稿

猜你喜欢

  • C#中判断某类型是否可以进行隐式类型转换

    2023-03-28 15:29:36
  • Java基础高级综合练习题扑克牌的创建

    2023-09-08 06:56:19
  • Android Studio实现进度条效果

    2021-10-12 05:37:17
  • Android框架Volley之利用Imageloader和NetWorkImageView加载图片的方法

    2023-07-06 00:21:08
  • C# DateTime日期比较方法案例详解

    2021-11-09 15:32:47
  • Java 逻辑控制全面详解

    2022-10-29 09:01:48
  • java求最大公约数与最小公倍数的方法示例

    2023-01-23 03:28:58
  • Spring Feign超时设置深入了解

    2022-01-17 10:39:06
  • Android自定义view仿淘宝快递物流信息时间轴

    2022-02-20 18:51:16
  • android实现下拉菜单三级联动

    2022-10-13 15:46:53
  • Android自定义视图中图片的处理

    2023-06-29 12:07:27
  • Java结构性设计模式中的装饰器模式介绍使用

    2022-04-08 06:30:00
  • C语言树与二叉树基础全刨析

    2023-01-25 16:06:57
  • java字符串遍历的几种常用方法总结

    2022-08-19 06:36:41
  • 使用java springboot设计实现的图书管理系统(建议收藏)

    2023-11-25 00:54:49
  • C# 启动 SQL Server 服务的实例

    2022-02-10 21:59:38
  • Android 安全加密:数字签名和数字证书详解

    2023-07-25 21:36:46
  • Java实现解出世界最难九宫格问题

    2022-06-14 19:47:10
  • Android GPS详解及示例代码

    2021-11-12 08:27:28
  • UnityWebRequest前后端交互实现过程解析

    2021-09-07 01:24:42
  • asp之家 软件编程 m.aspxhome.com