溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

責任鏈模式及Filter的工作原理是什么

發(fā)布時間:2021-12-03 10:31:01 來源:億速云 閱讀:121 作者:柒染 欄目:大數據

今天就跟大家聊聊有關 責任鏈模式及Filter的工作原理是什么,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。

每個軟件工程師的詞典中,各種高大上的詞不少,也可能因為使用開發(fā)語言與環(huán)境的差異有所不同,但也有不少是超越語言的。

像音樂家常說

音樂是沒有國界的。

而對于軟件工程師,則無論是JAVA工程師,C#工程師,都會了解設計模式。

設計模式是沒有開發(fā)語言界限的,是面向對象的經驗提煉出來,解決重復問題的設計方法。

關于設計模式,有許多經典的著作,像Gof的設計模式,像Robert.C.Martin的

P.P.P。而分析開源項目中對于設計模式的書籍則不多。我接下來打算寫一系列分析Tomcat內設計模式使用的文章,本文是第一篇,先介紹責任鏈模式在Tomcat中的使用。

介紹 

Chain of Refponsibility(責任鏈),是一種對象行為模式。

在Gof的設計模式一書中,對于該模式的意圖描述如下:

使多個對象都有機會處理請求,從而避免請求的發(fā)送者和接收者之間的耦合關系。將這個對象連成一條鏈,并沿著這條鏈傳遞請求,直到有一個對象處理它為止。

對于該模式的理解,最主要的是了解其一直在向下傳遞一個對象,閻宏曾在書中以擊鼓傳花來描述此模式。在Web應用中,這個傳的花就是請求。

了解了模式之后,我們看Tomcat中對于此模式是如何實現的。

在Filter的使用中,我們會注意到其接口中包含這樣一個方法

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

我們看到,這個方法中,除了向下傳遞請遞request和response之外,還傳了另一個FilterChain對象。每次當前Filter的邏輯處理完成后,我們一般會調用FilterChain的doFilter方法,以執(zhí)行下一個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執(zhí)行完畢后,FilterChain的doFilter是如何確認下一個Filter該誰去執(zhí)行了呢?

奧秘就在這里,即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都執(zhí)行完成后,pos < n 的邏輯不再執(zhí)行,跳到執(zhí)行后面真正的Servlet的請求處理。

而每個Filter,可以在filterChain執(zhí)行前后分別進行預處理后處理。是因為每個filter調用,最后類似于遞歸調用,在filter的doFilter執(zhí)行完畢后邏輯中會有return操作,保證不向下執(zhí)行到Servlet的邏輯中。

了解了Filter的執(zhí)行原理以及責任鏈模式的基本概念,我們自己要使用這個模式,只需要保證各個鏈實現相同的接口,接口方法中每次將Chain傳遞下去,即可很好的實現??刂艭hain執(zhí)行的邏輯中,可以通過數組或者List來存儲整個鏈的元素,像Tomcat這樣:

/**
* Filters.
*/
private ApplicationFilterConfig[] filters =
   new ApplicationFilterConfig[0];

在控制中,每次取出下一個元素執(zhí)行,就可以實現責任鏈了。

看完上述內容,你們對 責任鏈模式及Filter的工作原理是什么有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業(yè)資訊頻道,感謝大家的支持。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI