为什么Servlet Filter可以是Spring Bean?

Man*_*Kyu 1 spring filter interceptor spring-boot

我对过滤器和拦截器的了解是,作为 J2EE 规范的过滤器是 Web 服务器的一部分,而不是 Spring 框架的一部分。所以一些较旧的文章解释说,将过滤器注册为Spring Bean是不可能的,而Interceptor是可以的。但是我今天测试的结果是,Filters可以是Spring Bean,并且在Filters上注入Spring Bean也可以像Interceptor一样。(我在SpringBoot框架上测试过)

@Component
public class CustomFilterTest implements Filter {

    @Override
    public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws ServletException, IOException {
        chain.doFilter(request, response);
    }

    @Override
    public void init(final FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }

}
Run Code Online (Sandbox Code Playgroud)
@RestController
@RequiredArgsConstructor
public class ProductController {

    private final CustomFilterTest customFilterTest;

    @GetMapping("/test")
    public ResponseEntity<Void> temp() {
        System.out.println(customFilterTest);
        return ResponseEntity.noContent().build();
    }
}

Run Code Online (Sandbox Code Playgroud)

谁能向我解释一下吗?

M. *_*num 8

这里我们必须区分常规 Spring 应用程序和 Spring Boot 应用程序。与两者一样,您可以将 servlet 过滤器注册为 bean,但机制有点不同。

Spring框架

在普通的 Spring 中使用DelegatingFilterProxy来实现这一点。的任务DelegatingFilterProxy是在根应用程序上下文中查找与过滤器同名的bean(ApplicationContext通过注册的ContextLoaderListener)。该 bean 必须是您的托管 servlet 过滤器。

@Configuration
@EnableWebMvc
public class WebConfiguration {

  @Bean
  public void YourFilter myFilter() { ... }
}
Run Code Online (Sandbox Code Playgroud)

然后,对于 Web 应用程序,您将注册一个DelegatingFilterProxy名称myFilter以使其工作。

public class MyWebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

public void onStartup(ServletContext servletContext)
               throws ServletException {
   super.onStartup(servletContext);
   servletContext.addFilter("myFilter", DelegatingFilterProxy.class);
}
Run Code Online (Sandbox Code Playgroud)

春季启动

在 Spring Boot 中,情况有点不同,因为 Spring Boot 也控制着 servlet 容器,例如 Tomcat。这基本上意味着 Tomcat 也是您中的托管 bean,ApplicationContext并且 Spring Boot 可以将依赖项注入其中。因此,当 Spring Boot 检测到 servlet 过滤器的 bean 时,它会自动将其添加到过滤器链中(不需要 a DelegatingFilterProxy)。

@Bean这意味着您的过滤器只需要一个。

@Configuration
public class WebConfiguration {

  @Bean
  public YourFilter myFilter() { ... }
}
Run Code Online (Sandbox Code Playgroud)

FilterRegistrationBean此外,您还可以通过为此过滤器添加附加内容来配置 URL 等内容。

结论

对于普通 Spring 来说,DelegatingFilterProxy自 2005 年发布的 Spring 1.2 以来就已经存在了。这意味着如果您正在阅读非常非常非常旧的文章(2005 年之前),这是正确的,但是随着 的添加DelegatingFilterProxy,这就不再是了。随着 Spring Boot 的发布,这变得更小了,它或多或少是注册过滤器(作为托管 bean)的唯一方法。