• SptingBoot过滤器Filter的使用方式



    Filter属于Servlet规范,并不是Spring独有的。Filter主要用于拦截请求,做一些业务逻辑操作,然后可以决定请求是否可以继续往下分发,落到其他的Filter或者对应的Servlet。

    Filter的工作流程

    1. 进入filter,执行相关业务逻辑

    2. 若判定失败,直接返回,不需要将请求发给Servlet

    3. 若判定通行,进行入下一个filter

      如果全部filter通行,进入Servlet逻辑,Servlet执行完毕之后,又返回Filter,最后在返回给请求方

    自定义Filter的使用方式

    Spring中过滤器Filter不同使用方式都是通过:FilterRegistrationBean包装filter,最终注册到Servlet容器中。

    1. @WebFilter+@ServletComponentScan

    SpringBootApplication上添加@ServletComponentScan注解,在Filter上添加@WebFilter注解。

    该方式的缺点:无法设置过滤器之间的优先级。

    @WebFilter+@ServletComponentScan方式无法通过@Order注解指定过滤器优先级:优先级使用默认值Ordered.LOWEST_PRECEDENCE(2147483647),相同优先级的情况下,根据名字先后顺序来决定。

    使用方法

    1. 在SpringBootApplication上使用@ServletComponentScan注解

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

    2.在Filter上使用@WebFilter注解

    @WebFilter(urlPatterns = {"/test3"})
    public class MyFilter extends OncePerRequestFilter {
    
        @Override
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
            System.out.println("======= MyFilter =======");
            filterChain.doFilter(request,response);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    @WebFilter

    @WebFilter用于将一个类声明为过滤器。

    WebFilter注解的主要属性:

    属性名类型描述
    filterNameString指定过滤器的name属性,(springbean也是用该名称),等价于< filter-name>
    urlPatternsString[]指定一组过滤器的URL匹配模式。等价于< url-pattern>
    valueString[]该属性等价于urlPatterns属性,但是两个不应该同时使用
    sevletNamesString[]指定过滤器将用于哪些servlet。取值是@WebServlet中的name属性的取值,或者是web.xml中< servlet-name>
    dispatcherTypesDispatcherType[]指定一组过滤器的转发模式。具体取值包括:ASYNC、ERROR、FORWARD、INCLUDE、REQUEST,默认REQUEST
    initParamsWebInitParam[]指定一组过滤器初始化参数,等价于< init-param>
    asyncSupportedboolean声明过滤器是否支持异步操作模式,等价于< async-supported>标签
    descriptionString过滤器的描述信息,等价于< description>
    displayNameString过滤器的显示名,通常配合工具使用,等价于< display-name>

    @ServletComponentScan

    在SpringBoot项目中,@WebServlet、@WebFilter、@WebListener这三个注解默认是不会被扫描的,一般在SpringBootApplication上添加@ServletComponentScan注解,表示对这三个注解的扫描。

    @ServletComponentScan可以实现將Servlet(控制器)、Filter(过滤器)、Listener(监听器)自动注册到Spring容器中,无需其他代码。

    • Servlet:通过@WebServlet注解定义
    • Filter:通过@WebFilter注解定义
    • Listener:通过@WebListener注解定义

    常见问题分析

    1. 只使用@WebFilte:过滤器不生效

    WebFilter属于注解属于Servlet3+,与Spring本身没有什么关系,所以Spring默认是不认识这个注解的。

    2. @WebFilter+@Component:配置的过滤条件不生效
    同上,Spring是不认识@WebFilter注解的,所以注解配置的任何属性都无意义(例如:指定过滤的url)。
    该种方式其实就等同于只加了个@Component注解,此时过滤器能生效,但无过滤条件,会过滤所有url。

    3. @WebFilter+@Component+@ServletComponentScan:过滤器会被调用两次

    • 一次:@WebFilter+@ServletComponentScan,被SpringBean管理,过滤器生效,根据@WebFilter配置的属性过滤
    • 二次:@Component,又被SpringBean管理一次,过滤器生效(和上面不是同一个bean),过滤全部url

    4. @WebFilter+@Order+@ServletComponentScan:设置过滤器优先级无效

    通过@WebFilter+@ServletComponentScan方式注册的,其生成的FilterRegistrationBean并没有检查@Order注解,所以@Order注解不生效。

    细节可参考文章:关于@webFilter使用@Order无效问题

    2. @Component+@Order

    通过在Filter上加@Component和@Order注解,即可被Spring管理,并可指定过滤器的执行顺序。

    该方式的缺点:只能过滤所有URL,不能通过配置去过滤指定的 URL。

    使用方法

    @Order(100)
    @Component
    public class MyFilter extends OncePerRequestFilter {
    
        @Override
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
            System.out.println("======= MyFilter =======");
            filterChain.doFilter(request,response);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    3. FilterRegistrationBean(推荐)

    直接通过配置类定义Filter的FilterRegistrationBean,交给SpringBean容器管理。

    该方式既能通过配置去过滤指定的 URL,也能指定过滤器之间的优先级。

    使用方法

    public class MyFilter extends OncePerRequestFilter {
    
        @Override
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
            System.out.println("======= MyFilter =======");
            filterChain.doFilter(request,response);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    @Configuration
    public class FilterConfig {
    
        @Bean
        public FilterRegistrationBean<MyFilter> filterRegistrationBean() {
            FilterRegistrationBean registration = new FilterRegistrationBean();
            registration.setFilter(myFilter());
            registration.setName("myFilter");
            registration.addUrlPatterns("/test3");
            registration.setOrder(100);
            return registration;
        }
    
        @Bean
        public MyFilter myFilter() {
            return new MyFilter();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
  • 相关阅读:
    Spring Cloud Alibaba 工程搭建
    elasticsearch 安装
    Docker 使用手册
    一种新型侧信道攻击方法,影响大部分苹果 A&M 系列芯片
    Cerebral Cortex:调节γ振荡可以促进大脑连接性而改善认知障碍
    Java的方法
    万向区块链小课堂:超短文梳理区块链层级,字字珠玑
    C语言:字符指针
    Flink部署 完整使用 (第三章)
    Hubble数据库再获得国家级重点项目推荐,作为HTAP国产数据库入选工信部全国试点
  • 原文地址:https://blog.csdn.net/JokerLJG/article/details/127634366