ChatGPT解决这个技术问题 Extra ChatGPT

Spring MVC 的 DelegatingFilterProxy 有什么意义?

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

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

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

我找到了 this explanation in the Spring docs,但它并不能帮助我理解它:

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

7.1 DelegatingFilterProxy 当使用servlet过滤器时,你显然需要在你的web.xml中声明它们,否则它们会被servlet容器忽略。在 Spring Security 中,过滤器类也是在应用程序上下文中定义的 Spring bean,因此能够利用 Spring 丰富的依赖注入设施和生命周期接口。 Spring 的 DelegatingFilterProxy 提供了 web.xml 和应用程序上下文之间的链接。使用 DelegatingFilterProxy 时,您会在 web.xml 文件中看到如下内容: myFilter org.springframework.web.filter.DelegatingFilterProxy myFilter /* 注意过滤器实际上是一个 DelegatingFilterProxy ,而不是实际实现过滤器逻辑的类。 DelegatingFilterProxy 所做的是将过滤器的方法委托给从 Spring 应用程序上下文获取的 bean。这使 bean 能够从 Spring Web 应用程序上下文生命周期支持和配置灵活性中受益。 bean 必须实现 javax.servlet.Filter 并且它必须与 filter-name 元素中的名称相同。阅读 DelegatingFilterProxy 的 Javadoc 了解更多信息

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


j
jbbarquero

这里有某种魔法,但归根结底,一切都是确定性程序。

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

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

正如您在 web.xml 中看到的,bean 的名称是“springSecurityFilterChain”。

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

请记住,您的应用程序上下文是使用所有应用程序上下文 (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 AND applicationContext-security.xml”是相同的文件名两次。
谢谢musiKk(我想你可以直接编辑帖子)
这就是我一直在寻找并为我澄清事情的解释。
@jbbarquero:你是对的,但我不确定正确的版本应该是什么。我倾向于把它留给原作者来修复,以免无意中改变意思。
好的。无论如何,我非常感谢您为改进我的回复所提供的帮助。再次感谢,音乐
T
Tom

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

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

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


感谢您发布这条富有启发性的评论。我现在正在学习 Spring Security,试图理解它来进行定制。我不知道什么是 servlet 过滤器或什么是 springs 过滤器。您对 AOP 的了解清楚地说明了为什么会有过滤器而不是仅使用 servlet........所以您不必在每个 servlet/资源中一遍又一遍地编写相同的前/后处理
哇。这个解释正是我需要的。感谢您分享你的知识。
@Ryan Stewart 如果我有两个 bean 在 applicationContext 中实现 Filter 接口,并且我想按顺序执行,那么我该怎么做呢?
@skaffman如果我有两个bean在applicationContext中实现了Filter接口,并且我想按顺序执行,那我该怎么做呢?
v
vphilipnyc

什么是 Servlet 过滤器?

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

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

servlet 过滤器在哪里使用?

现代网络应用程序可以有几十个这样的过滤器。诸如授权、缓存、ORM 会话管理和依赖注入之类的东西通常是在 servlet 过滤器的帮助下实现的。所有这些过滤器都需要在 web.xml 中注册。

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

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

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

这是 DelegatingFilterProxy 介入的地方。DelegatingFilterProxy 是 Spring Framework 提供的 javax.servlet.Filter 接口的实现。在 web.xml 中配置 DelegatingFilterProxy 后,您可以在 spring 配置中声明执行过滤的实际 beans。这样,Spring 创建了执行实际过滤的 bean 实例,您可以使用 DI 来配置这些 bean。

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


很好的解释。
B
Bozho

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

所以,如果你需要类似的东西:

public class FooFilter {

    @Inject
    private FooService service;

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

}

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


R
Ritesh

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

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

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


J
Janet

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

元素封装了应用程序 Web 层的安全配置。 >它创建一个名为“springSecurityFilterChain”的FilterChainProxy bean,它维护组成Web安全配置[19]的>安全过滤器堆栈。一些核心过滤器总是 >created 并且其他的将被添加到堆栈中,具体取决于 >present 的属性子元素。标准过滤器的位置是固定的(请参阅>命名空间介绍中的过滤器顺序表),消除了以前版本框架的常见错误源>当用户必须在FilterChainProxy bean中显式配置过滤器链时。当然,如果您需要完全控制配置,您仍然可以这样做。

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


O
OutOfMind

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

我试图通过删除有问题的过滤器并添加它来运行我的 spring 安全项目。我发现如果我们添加过滤器,那么只有调用才会重定向到 spring-security 配置中定义的所需登录页面。

因此,同意@Ryan 的回答。