摘錄自:https://www.jianshu.com/p/3d9b4cfe1a62
doFilter是整個過濾器最底層的概念Filter接口中的方法
所有過濾器都要實現Filter
package javax.servlet; import java.io.IOException; public interface Filter { void init(FilterConfig var1) throws ServletException; void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException; void destroy(); }
而doFilterInternal是OncePerRequestFilter 中的一個抽象方法
閱讀源碼可知:
OncePerRequestFilter.doFilter方法中通過request.getAttribute判斷當前過濾器是否已執行
若未執行過,則調用doFilterInternal方法,交由其子類實現
OncePerRequestFilter
顧名思義,它能夠確保在一次請求中只通過一次filter,而不會重復執行
是由Spring提供的抽象類
package org.springframework.session.web.http; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; abstract class OncePerRequestFilter implements Filter { public static final String ALREADY_FILTERED_SUFFIX = ".FILTERED"; private String alreadyFilteredAttributeName = this.getClass().getName().concat(".FILTERED"); OncePerRequestFilter() { } public final void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException { if (request instanceof HttpServletRequest && response instanceof HttpServletResponse) { HttpServletRequest httpRequest = (HttpServletRequest)request; HttpServletResponse httpResponse = (HttpServletResponse)response; boolean hasAlreadyFilteredAttribute = request.getAttribute(this.alreadyFilteredAttributeName) != null; if (hasAlreadyFilteredAttribute) { filterChain.doFilter(request, response); } else { request.setAttribute(this.alreadyFilteredAttributeName, Boolean.TRUE); try { this.doFilterInternal(httpRequest, httpResponse, filterChain); } finally { request.removeAttribute(this.alreadyFilteredAttributeName); } } } else { throw new ServletException("OncePerRequestFilter just supports HTTP requests"); } } protected abstract void doFilterInternal(HttpServletRequest var1, HttpServletResponse var2, FilterChain var3) throws ServletException, IOException; public void init(FilterConfig config) { } public void destroy() { } }
常識上都認為,一次請求本來就只filter一次,為什么還要由此特別限定呢? 往往我們的常識和實際的實現並不真的一樣,經過一番資料的查閱,此方法是為了兼容不同的web container 也就是說並不是所有的container都入我們期望的只過濾一次,servlet版本不同,執行過程也不同 因此,為了兼容各種不同運行環境和版本,默認filter繼承OncePerRequestFilter是一個比較穩妥的選擇。