我们发现Spring提供的URL请求Filter,都继承了OncePerRequestFilter类,
这个类是对原生的Filter进行优化,使Filter对请求不会循环调用,而是只调用一次,循环调用的将被忽略。
我们看一下源码:
/**
* This <code>doFilter</code> implementation stores a request attribute for
* "already filtered", proceeding without filtering again if the
* attribute is already there.
* @see #getAlreadyFilteredAttributeName
* @see #shouldNotFilter
* @see #doFilterInternal
*/
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;
String alreadyFilteredAttributeName = getAlreadyFilteredAttributeName();
if (request.getAttribute(alreadyFilteredAttributeName) != null || shouldNotFilter(httpRequest)) {
// Proceed without invoking this filter...
filterChain.doFilter(request, response);
}
else {
// Do invoke this filter...
request.setAttribute(alreadyFilteredAttributeName, Boolean.TRUE);
try {
doFilterInternal(httpRequest, httpResponse, filterChain);
}
finally {
// Remove the "already filtered" request attribute for this request.
request.removeAttribute(alreadyFilteredAttributeName);
}
}
}
这个代码里面,OncePerRequestFilter实现了doFilter方法,并在过滤时,加入alreadyFilteredAttributeName这个属性,通过这个值,判断是不是循环调用了。