Spring MVC的DelegatingFilterProxy有什么意义?

Tho*_*mas 116 java spring spring-mvc spring-security

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

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
Run Code Online (Sandbox Code Playgroud)

我试图找出它为什么存在以及它是否真的需要它.

在Spring文档中找到了这个解释,但它无助于我理解它:

它似乎表明这个组件是定义的servlet web.xml和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>
Run Code Online (Sandbox Code Playgroud)

请注意,过滤器实际上是a DelegatingFilterProxy,而不是实际实现过滤器逻辑的类.什么DelegatingFilterProxy是将Filter的方法委托给从Spring应用程序上下文获得的bean.这使bean能够受益于Spring Web应用程序上下文生命周期支持和配置灵活性.bean必须实现javax.servlet.Filter,并且必须与filter-name元素中的名称相同.有关更多信息,请阅读DelegatingFilterProxyJavadoc

所以,如果我把它从我web.xml身上拿走,会发生什么?我的servlet无法与Spring容器通信?**

jbb*_*ero 125

这里有一些魔力,但最后,一切都是确定性的程序.

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

叫哪个bean?DelegatingFilterProxy"支持"targetBeanName"[...],在Spring应用程序上下文中指定目标bean的名称."

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

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

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

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

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

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

<http auto-config="true" use-expressions="true"> 
Run Code Online (Sandbox Code Playgroud)

正如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">
Run Code Online (Sandbox Code Playgroud)

但它不太值得推荐,因为你需要进行大量的配置(你要使用的所有过滤器.还有十几个)


Rya*_*art 69

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

输入DelegatingFilterProxy.编写一个Filter实现并使其成为一个Spring bean,但不是将自己的Filter类添加到web.xml中,而是使用DelegatingFilterProxy,并在Spring上下文中为其指定过滤器的bean名称.(如果没有显式提供名称,它使用"filter-name".)然后在运行时,DelegatingFilterProxy处理查找真实实现的复杂性 - 您在Spring中编写和配置的实现 - 并将请求路由到它.所以在运行时,就好像你已经在web.xml中列出了你的过滤器,但是你可以像任何其他Spring bean一样连接它.

如果您从web.xml中获取该过滤器映射,一切都将继续有效,但您的所有URL都不会受到保护.(假设名称"springSecurityFilterChain"准确地描述了它的作用.)这是因为这个映射过滤每个传入的请求并将其交给在Spring上下文中定义的安全过滤器.


Tah*_*tar 43

什么是Servlet过滤器?

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

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

使用servlet过滤器的地方?

现代网络应用程序可以有许多这样的过滤器.授权,缓存,ORM会话管理和依赖注入等操作通常借助servlet过滤器实现.所有这些过滤器都需要注册web.xml.

实例化Servlet过滤器 - 没有Spring Framework

您的servlet容器创建声明的Filters实例,web.xml并在适当的时间调用它们(即,在处理servlet请求时).现在,如果你像大多数依赖注入(DI)粉丝一样,你可能会说我的DI框架(Spring)做得更好.我不能得到用Spring创建的servlet过滤器,所以它们适合所有DI的优点吗?

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

这里的DelegatingFilterProxy步骤DelegatingFilterProxyjavax.servlet.FilterSpring Framework提供的接口的一个实现.DelegatingFilterProxy在web.xml中配置后,您可以声明在spring配置中执行过滤的实际bean.这样,Spring会创建执行实际过滤的bean实例,您可以使用DI来配置这些bean.

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


Boz*_*zho 15

问题是,servlet过滤器由servlet容器管理,而不是由spring管理.您可能需要在过滤器中注入一些弹簧组件.

所以,如果您需要以下内容:

public class FooFilter {

    @Inject
    private FooService service;

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

}
Run Code Online (Sandbox Code Playgroud)

那么你需要委托过滤器代理.


Rit*_*esh 1

你对“胶水”的看法是对的。正如FilterChainProxy的 JavaDocs 中所写:

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

请参阅博客Behind the Spring Security Namespace的 FIlterChainProxy 部分以获得精彩的解释。