Spring MVC的DelegatingFilterProxy有什么意义?

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

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

我试图找出为什么它在那里,是否真的需要。

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

似乎表明这个组件是web.xml定义的servlet和Spring applicationContext.xml定义的组件之间的“粘合剂”。

7.1 DelegatingFilterProxy

当使用servletfilter时,显然需要在你的web.xml声明它们,否则servlet容器将忽略它们。 在Spring Security中,filter类也是在应用程序上下文中定义的Spring bean,因此可以利用Spring丰富的dependency injectionfunction和生命周期接口。 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> 

请注意,filter实际上是一个DelegatingFilterProxy ,而不是实际实现filter逻辑的类。 DelegatingFilterProxy所做的是将Filter的方法委托给从Spring应用程序上下文获得的bean。 这使bean可以从Spring Web应用程序上下文生命周期支持和configuration灵活性中受益。 该bean必须实现javax.servlet.Filter并且它必须与filter-name元素中的名称相同。 阅读Javadoc的DelegatingFilterProxy获取更多信息

所以,如果我把这个从web.xml取出,会发生什么? 我的servlet将无法与Spring容器通信?**

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

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

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

正如你在web.xml中看到的那个bean的名字是“ springSecurityFilterChain

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

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

所以试着在后面find一个名为“springSecurityFilterChain”的bean

也许你不能 (例如,如果你遵循教程,或者如果你使用Rooconfiguration安全性)

这是神奇的: configuration安全性有一个新的元素 ,就像

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

http://www.springframework.org/schema/security/spring-security-3.0.xsd所允许的那样,将会有所斩获。;

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

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

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

但不太推荐,因为你需要做很多的configuration(你要使用的所有filter,而且有十几个)

你知道什么是Servlet filter ,它是如何工作的? 这是Servlet规范中非常有用的一部分,允许我们将类AOP概念应用于HTTP请求的服务。 许多框架使用Filter来实现各种各样的事情,并且find它们的自定义实现并不罕见,因为它们的编写非常简单并且非常有用。 在一个Spring应用程序中,你的应用程序可以做的大部分事情就是在你的Spring bean中。 但是,Filter实例受servlet容器控制。 容器实例化,初始化并销毁它。 但是,Servlet规范并不要求任何forms的Spring集成,所以你只剩下一个非常有用的概念(Filters),没有方便的方法将它绑定到你的Spring应用程序和执行工作的bean。

inputDelegatingFilterProxy。 您编写一个Filter实现并将其设为Spring bean,但不是将自己的Filter类添加到web.xml,而是使用DelegatingFilterProxy,并在Spring上下文中为其指定filter的bean名称。 (如果你没有明确地提供一个名字,它使用“filter-name”)。然后在运行时,DelegatingFilterProxy处理find真正的实现的复杂性 – 你在Spring中编写和configuration的实现 – 并将请求路由到它。 所以在运行时,就好像你已经在web.xml中列出了你的filter,但是你可以像其他任何Spring bean那样得到好处。

如果你把这个filter映射到你的web.xml中,所有东西都会继续工作,但是你的URL都不会被保护。 (假设名字“springSecurityFilterChain”准确地描述了它的作用)。这是因为这个映射过滤了每个传入的请求,并把它传递给在你的spring上下文中定义的安全filter。

什么是Servletfilter?

一般来说, Servletfilter是一个Java WebApp概念。 您可以在任何webapp中使用servletfilter,无论您是否在应用程序中使用Spring框架。

这些filter可以在到达目标servlet之前拦截请求。 您可以在servletfilter中实现通用function,如授权。 一旦实现,您可以在web.xml中configurationfilter,将其应用于特定的servlet,特定的请求url模式或所有url模式。

在哪里使用servletfilter?

现代的networking应用程序可以有几十个这样的filter。 像授权,caching,ORM会话pipe理和dependency injection等事情通常是借助于servletfilter来实现的。 所有这些filter都需要在web.xml注册。

实例化Servletfilter – 没有Spring框架

您的servlet容器将创build在web.xml声明的filter的实例,并在适当的时候调用它们(即,在提供servlet请求时)。 现在,如果你像绝大多数的dependency injection(DI)粉丝那样,你可能会说创build实例就是我的DI框架(Spring)做得更好。 我不能得到我用Spring创build的servletfilter,所以他们适合所有的DI善良?

DelegatingFilterProxy ,以便Spring创build您的filter实例

这是DelegatingFilterProxy步入的地方。DelegatingFilterProxy是Spring Framework提供的javax.servlet.Filter接口的一个实现。 一旦在web.xml中configuration了DelegatingFilterProxy ,就可以声明在Springconfiguration中进行筛选的实际Bean 。 这样,Spring就创build了实际进行过滤的bean的实例,并且可以使用DI来configuration这些bean。

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

问题是,servletfilter由servlet容器pipe理,而不是由spring来pipe理。 而且您可能需要将一些弹簧组件注入到filter中。

所以,如果你需要这样的东西:

 public class FooFilter { @Inject private FooService service; public void doFilter(....) { .. } } 

那么你需要委托过滤代理。

你对“胶水”的东西是正确的。 正如在FilterChainProxy的 JavaDocs中所写:

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

请参阅Spring Security命名空间后面的博客的FIlterChainProxy部分,以获得很好的解释。

我一直困惑于web.xml中的“springSecurityFilterChain”,并在springframework安全文档中find了这个答案:

<http>元素封装了应用程序的Web层的安全configuration。 >它创build了一个名为“springSecurityFilterChain”的FilterChainProxy bean,它维护构成Web安全configuration的安全filter堆栈[19]。 一些核心filter总是被创build,其他的将被添加到栈中,这取决于存在的子元素的属性。 标准filter的位置是固定的(请参阅>命名空间简介中的filter顺序表),当用户必须在FilterChainProxy bean中显式configurationfilter链时,使用旧版本的框架移除常见的错误源。 当然,如果您需要完全控制configuration,您仍然可以这样做。

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

它已经很长一段时间,但我有同样的问题,我发现这一点: https : //www.javacodegeeks.com/2013/11/spring-security-behind-the-scenes.html

我试图通过删除有问题的filter并添加它来运行我的spring安全项目。 我发现的是,如果我们添加filter,那么只有在popup安全configuration中定义的呼叫才会redirect到所需的login页面。

因此,同意@ Ryan的答案。