zoukankan      html  css  js  c++  java
  • springboot2专题之第六篇:web开发创建过滤器的几种方式

    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;
        }
    
    }
    1. RegistrationBean 实现了 ServletContextInitializer 接口,在 Servlet 启动时,RegistrationBean#onStartup 方法会被调用,进而完成 Filter、Servlet 以及 Listener 的注册。
    2. enabled 属性可以理解为一个开关,设置为 false 相当于关闭组件注册。

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

    实现类的作用一目了然:

    1. ServletListenerRegistrationBean 用来注册监听器。
    2. ServletRegistrationBean 用来注册 Servlet。
    3. DispatcherServletRegistrationBean 用来注册 DispatcherServlet。
    4. FilterRegistrationBean 用来注册过滤器。
    5. DelegatingFilterProxyRegistrationBean 则用来注册 DelegatingFilterProxy,DelegatingFilterProxy 在 Spring Security、Spring Session、Shiro 等整合时非常有用。

    本文案例下载地址:https://github.com/lenve/javaboy-code-samples

    来源:http://itboyhub.com/2021/01/29/spring-boot-filter/

  • 相关阅读:
    颜色转换
    颜色转换、随机、16进制转换、HSV
    ColorTransform调整显示对象的颜色值
    unity+统计代码总行数
    Unity加载json数据
    打不开unity编辑器界面,每次默认打开上一次项目,并且报错Error loading file:///C%3A%2FUsers%2FT01017%2FAppData%2FRoaming%2FUnity%2FPackages%2Fnode_modules%2F
    Unity 同一Text文本修改不同的字体大小和字体颜色,加空格
    Unity 限时使用 限制试用时间和使用次数
    unity更改文字透明度
    unity+动画状态机
  • 原文地址:https://www.cnblogs.com/konglxblog/p/15595914.html
Copyright © 2011-2022 走看看