Spring MVC的De delegateatingFilterProxy有什么意义?

2022-08-31 08:43:42

我在我的春季MVC应用程序中看到了这一点:web.xml

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

我试图弄清楚为什么它在那里,以及它是否真的需要。

我在Spring文档中找到了这个解释,但它并没有帮助我理解它:

这似乎表明,该组件是弹簧中定义的servlets和Spring中定义的组件之间的“胶水”。web.xmlapplicationContext.xml

7.1 委派过滤器

使用 servlet 过滤器时,您显然需要在 中声明它们,否则它们将被 servlet 容器忽略。在Spring Security中,过滤器类也是在应用程序上下文中定义的Spring Bean,因此能够利用Spring丰富的依赖注入设施和生命周期接口。Spring提供了应用程序上下文之间的链接。web.xmlDelegatingFilterProxyweb.xml

使用 Dede delegateatingFilterProxy 时,您将在文件中看到如下内容:web.xml

<filter>
   <filter-name>myFilter</filter-name>
   <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
   <filter-name>myFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

请注意,过滤器实际上是一个 ,而不是实际实现过滤器逻辑的类。所做的是将 Filter 的方法委托给从 Spring 应用程序上下文中获取的 Bean。这使Bean能够从Spring Web应用程序上下文生命周期支持和配置灵活性中受益。Bean 必须实现,并且它必须具有与 filter-name 元素中的名称相同的名称。阅读 Javadoc for DelegatingFilterProxy 以了解更多信息DelegatingFilterProxyDelegatingFilterProxyjavax.servlet.Filter

那么,如果我把它从我的中取出,会发生什么?我的 servlet 将无法与 Spring 容器通信?web.xml


答案 1

这里有某种魔力,但最终,一切都是确定性的程序。

如上所述,DedetleatingFilterProxy是一个过滤器,其目标是“委托给实现过滤器接口的Spring管理的Bean”,也就是说,它在Spring应用程序上下文中查找Bean(“目标Bean”或“委托”)并调用它。这怎么可能?因为这个 bean 实现了 javax.servlet.Filter,所以调用了它的 doFilter 方法。

哪种豆子叫什么?DedetleingFilterProxy “支持 'targetBeanName' [...],在 Spring 应用程序上下文中指定目标 Bean 的名称。

正如你在网络中看到的.xml豆子的名字是“springSecurityFilterChain”。

因此,在 Web 应用程序的上下文中,Filter 在应用程序上下文中实例化名为“springSecurityFilterChain”的 Bean,然后通过 doFilter() 方法委托给它。

请记住,应用程序上下文是使用所有应用程序上下文 (XML) 文件定义的。例如:applicationContext.xml and applicationContext-security.xml。

所以试着在后者中找到一种叫做“springSecurityFilTerChain”的豆子......

...并且可能您不能(例如,如果您遵循教程或使用Roo配置了安全性)

这是魔术:有一个用于配置安全性的新元素,例如

<http auto-config="true" use-expressions="true"> 

因为它是 http://www.springframework.org/schema/security/spring-security-3.0.xsd 允许的,将做到这一点。

当Spring使用XML文件加载应用程序上下文时,如果它找到一个元素,它将尝试设置HTTP安全性,即过滤器堆栈和受保护的URL,并注册名为“springSecurityFilterChain”的FilterChainProxy。

或者,您可以用经典的方式定义 Bean,即:

<beans:bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">

但不太推荐,因为您需要进行大量配置(您将要使用的所有过滤器)。而且有十几个)


答案 2

你知道什么是Servlet过滤器以及它是如何工作的吗?它是Servlet规范中非常有用的一部分,允许我们将类似AOP的概念应用于HTTP请求的服务。许多框架将 Filter 实现用于各种用途,并且查找它们的自定义实现并不罕见,因为它们编写起来非常简单且有用。在Spring应用程序中,您的应用程序可以执行的大多数操作都在您的Spring Bean中。但是,Filter 实例由 Servlet 容器控制。容器实例化、初始化并销毁它。不过,Servlet Spec不需要任何类型的Spring集成,因此您留下了一个非常有用的概念(过滤器),没有方便的方法将其与您的Spring应用程序和完成工作的Bean联系起来。

输入委派过滤器Proxy。您编写了一个 Filter 实现并使其成为 Spring bean,但不是将自己的 Filter 类添加到 Web.xml而是使用 DelegatingFilterProxy,并在 Spring 上下文中为其指定过滤器的 Bean 名称。(如果未显式提供名称,它将使用“筛选器名称”。然后在运行时,DelegatingFilterProxy 处理查找实际实现(您在 Spring 中编写和配置的实现)并将请求路由到它的复杂性。因此,在运行时,就好像您在Web中列出了过滤器.xml,但是您可以像任何其他Spring Bean一样连接它。

如果您将该过滤器映射从Web.xml中删除,则一切都将继续工作,但您的任何URL都不会受到保护。(这是假设“springSecurityFilterChain”这个名字准确地描述了它的作用。这是因为此映射正在过滤每个传入的请求,并将其传递给在Spring上下文中定义的安全过滤器。


推荐