OncePerRequestFilter原理简介
OncePerRequestFilter是Spring Boot⾥⾯的⼀个过滤器抽象类,其同样在Spring Security⾥⾯被⼴泛⽤到
这个过滤器抽象类通常被⽤于继承实现并在每次请求时只执⾏⼀次过滤,这⾥⾯是如何实现的,我们可以通过源码到答案
public abstract class OncePerRequestFilter extends GenericFilterBean {
//⼀个标记,后⾯会⽤到
public static final String ALREADY_FILTERED_SUFFIX = ".FILTERED";
@Override
public final void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
if (!(request instanceof HttpServletRequest) || !(response instanceof HttpServletResponse)) {
throw new ServletException("OncePerRequestFilter just supports HTTP requests");
}
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
//这⾥获取⼀个名称,该名称后⾯会被⽤于放到request当作key
String alreadyFilteredAttributeName = getAlreadyFilteredAttributeName();
//检测当前请求是否已经拥有了该标记,如果拥有该标记则代表该过滤器执⾏过了(后⾯注释有说明)
boolean hasAlreadyFilteredAttribute = Attribute(alreadyFilteredAttributeName) != null;
if (skipDispatch(httpRequest) || shouldNotFilter(httpRequest)) {
// Proceed without invoking
filterChain.doFilter(request, response);
}
/
/如果此过滤器已经被执⾏过则执⾏如下的逻辑
else if (hasAlreadyFilteredAttribute) {
if (DispatcherType.ERROR.DispatcherType())) {
doFilterNestedErrorDispatch(httpRequest, httpResponse, filterChain);
return;
}
// Proceed without invoking
filterChain.doFilter(request, response);
}springboot原理通俗
//⾛到这⾥说明该过滤器没有被执⾏过
else {
/
/ Do invoke
// 在当前请求⾥⾯设置⼀个标记,key就是前⾯拼接的那个变量,value是true,这个标记如果在request存在则在前⾯会被检测到并改变hasAlreadyFilteredAttribute的值  request.setAttribute(alreadyFilteredAttributeName, Boolean.TRUE);
try {
// 这个⽅法是⼀个抽象⽅法需要⼦类去实现具体的过滤逻辑
doFilterInternal(httpRequest, httpResponse, filterChain);
}
finally {
// Remove the "already filtered" request attribute for this request.
// 执⾏完毕之后移除该标记
}
}
}
//其余代码略
}
以上通过增加标记的⽅式来实现过滤器只被执⾏⼀次

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。