美文网首页撸一个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