spring 什么是OncePerRequestFilter?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13152946/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 05:29:01  来源:igfitidea点击:

What is OncePerRequestFilter?

spring

提问by Somu

Documentation says org.springframework.web.filter.OncePerRequestFilter"guarantees to be just executed once per request". Under what circumstances a Filter may possibly be executed more than once per request?

文档说org.springframework.web.filter.OncePerRequestFilter保证每个请求只执行一次”。在什么情况下,每个请求可能会多次执行过滤器?

采纳答案by Stephen C

Under what circumstances a Filter may possibly be executed more than once per request?

在什么情况下,每个请求可能会多次执行过滤器?

You could have the filter on the filter chain more than once.

您可以在过滤器链上多次使用过滤器。

The request could be dispatched to a different (or the same) servlet using the request dispatcher.

可以使用请求分派器将请求分派到不同(或相同)的 servlet。



A common use-case is in Spring Security, where authentication and access control functionality is typically implemented as filters that sit in front of the main application servlets. When a request is dispatched using a request dispatcher, it has to go through the filter chain again (or possibly a different one) before it gets to the servlet that is going to deal with it. The problem is that some of the security filter actions should only be performed once for a request. Hence the need for thisfilter.

一个常见的用例是在 Spring Security 中,其中身份验证和访问控制功能通常被实现为位于主应用程序 servlet 前面的过滤器。当使用请求调度器调度请求时,它必须再次通过过滤器链(或可能是不同的过滤器链),然后才能到达将要处理它的 servlet。问题是某些安全过滤器操作只应针对一个请求执行一次。因此需要这个过滤器。

回答by Arman

To understand the role of OncePerRequestFilter, we need to first clearly understand how a normal filter behaves. When you want some specific code to execute just before or after servlet execution, you create a filter which works as:

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

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

So code1 executes before servlet and code2 after servlet execution. But here, while servlet execution, there can be some other request to a different servlet and that different servlet is also having this same filter. In this case, this filter will execute again.

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

OncePerRequestFilterprevents this behavior. For our one request, this filter will execute exactly one time (no more no less). This behavior is very useful while working with security authentication.

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

回答by Nilesh

A special kind of GenericFilterBean was introduced to live in Servlet 3.0 environment. This version added a possibility to treat the requests in separate threads. To avoid multiple filters execution for this case, Spring Web project defines a special kind of filter, OncePerRequestFilter. It extends directly GenericFilterBean and, as this class, is located in org.springframework.web.filter package. OncePerRequestFilter defines doFilter method. Inside it checks if given filter was already applied by looking for "${className}.FILTER" attribute corresponding to true in request's parameters. In additionally, it defines an abstract doFilterInternal((HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) method. Its implementations will contain the code to execute by given filter if the filter hasn't been applied.

在 Servlet 3.0 环境中引入了一种特殊的 GenericFilterBean。此版本增加了在单独的线程中处理请求的可能性。为了避免这种情况下执行多个过滤器,Spring Web 项目定义了一种特殊的过滤器,OncePerRequestFilter。它直接扩展 GenericFilterBean 并且作为此类,位于 org.springframework.web.filter 包中。OncePerRequestFilter 定义了 doFilter 方法。在它内部,通过在请求的参数中查找与 true 对应的“${className}.FILTER”属性来检查是否已经应用了给定的过滤器。此外,它还定义了一个抽象的 doFilterInternal((HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) 方法。如果过滤器没有,它的实现将包含由给定过滤器执行的代码

回答by Prashant Chamoli

Under what circumstances a Filter may possibly be executed more than once per request?

在什么情况下,每个请求可能会多次执行过滤器?



A filter may be invoked as part of a REQUEST or ASYNC dispatches that occur in separate threads. We should use OncePerRequestFilter since we are doing a database call to retrieve the principal or the authenticated user, there is no point in doing this more than once. After that, we set the principal to the security context.

过滤器可以作为在单独线程中发生的 REQUEST 或 ASYNC 调度的一部分被调用。我们应该使用OncePerRequestFilter,因为我们正在执行数据库调用来检索主体或经过身份验证的用户,因此多次执行此操作毫无意义。之后,我们将主体设置为安全上下文。

Authentication auth = jwtTokenProvider.getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(auth);

where jwtTokenProvider is your service for getting authentication from the jwt token.

其中 jwtTokenProvider 是您从 jwt 令牌获取身份验证的服务。