您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關 責任鏈模式及Filter的工作原理是什么,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。
每個軟件工程師的詞典中,各種高大上的詞不少,也可能因為使用開發語言與環境的差異有所不同,但也有不少是超越語言的。
像音樂家常說
音樂是沒有國界的。
而對于軟件工程師,則無論是JAVA工程師,C#工程師,都會了解設計模式。
設計模式是沒有開發語言界限的,是面向對象的經驗提煉出來,解決重復問題的設計方法。
關于設計模式,有許多經典的著作,像Gof的設計模式,像Robert.C.Martin的
P.P.P。而分析開源項目中對于設計模式的書籍則不多。我接下來打算寫一系列分析Tomcat內設計模式使用的文章,本文是第一篇,先介紹責任鏈模式在Tomcat中的使用。
介紹
Chain of Refponsibility(責任鏈),是一種對象行為模式。
在Gof的設計模式一書中,對于該模式的意圖描述如下:
使多個對象都有機會處理請求,從而避免請求的發送者和接收者之間的耦合關系。將這個對象連成一條鏈,并沿著這條鏈傳遞請求,直到有一個對象處理它為止。
對于該模式的理解,最主要的是了解其一直在向下傳遞一個對象,閻宏曾在書中以擊鼓傳花來描述此模式。在Web應用中,這個傳的花就是請求。
了解了模式之后,我們看Tomcat中對于此模式是如何實現的。
在Filter的使用中,我們會注意到其接口中包含這樣一個方法
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
我們看到,這個方法中,除了向下傳遞請遞request和response之外,還傳了另一個FilterChain對象。每次當前Filter的邏輯處理完成后,我們一般會調用FilterChain的doFilter方法,以執行下一個Filter的邏輯。這里需要注意的是,可能這個FilterChain的接口方法也叫doFilter容易引起誤解,其實這個方法的聲明如下:
/**
* Causes the next filter in the chain to be invoked, or if the calling
* filter is the last filter in the chain, causes the resource at the end of
* the chain to be invoked.
*/
public void doFilter(ServletRequest request, ServletResponse response);
如果這里稱之為invokeFilter或者executeFilter也許更好理解些。
那么,每一次,一個Filter執行完畢后,FilterChain的doFilter是如何確認下一個Filter該誰去執行了呢?
奧秘就在這里,即FilterChain接口的實現。
/**
* Invoke the next filter in this chain, passing the specified request
* and response. If there are no more filters in this chain, invoke
* the <code>service()</code> method of the servlet itself.
*
*/
public void doFilter(ServletRequest request, ServletResponse response){
if( Globals.IS_SECURITY_ENABLED ) {//注意這里是啟用了SecurityManager,了解詳情可以后臺回復關鍵字003查看。
final ServletRequest req = request;
final ServletResponse res = response;
try {
java.security.AccessController.doPrivileged(
new java.security.PrivilegedExceptionAction<Void>() {
@Override
public Void run()
throws ServletException, IOException {
internalDoFilter(req,res);
return null;
} });
} catch( PrivilegedActionException pe) { }
} else {
internalDoFilter(request,response);//默認每次調用的處理方法在這里
}}
private void internalDoFilter(ServletRequest request,
ServletResponse response){
// Call the next filter if there is one
if (pos < n) {
ApplicationFilterConfig filterConfig = filters[pos++];
Filter filter = null;
filter = filterConfig.getFilter();
filter.doFilter(request, response, this);
return;
}
// We fell off the end of the chain -- call the servlet instance
if ((request instanceof HttpServletRequest) &&
(response instanceof HttpServletResponse)) {
servlet.service(request, response);
} else {
servlet.service(request, response);
}}
我們看到,在真正處理FilterChain的控制中,是通過pos和n這兩個參數來判斷的。兩者的聲明如下:
/**
* The int which is used to maintain the current position
* in the filter chain.
*/
private int pos = 0;
/**
* The int which gives the current number of filters in the chain.
*/
private int n = 0;
我們看到,一個標識當前處理的Filter,一個標識chain中的總filter數。
在chain中的Filter都執行完成后,pos < n 的邏輯不再執行,跳到執行后面真正的Servlet的請求處理。
而每個Filter,可以在filterChain執行前后分別進行預處理和后處理。是因為每個filter調用,最后類似于遞歸調用,在filter的doFilter執行完畢后邏輯中會有return操作,保證不向下執行到Servlet的邏輯中。
了解了Filter的執行原理以及責任鏈模式的基本概念,我們自己要使用這個模式,只需要保證各個鏈實現相同的接口,接口方法中每次將Chain傳遞下去,即可很好的實現。控制Chain執行的邏輯中,可以通過數組或者List來存儲整個鏈的元素,像Tomcat這樣:
/**
* Filters.
*/
private ApplicationFilterConfig[] filters =
new ApplicationFilterConfig[0];
在控制中,每次取出下一個元素執行,就可以實現責任鏈了。
看完上述內容,你們對 責任鏈模式及Filter的工作原理是什么有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。