1. 程式人生 > 其它 >doFilter和doFilterInternal OncePerRequestFilter 顧名思義,它能夠確保在一次請求中只通過一次filter,而不會重複執行,是由Spring提供的抽象類,重寫該介面的dofilterinternal方法,用來記錄每次請求ip mac sessionid和返回報文日誌

doFilter和doFilterInternal OncePerRequestFilter 顧名思義,它能夠確保在一次請求中只通過一次filter,而不會重複執行,是由Spring提供的抽象類,重寫該介面的dofilterinternal方法,用來記錄每次請求ip mac sessionid和返回報文日誌

OncePerRequestFilter
顧名思義,它能夠確保在一次請求中只通過一次filter,而不會重複執行
是由Spring提供的抽象類
https://www.cnblogs.com/sjxbg/p/13475387.html

摘錄自: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;

</span><span style="color: rgba(0, 0, 255, 1)">void</span> doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> IOException, ServletException;

</span><span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> 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() {
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">final</span> <span style="color: rgba(0, 0, 255, 1)">void</span> doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> ServletException, IOException {
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> (request <span style="color: rgba(0, 0, 255, 1)">instanceof</span> HttpServletRequest &amp;&amp; response <span style="color: rgba(0, 0, 255, 1)">instanceof</span><span style="color: rgba(0, 0, 0, 1)"> HttpServletResponse) {
        HttpServletRequest httpRequest </span>=<span style="color: rgba(0, 0, 0, 1)"> (HttpServletRequest)request;
        HttpServletResponse httpResponse </span>=<span style="color: rgba(0, 0, 0, 1)"> (HttpServletResponse)response;
        </span><span style="color: rgba(0, 0, 255, 1)">boolean</span> hasAlreadyFilteredAttribute = request.getAttribute(<span style="color: rgba(0, 0, 255, 1)">this</span>.alreadyFilteredAttributeName) != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
        </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (hasAlreadyFilteredAttribute) {
            filterChain.doFilter(request, response);
        } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
            request.setAttribute(</span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.alreadyFilteredAttributeName, Boolean.TRUE);

            </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
                </span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.doFilterInternal(httpRequest, httpResponse, filterChain);
            } </span><span style="color: rgba(0, 0, 255, 1)">finally</span><span style="color: rgba(0, 0, 0, 1)"> {
                request.removeAttribute(</span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.alreadyFilteredAttributeName);
            }
        }

    } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
        </span><span style="color: rgba(0, 0, 255, 1)">throw</span> <span style="color: rgba(0, 0, 255, 1)">new</span> ServletException("OncePerRequestFilter just supports HTTP requests"<span style="color: rgba(0, 0, 0, 1)">);
    }
}

</span><span style="color: rgba(0, 0, 255, 1)">protected</span> <span style="color: rgba(0, 0, 255, 1)">abstract</span> <span style="color: rgba(0, 0, 255, 1)">void</span> doFilterInternal(HttpServletRequest var1, HttpServletResponse var2, FilterChain var3) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> ServletException, IOException;

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> init(FilterConfig config) {
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> destroy() {
}

}

常識上都認為,一次請求本來就只filter一次,為什麼還要由此特別限定呢?
往往我們的常識和實際的實現並不真的一樣,經過一番資料的查閱,此方法是為了相容不同的web container
也就是說並不是所有的container都入我們期望的只過濾一次,servlet版本不同,執行過程也不同
因此,為了相容各種不同執行環境和版本,預設filter繼承OncePerRequestFilter是一個比較穩妥的選擇。

摘錄自: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;

</span><span style="color: rgba(0, 0, 255, 1)">void</span> doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> IOException, ServletException;

</span><span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> 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() {
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">final</span> <span style="color: rgba(0, 0, 255, 1)">void</span> doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> ServletException, IOException {
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> (request <span style="color: rgba(0, 0, 255, 1)">instanceof</span> HttpServletRequest &amp;&amp; response <span style="color: rgba(0, 0, 255, 1)">instanceof</span><span style="color: rgba(0, 0, 0, 1)"> HttpServletResponse) {
        HttpServletRequest httpRequest </span>=<span style="color: rgba(0, 0, 0, 1)"> (HttpServletRequest)request;
        HttpServletResponse httpResponse </span>=<span style="color: rgba(0, 0, 0, 1)"> (HttpServletResponse)response;
        </span><span style="color: rgba(0, 0, 255, 1)">boolean</span> hasAlreadyFilteredAttribute = request.getAttribute(<span style="color: rgba(0, 0, 255, 1)">this</span>.alreadyFilteredAttributeName) != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
        </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (hasAlreadyFilteredAttribute) {
            filterChain.doFilter(request, response);
        } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
            request.setAttribute(</span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.alreadyFilteredAttributeName, Boolean.TRUE);

            </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
                </span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.doFilterInternal(httpRequest, httpResponse, filterChain);
            } </span><span style="color: rgba(0, 0, 255, 1)">finally</span><span style="color: rgba(0, 0, 0, 1)"> {
                request.removeAttribute(</span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.alreadyFilteredAttributeName);
            }
        }

    } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
        </span><span style="color: rgba(0, 0, 255, 1)">throw</span> <span style="color: rgba(0, 0, 255, 1)">new</span> ServletException("OncePerRequestFilter just supports HTTP requests"<span style="color: rgba(0, 0, 0, 1)">);
    }
}

</span><span style="color: rgba(0, 0, 255, 1)">protected</span> <span style="color: rgba(0, 0, 255, 1)">abstract</span> <span style="color: rgba(0, 0, 255, 1)">void</span> doFilterInternal(HttpServletRequest var1, HttpServletResponse var2, FilterChain var3) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> ServletException, IOException;

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> init(FilterConfig config) {
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> destroy() {
}

}

常識上都認為,一次請求本來就只filter一次,為什麼還要由此特別限定呢?
往往我們的常識和實際的實現並不真的一樣,經過一番資料的查閱,此方法是為了相容不同的web container
也就是說並不是所有的container都入我們期望的只過濾一次,servlet版本不同,執行過程也不同
因此,為了相容各種不同執行環境和版本,預設filter繼承OncePerRequestFilter是一個比較穩妥的選擇。