花式玩SpringBoot!过滤器竟有N种注册方式!手把手教你

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

创新互联成立与2013年,我们提供高端网站建设、小程序制作、电商视觉设计、成都APP应用开发及网络营销搜索优化服务,在传统互联网与移动互联网发展的背景下,我们坚守着用标准的设计方案与技术开发实力作基础,以企业及品牌的互联网商业目标为核心,为客户打造具商业价值与用户体验的互联网+产品。

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

1.@WebFilter

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

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

 
 
 
 
  1. @WebFilter(urlPatterns = "/*")
  2. public class MyFilter implements Filter {
  3.     @Override
  4.     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
  5.         System.out.println("-----doFilter-----");
  6.         chain.doFilter(request, response);
  7.     }
  8. }

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

 
 
 
 
  1. @SpringBootApplication
  2. @ServletComponentScan
  3. public class FilterdemoApplication {
  4.     public static void main(String[] args) {
  5.         SpringApplication.run(FilterdemoApplication.class, args);
  6.     }
  7. }

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

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

2.@Bean

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

 
 
 
 
  1. @Component
  2. public class MyFilter implements Filter {
  3.     @Override
  4.     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
  5.         System.out.println("-----doFilter-----");
  6.         chain.doFilter(request, response);
  7.     }
  8. }

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

 
 
 
 
  1. @Component
  2. @Order(-1)
  3. public class MyFilter implements Filter {
  4.     @Override
  5.     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
  6.         System.out.println("-----doFilter-----");
  7.         chain.doFilter(request, response);
  8.     }
  9. }

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

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

3.FilterRegistrationBean

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

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

 
 
 
 
  1. @Configuration
  2. public class FilterConfiguration {
  3.     @Bean
  4.     FilterRegistrationBean myFilterFilterRegistrationBean() {
  5.         FilterRegistrationBean bean = new FilterRegistrationBean<>();
  6.         bean.setFilter(new MyFilter());
  7.         bean.setOrder(-1);
  8.         bean.setUrlPatterns(Arrays.asList("/*"));
  9.         return bean;
  10.     }
  11.     @Bean
  12.     FilterRegistrationBean myFilterFilterRegistrationBean2() {
  13.         FilterRegistrationBean bean = new FilterRegistrationBean<>();
  14.         bean.setFilter(new MyFilter2());
  15.         bean.setOrder(-2);
  16.         bean.setUrlPatterns(Arrays.asList("/hello"));
  17.         return bean;
  18.     }
  19. }

4.扩展

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

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

 
 
 
 
  1. public abstract class RegistrationBean implements ServletContextInitializer, Ordered {
  2.  private int order = Ordered.LOWEST_PRECEDENCE;
  3.  private boolean enabled = true;
  4.  @Override
  5.  public final void onStartup(ServletContext servletContext) throws ServletException {
  6.   String description = getDescription();
  7.   if (!isEnabled()) {
  8.    logger.info(StringUtils.capitalize(description) + " was not registered (disabled)");
  9.    return;
  10.   }
  11.   register(description, servletContext);
  12.  }
  13.  protected abstract String getDescription();
  14.  protected abstract void register(String description, ServletContext servletContext);
  15.  public void setEnabled(boolean enabled) {
  16.   this.enabled = enabled;
  17.  }
  18.  public boolean isEnabled() {
  19.   return this.enabled;
  20.  }
  21.  public void setOrder(int order) {
  22.   this.order = order;
  23.  }
  24.  @Override
  25.  public int getOrder() {
  26.   return this.order;
  27.  }
  28. }
  1. RegistrationBean 实现了 ServletContextInitializer 接口,在 Servlet 启动时,RegistrationBean#onStartup 方法会被调用,进而完成 Filter、Servlet 以及 Listener 的注册。
  2. enabled 属性可以理解为一个开关,设置为 false 相当于关闭组件注册。

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

实现类的作用一目了然:

  • ServletListenerRegistrationBean 用来注册监听器。
  • 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

本文转载自微信公众号「江南一点雨」,可以通过以下二维码关注。转载本文请联系江南一点雨公众号。

本文题目:花式玩SpringBoot!过滤器竟有N种注册方式!手把手教你
地址分享:http://www.hantingmc.com/qtweb/news47/494547.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联