为啥在 Spring 中使用 OncePerRequestFilter?

Posted

技术标签:

【中文标题】为啥在 Spring 中使用 OncePerRequestFilter?【英文标题】:Why use OncePerRequestFilter in Spring?为什么在 Spring 中使用 OncePerRequestFilter? 【发布时间】:2016-06-28 22:46:43 【问题描述】:

正如文档所说:

过滤器基类,旨在保证每次执行一次 请求调度,在任何 servlet 容器上。

有个问题 What is OncePerRequestFilter? 我仍然不知道我们为什么要使用它。

它说“在任何 servlet 容器上”。这是否意味着有servlet容器会多次执行过滤器?

【问题讨论】:

“为什么要使用它?” - 每个请求只执行一次,不多也不少? 【参考方案1】:

OncePerRequestFilter 状态的 javadoc

从 Servlet 3.0 开始,过滤器可以作为 javax.servlet.DispatcherType REQUEST 或 javax.servlet.DispatcherType ASYNC 调度的一部分被调用,这些调度发生在不同的线程中。可以在 web.xml 中配置过滤器是否应该参与异步调度。但是,在某些情况下,servlet 容器采用不同的默认配置。因此,子类可以覆盖方法 shouldNotFilterAsyncDispatch() 以静态声明它们是否确实应该在两种类型的分派期间调用一次,以提供线程初始化、日志记录、安全性等。这种机制补充而不是取代在 web.xml 中使用调度程序类型配置过滤器的需要。

因此,这是 Spring 中实现的附加“安全”功能,以确保无论环境如何,事情都可以正常工作。如果您查看扩展它的类,您会发现有很多;包括 CorsFilter。不确定是否有不扩展它的 Spring 过滤器,可能没有。

【讨论】:

【参考方案2】:

我也回答了here。 要理解 OncePerRequestFilter 的作用,我们首先需要清楚地了解普通过滤器的行为方式。 当您希望在 servlet 执行之前或之后执行某些特定代码时,您可以创建一个过滤器,其作用如下:

code1   ===>   servlet execution (using chain.doFilter())   ===>    code2

所以 code1 在 servlet 之前执行,code2 在 servlet 执行之后。 但是在这里,当 servlet 执行时,可能会有一些其他请求到不同的 servlet,并且不同的 servlet 也具有相同的过滤器。 在这种情况下,这个过滤器将再次执行。

OncePerRequestFilter 阻止了这种行为。对于我们的一个请求,此过滤器将只执行一次(不多不少)。此行为在使用安全身份验证时非常有用。

【讨论】:

【参考方案3】:

一个用例是编写您自己的自定义过滤器,该过滤器扩展了 OncePerRequestFilter。

这可确保您的自定义过滤器在请求进入时位于最前线,并且规范确保它被执行。

希望对您有所帮助。

【讨论】:

以上是关于为啥在 Spring 中使用 OncePerRequestFilter?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在 Spring 中使用 Url Rewrite Filter?

为啥 Spring RestTemplate 在 Spring 中默认不是 Bean?

为啥 Spring 在使用 Hibernate 3 时推迟关闭 Hibernate 会话

为啥 Spring 在配置时并不总是使用批量插入/更新?

Spring:为啥我在使用注解时需要 applicationContext.xml?

为啥在 Spring Saml 中忽略 cacerts?