Tomcat 系統架構與設計模式_ 設計模式分析

門面設計模式

門面設計模式在 Tomcat 中有多處使用,在 Request 和 Response 對象封裝中、Standard Wrapper 到 ServletConfig 封裝中、ApplicationContext 到 ServletContext 封裝中等都用到了這種設計模式。html

門面設計模式的原理

這麼多場合都用到了這種設計模式,那這種設計模式究竟能有什麼做用呢?顧名思義,就是將一個東西封裝成一個門面好與人家更容易進行交流,就像一個國家的外交部同樣。java

這種設計模式主要用在一個大的系統中有多個子系統組成時,這多個子系統確定要涉及到相互通訊,可是每一個子系統又不能將本身的內部數據過多的暴露給其它系統,否則就沒有必要劃分子系統了。每一個子系統都會設計一個門面,把別的系統感興趣的數據封裝起來,經過這個門面來進行訪問。這就是門面設計模式存在的意義。web

門面設計模式示意圖以下:設計模式

圖 1. 門面示意圖

圖 1. 門面示意圖

Client 只能訪問到 Façade 中提供的數據是門面設計模式的關鍵,至於 Client 如何訪問 Façade 和 Subsystem 如何提供 Façade 門面設計模式並無規定死。tomcat

Tomcat 的門面設計模式示例

Tomcat 中門面設計模式使用的不少,由於 Tomcat 中有不少不一樣組件,每一個組件要相互交互數據,用門面模式隔離數據是個很好的方法。服務器

下面是 Request 上使用的門面設計模式:app

圖 2. Request 的門面設計模式類圖

圖 2. Request 的門面設計模式類圖

從圖中能夠看出 HttpRequestFacade 類封裝了 HttpRequest 接口可以提供數據,經過 HttpRequestFacade 訪問到的數據都被代理到 HttpRequest 中,一般被封裝的對象都被設爲 Private 或者 Protected 訪問修飾,以防止在 Façade 中被直接訪問。spa

回頁首設計

觀察者設計模式

這種設計模式也是經常使用的設計方法一般也叫發佈 - 訂閱模式,也就是事件監聽機制,一般在某個事件發生的先後會觸發一些操做。代理

觀察者模式的原理

觀察者模式原理也很簡單,就是你在作事的時候旁邊總有一我的在盯着你,當你作的事情是它感興趣的時候,它就會跟着作另一些事情。可是盯着你的人必需要到你那去登記,否則你沒法通知它。觀察者模式一般包含下面這幾個角色:

  • Subject 就是抽象主題:它負責管理全部觀察者的引用,同時定義主要的事件操做。

  • ConcreteSubject 具體主題:它實現了抽象主題的全部定義的接口,當本身發生變化時,會通知全部觀察者。

  • Observer 觀察者:監聽主題發生變化相應的操做接口。

Tomcat 的觀察者模式示例

Tomcat 中觀察者模式也有多處使用,前面講的控制組件生命週期的 Lifecycle 就是這種模式的體現,還有對 Servlet 實例的建立、Session 的管理、Container 等都是一樣的原理。下面主要看一下 Lifecycle 的具體實現。

Lifecycle 的觀察者模式結構圖:

圖 3. Lifecycle 的觀察者模式結構圖

圖 3. Lifecycle 的觀察者模式結構圖

上面的結構圖中,LifecycleListener 表明的是抽象觀察者,它定義一個 lifecycleEvent 方法,這個方法就是當主題變化時要執行的方法。 ServerLifecycleListener 表明的是具體的觀察者,它實現了 LifecycleListener 接口的方法,就是這個具體的觀察者具體的實現方式。Lifecycle 接口表明的是抽象主題,它定義了管理觀察者的方法和它要所作的其它方法。而 StandardServer 表明的是具體主題,它實現了抽象主題的全部方法。這裏 Tomcat 對觀察者作了擴展,增長了另外兩個類:LifecycleSupport、LifecycleEvent,它們做爲輔助類擴展了觀察者的功能。LifecycleEvent 使得能夠定義事件類別,不一樣的事件可區別處理,更加靈活。LifecycleSupport 類代理了主題對多觀察者的管理,將這個管理抽出來統一實現,之後若是修改只要修改 LifecycleSupport 類就能夠了,不須要去修改全部具體主題,由於全部具體主題的對觀察者的操做都被代理給 LifecycleSupport 類了。這能夠認爲是觀察者模式的改進版。

LifecycleSupport 調用觀察者的方法代碼以下:

清單 1. LifecycleSupport 中的 fireLifecycleEvent 方法
public void fireLifecycleEvent(String type, Object data) {
    LifecycleEvent event = new LifecycleEvent(lifecycle, type, data);
    LifecycleListener interested[] = null;
    synchronized (listeners) {
        interested = (LifecycleListener[]) listeners.clone();
    }
    for (int i = 0; i < interested.length; i++)
        interested[i].lifecycleEvent(event);
}

主題是怎麼通知觀察者呢?看下面代碼:

清單 2. 容器中的 start 方法
public void start() throws LifecycleException {
    lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
    lifecycle.fireLifecycleEvent(START_EVENT, null);
    started = true;
    synchronized (services) {
        for (int i = 0; i < services.length; i++) {
            if (services[i] instanceof Lifecycle)
                ((Lifecycle) services[i]).start();
            }
        }
    lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
}

回頁首

命令設計模式

前面把 Tomcat 中兩個核心組件 Connector 和 Container,比做一對夫妻。男的將接受過來的請求以命令的方式交給女主人。對應到 Connector 和 Container,Connector 也是經過命令模式調用 Container 的。

命令模式的原理

命令模式主要做用就是封裝命令,把發出命令的責任和執行命令的責任分開。也是一種功能的分工。不一樣的模塊能夠對同一個命令作出不一樣解釋。

下面是命令模式一般包含下面幾個角色:

  • Client:建立一個命令,並決定接受者

  • Command 命令:命令接口定義一個抽象方法

  • ConcreteCommand:具體命令,負責調用接受者的相應操做

  • Invoker 請求者:負責調用命令對象執行請求

  • Receiver 接受者:負責具體實施和執行一次請求

Tomcat 中的命令模式的示例

Tomcat 中命令模式在 Connector 和 Container 組件之間有體現,Tomcat 做爲一個應用服務器,無疑會接受到不少請求,如何分配和執行這些請求是必須的功能。

下面看一下 Tomcat 是如何實現命令模式的,下面是 Tomcat 命令模式的結構圖:

圖 4. Tomcat 命令模式的結構圖

圖 4. Tomcat 命令模式的結構圖

Connector 做爲抽象請求者,HttpConnector 做爲具體請求者。HttpProcessor 做爲命令。Container 做爲命令的抽象接受者,ContainerBase 做爲具體的接受者。客戶端就是應用服務器 Server 組件了。Server 首先建立命令請求者 HttpConnector 對象,而後建立命令 HttpProcessor 命令對象。再把命令對象交給命令接受者 ContainerBase 容器來處理命令。命令的最終是被 Tomcat 的 Container 執行的。命令能夠以隊列的方式進來,Container 也能夠以不一樣的方式來處理請求,如 HTTP1.0 協議和 HTTP1.1 的處理方式就會不一樣。

回頁首

責任鏈模式

Tomcat 中一個最容易發現的設計模式就是責任鏈模式,這個設計模式也是 Tomcat 中 Container 設計的基礎,整個容器的就是經過一個鏈鏈接在一塊兒,這個鏈一直將請求正確的傳遞給最終處理請求的那個 Servlet。

責任鏈模式的原理

責任鏈模式,就是不少對象有每一個對象對其下家的引用而鏈接起來造成一條鏈,請求在這條鏈上傳遞,直到鏈上的某個對象處理此請求,或者每一個對象均可以處理請求,並傳給下一家,直到最終鏈上每一個對象都處理完。這樣能夠不影響客戶端而可以在鏈上增長任意的處理節點。

一般責任鏈模式包含下面幾個角色:

  • Handler(抽象處理者):定義一個處理請求的接口

  • ConcreteHandler(具體處理者):處理請求的具體類,或者傳給下家

Tomcat 中責任鏈模式示例

在 tomcat 中這種設計模式幾乎被完整的使用,tomcat 的容器設置就是責任鏈模式,從 Engine 到 Host 再到 Context 一直到 Wrapper 都是經過一個鏈傳遞請求。

Tomcat 中責任鏈模式的類結構圖以下:

圖 5. Tomcat 責任鏈模式的結構圖

圖 5. Tomcat 責任鏈模式的結構圖

上圖基本描述了四個子容器使用責任鏈模式的類結構圖,對應的責任鏈模式的角色,Container 扮演抽象處理者角色,具體處理者由 StandardEngine 等子容器扮演。與標準的責任鏈不一樣的是,這裏引入了 Pipeline 和 Valve 接口。他們有什麼做用呢?

實際上 Pipeline 和 Valve 是擴展了這個鏈的功能,使得在鏈往下傳遞過程當中,可以接受外界的干預。Pipeline 就是鏈接每一個子容器的管子,裏面傳遞的 Request 和 Response 對象比如管子裏流的水,而 Valve 就是這個管子上開的一個個小口子,讓你有機會可以接觸到裏面的水,作一些額外的事情。

爲了防止水被引出來而不能流到下一個容器中,每一段管子最後總有一個節點保證它必定能流到下一個子容器,因此每一個容器都有一個 StandardXXXValve。只要涉及到這種有鏈式是處理流程這是一個很是值得借鑑的模式。

相關文章
相關標籤/搜索