文档说org.springframework.web.filter.OncePerRequestFilter
“保证每个请求只执行一次”。在什么情况下,每个请求可能多次执行过滤器?
Answers:
在什么情况下,每个请求可能多次执行过滤器?
您可以多次将过滤器放在过滤器链上。
可以使用请求分派器将请求分派到其他(或相同)的servlet。
一个常见的用例是在Spring Security中,其中身份验证和访问控制功能通常被实现为位于主应用程序servlet前面的过滤器。当使用请求分派器分派一个请求时,它必须再次经过过滤器链(或者可能是另一个过滤器),然后才能到达要处理的servlet。问题在于,某些安全筛选器操作仅应针对请求执行一次。因此,需要此过滤器。
要了解OncePerRequestFilter的作用,我们需要首先清楚地了解普通过滤器的行为。当您希望在Servlet执行之前或之后执行某些特定代码时,可以创建一个过滤器,其工作方式如下:
code1 ===> servlet execution (using chain.doFilter()) ===> code2
因此,code1在servlet之前执行,而code2在servlet执行之后。但是在这里,在执行servlet时,可能会向其他servlet发出其他请求,并且不同的servlet也具有相同的过滤器。在这种情况下,此过滤器将再次执行。
OncePerRequestFilter防止此行为。对于我们的一个请求,此过滤器将恰好执行一次(不多不少)。使用安全认证时,此行为非常有用。
this request can be allowed to hit your APIs.
@arman,您能否引用任何示例,为什么我们要从一个api调用中调用其他api-当servlet收到请求时,我们可以调用其他层,例如service / dao等,但这就是java调用。如果您详细说明您的答案或评论,将会更容易理解。
在什么情况下,每个请求可能多次执行过滤器?
过滤器可以作为在单独线程中发生的REQUEST或ASYNC调度的一部分来调用。我们应该使用OncePerRequestFilter,因为我们正在进行数据库调用以检索主体或已认证的用户,这样做没有意义。之后,我们将主体设置为安全上下文。
Authentication auth = jwtTokenProvider.getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(auth);
其中jwtTokenProvider是用于从jwt令牌获取身份验证的服务。
引入了一种特殊的GenericFilterBean以生活在Servlet 3.0环境中。该版本增加了在单独的线程中处理请求的可能性。为了避免在这种情况下执行多个过滤器,Spring Web项目定义了一种特殊的过滤器OncePerRequestFilter。它直接扩展GenericFilterBean,并且作为此类,位于org.springframework.web.filter包中。OncePerRequestFilter定义doFilter方法。在其内部,通过查找与请求参数中的true对应的“ $ {className} .FILTER”属性,检查给定的过滤器是否已应用。另外,它定义了一个抽象的doFilterInternal((HttpServletRequest请求,HttpServletResponse响应,FilterChain filterChain)方法。如果过滤器没有执行,则其实现将包含要由给定过滤器执行的代码。