美文网首页撸一个mvc框架
SpringMVC —— @WebFilter 注解与 Spri

SpringMVC —— @WebFilter 注解与 Spri

作者: 想54256 | 来源:发表于2020-11-20 13:41 被阅读0次

    title: SpringMVC —— @WebFilter 注解与 SpringMVC
    date: 2020/11/19 17:09


    引言

    之前同事在写 Filter 的时候发现在 Filter 中无法使用 @Value 等注解进行 DI,代码如下:

    @WebFilter("/demo03/*")
    public class Filter1 implements Filter {
    
        @Value("${test03.aaa}")
        private String aaa;
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
    
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            System.out.println(aaa);
            System.out.println(servletRequest.getParameter("name"));
            filterChain.doFilter(servletRequest, servletResponse);
        }
    
        @Override
        public void destroy() {
    
        }
    }
    

    @WebFilter 注解是 servlet3.0 提供的注解,只是为了代替在 web.xml 文件中配置 filter,下面介绍 3 种可以 DI 的配置方法。

    配置 Filter

    1)@ServletComponentScan 方式(只适用于 jar 包启动方式)

    @WebFilter("/demo03/*")
    public class Filter1 implements Filter {
    
        ...
    }
    
    @ServletComponentScan
    @SpringBootApplication
    public class SpringTestApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(SpringTestApplication.class, args);
        }
    
    }
    

    2)直接加 @Component 注解(错误,不要使用)

    @Component
    @WebFilter("/demo03/*")
    public class Filter1 implements Filter {
    
        ...
    }
    

    问题:war 包启动时一次请求调用了两次 Filter,一次有 DI 的值一次没有。

    image

    经过测试发现,好像是 Spring 加了一个拦截/*的过滤器,Tomcat 加了一个拦截/demo03/*的过滤器(Tomcat 加的没有进行 DI;而且在使用 jar 包启动的时候 Tomcat 不会加拦截器,所以没问题)。

    3)通过 FilterRegistrationBean 向容器中注册(一切正常)

    @Component
    public class Filter1 implements Filter {
    
        ...
    }
    
    @SpringBootApplication
    public class SpringTestApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(SpringTestApplication.class, args);
        }
    
        @Bean
        public FilterRegistrationBean<Filter1> func(Filter1 filter1) {
            FilterRegistrationBean<Filter1> registrationBean = new FilterRegistrationBean<>();
            registrationBean.setFilter(filter1);
            registrationBean.addUrlPatterns("/demo03/*");
            return registrationBean;
        }
    
    }
    

    从上面三种方式可以得出:

    1. 外部 Tomcat 启动时 Tomcat 会扫描携带 @WebFilter 注解的 Filter 然后加入过滤器链。
    2. 如果 Filter 上标注了 @Component 注解,则 Spring 会自动将进行 DI 并加入过滤器链中,只不过拦截的地址是/*
    3. 第三种配置方式因为没有携带 @WebFilter 注解,所以不会被 Tomcat 扫描,但为啥 Spring 没有为其加两个拦截地址呢? 理论上 @Component -> /* @Bean ->/demo03/* -> 看最后一张图中的 seen 字段

    代码解析

    @ServletComponentScan

    image image image image image

    发没发现这种方式和我们的第三种配置方式实际上是一样的。

    当 Tomcat 启动完成的时候会调用 ServletContainerInitializer 的 onStartup() 方法

    image image

    229 行 getServletContextInitializerBeans()

    image image image

    230 行 beans.onStartup(servletContext);

    image image image image

    使用 @Component 标注 Filter 为啥也会进行拦截

    image image image

    相关文章

      网友评论

        本文标题:SpringMVC —— @WebFilter 注解与 Spri

        本文链接:https://www.haomeiwen.com/subject/aaudiktx.html