Spring MVC的DelegatingFilterProxy有什么意义?


120

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

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

我试图弄清楚为什么它存在以及是否真正需要它。

在Spring文档中找到了这种解释,但并不能帮助我理解它:

似乎表明该组件是web.xmlSpring中定义的servlet 和Spring中定义的组件之间的“胶水” applicationContext.xml

7.1 DelegatingFilterProxy

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

使用DelegatingFilterProxy时,您将在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>

请注意,过滤器实际上是一个DelegatingFilterProxy,而不是将实际实现过滤器逻辑的类。什么DelegatingFilterProxy确实是通过向其从Spring应用程序上下文中的bean代理Filter的方法。这使bean可以从Spring Web应用程序上下文生命周期支持和配置灵活性中受益。Bean必须实现javax.servlet.Filter,并且必须与filter-name元素中的名称相同。阅读Javadoc for DelegatingFilterProxy了解更多信息

因此,如果我从中删除此文件web.xml,将会发生什么?我的servlet无法与Spring容器通信?**

Answers:


127

这里有种魔术,但最后,一切都是确定性程序。

DelegatingFilterProxy的是因为它是上面说明的过滤器,其目标是“ 委托给Spring管理的bean实现Filter接口 ”,也就是说,它在你的Spring应用程序找到了豆(“目标豆”或“代表”)上下文并调用它。这怎么可能?由于此bean实现javax.servlet.Filter,因此将调用其doFilter方法。

哪个豆叫?“ DelegatingFilterProxy”支持“ targetBeanName”,在Spring应用程序上下文中指定目标bean的名称。“

正如您在web.xml中看到的那样,bean的名称为“ springSecurityFilterChain

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

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

因此,请尝试在后者中找到一个名为“ springSecurityFilterChain”的bean ...

...并且可能您不能这样做(例如,如果您遵循了教程或使用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">

但是不建议这样做,因为您需要做很多配置(将要使用的所有过滤器。并且有十几个过滤器)


“ applicationContext-security.xml和applicationContext-security.xml”是同一文件名两次。
musiKk 2014年

谢谢musiKk(我想您可以直接编辑该帖子)
jbbarquero 2014年

这就是我一直在寻找并为我整理东西的解释。
user871611 2014年

@jbbarquero:您是对的,但我不确定应该使用的版本正确。我倾向于将其留给原始作者来解决,以免无意中改变其含义。
musiKk 2014年

好。无论如何,我非常感谢您为改善我的反应所提供的帮助。再次感谢,musiKk
jbbarquero 2014年

73

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

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

如果您从web.xml中删除该过滤器映射,则所有内容将继续运行,但不会保护所有URL。(假设名称“ springSecurityFilterChain”准确地描述了它的作用。)这是因为此映射正在过滤每个传入的请求,并将其交给在Spring上下文中定义的安全过滤器。


感谢您发布此启发性评论。我现在正在学习Spring Security,试图充分了解它来进行自定义。我不知道什么是servlet过滤器或什么是springs过滤器。您对AOP的了解清楚地说明了为什么会有过滤器而不是仅使用servlet ....所以您不必在每个servlet /资源中一遍又一遍地编写相同的前后处理
Steve

哇。正是我所需要的解释。感谢您分享你的知识。
查尔斯·莫林

@Ryan Stewart如果我有两个bean在applicationContext中实现Filter接口,并且我想按顺序执行,那么我该怎么做呢?
Abhishek Nayak 2014年

@skaffman如果我有两个bean在applicationContext中实现Filter接口,并且我想按顺序执行,那我该怎么做呢?
Abhishek Nayak 2014年

44

什么是Servlet过滤器?

Servlet过滤器通常是Java WebApp概念。无论您是否在应用程序中使用Spring框架,都可以在任何Web应用程序中使用servlet过滤器。

这些过滤器可以在请求到达目标servlet之前对其进行拦截。您可以在servlet过滤器中实现通用功能,例如授权。实施后,您可以将web.xml中的过滤器配置为应用于特定的servlet,特定的请求url模式或所有url模式。

在哪里使用servlet过滤器?

现代网络应用程序可以包含数十种此类过滤器。授权,缓存,ORM会话管理和依赖项注入之类的事情通常是借助servlet过滤器实现的。所有这些过滤器都需要在中注册web.xml

实例化Servlet过滤器-没有Spring框架

您的servlet容器创建在web.xml其中声明的Filter的实例,并在适当的时间(例如,在服务servlet请求时)调用它们。现在,如果您像大多数依赖注入(DI)爱好者一样,您可能会说实例的创建是我的DI框架(Spring)做得更好的。我不能用Spring创建我的servlet过滤器,以便它们适合所有DI优点吗?

DelegatingFilterProxy,以便Spring创建您的过滤器实例

这是DelegatingFilterProxy步骤,DelegatingFilterProxy是一个impelmentation javax.servlet.Filter由Spring框架提供的接口。DelegatingFilterProxy在web.xml中配置后,就可以声明在spring配置中进行过滤的实际bean。这样,Spring将创建执行实际过滤的bean实例,并且您可以使用DI来配置这些bean。

请注意,您只需要一个DelegatingFilterProxy声明,web.xml但是可以bean在应用程序上下文中将多个过滤链接在一起。


很好解释。
user4906240

15

事实是,servlet过滤器是由servlet容器而不是spring管理的。并且您可能需要将一些弹簧组件注入过滤器中。

因此,如果您需要以下内容:

public class FooFilter {

    @Inject
    private FooService service;

    public void doFilter(....) { .. }

}

那么您需要委托过滤器代理。


1

您对“胶水”材料是正确的。如FilterChainProxy的 JavaDocs所述:

通过在应用程序web.xml文件中添加标准Spring DelegatingFilterProxy声明,将FilterChainProxy链接到servlet容器过滤器链。

请参阅Spring Security命名空间后面博客的FIlterChainProxy部分,以获取出色的解释。


0

我对web.xml中的“ springSecurityFilterChain”感到困惑,并在springframework安全文档中找到了以下答案:

<http>单元封装为应用程序的Web层的安全配置。>它将创建一个名为“ springSecurityFilterChain”的FilterChainProxy bean,该bean维护构成网络安全配置的安全过滤器堆栈[19]。始终会创建一些核心过滤器,而其他过滤器将根据存在的子元素属性添加到堆栈中。标准过滤器的位置是固定的(请参阅> namespace简介中的过滤器顺序表),从而消除了用户必须在FilterChainProxy bean中显式配置过滤器链时以前版本的框架常见的错误源。当然,如果您需要完全控制配置,则仍然可以这样做。

这是链接http://docs.spring.io/spring-security/site/docs/3.0.x/reference/appendix-namespace.html


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.