什么是OncePerRequestFilter?

时间:2012-10-31 07:11:21

标签: spring

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

4 个答案:

答案 0 :(得分:44)

  

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

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

可以使用请求调度程序将请求分派到不同的(或相同的)servlet。


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

答案 1 :(得分:12)

要了解 OncePerRequestFilter 的作用,我们需要首先清楚地了解普通过滤器的行为。 如果要在Servlet执行之前或之后执行某些特定代码,则创建一个过滤器,其工作方式为:

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

因此code1在servlet之前执行,而code2在servlet执行之后。 但是在这里,在执行servlet时,可能会有其他请求发送到不同的servlet,并且该不同的servlet也具有相同的过滤器。 在这种情况下,此过滤器将再次执行。

OncePerRequestFilter 阻止了此行为。对于我们的一个请求,此过滤器将恰好执行一次(不多不少)。使用安全认证时,此行为非常有用。

答案 2 :(得分:2)

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

答案 3 :(得分:0)

  

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


过滤器可以作为在单独线程中发生的REQUEST或ASYNC调度的一部分来调用。我们应该使用OncePerRequestFilter,因为我们正在进行数据库调用以检索主体或已认证的用户,这样做没有意义。之后,我们将主体设置为安全上下文。

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

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