概況:
Tomcat 的總體結構圖:
作為大天朝子民的我們不難發現圖中Tomcat的兩個核心元件:Connector 和 ContainerConnector | Container |
---|---|
負責和外界取得聯絡,即建立連線(一個Connetor元件只能處理一種請求協議,例如一個Connector元件不能既處理http方式的請求又能處理https請求,因此需要多個Connector元件。) | 負責處理Connector接受的請求,主要是處理內部事務(Container包含了Engine,Host,Context,Wrapper四個元件,負責處理請求相關的邏輯) |
Service 只是在 Connector 和 Container 外面多包一層,把它們組裝在一起,對外提供服務,一個 Service 可以設定多個 Connector,但是隻能有一個 Container 容器。 Server控制Tomcat的整個生命週期。
認識 StandardService:
Service介面 | Lifecycle介面 |
---|---|
關聯Connector和Container,同時初始化它下面的其他元件 | 控制所有元件的生命週期 |
StandardService實現了Service介面和Lifecycle介面,這樣它就可以控制它下面元件的生命週期了;除了對Service和Lifecycle介面方法的實現它還有幾個方法是用於事件監聽方法的實現。
圖 Service 介面
圖 StandardService 類原始碼剖析:
下面看一下 StandardService 中主要的幾個方法實現的程式碼,下面是 setContainer 和 addConnector 方法的原始碼:
清單 1. StandardService. SetContainer
public void setContainer(Container container) {
Container oldContainer = this.container;
if ((oldContainer != null) && (oldContainer instanceof Engine))
((Engine) oldContainer).setService(null);
this.container = container;
if ((this.container != null) && (this.container instanceof Engine))
((Engine) this.container).setService(this);
if (started && (this.container != null) && (this.container instanceof Lifecycle)) {
try {
((Lifecycle) this.container).start();
} catch (LifecycleException e) {
;
}
}
synchronized (connectors) {
for (int i = 0; i < connectors.length; i++)
connectors[i].setContainer(this.container);
}
if (started && (oldContainer != null) && (oldContainer instanceof Lifecycle)) {
try {
((Lifecycle) oldContainer).stop();
} catch (LifecycleException e) {
;
}
}
support.firePropertyChange("container", oldContainer, this.container);
}
複製程式碼
這段程式碼很簡單,其實就是先判斷當前的這個 Service 有沒有已經關聯了 Container,如果已經關聯了,那麼去掉這個關聯關係—— oldContainer.setService(null)。如果這個 oldContainer 已經被啟動了,結束它的生命週期。然後再替換新的關聯、再初始化並開始這個新的 Container 的生命週期。最後將這個過程通知感興趣的事件監聽程式。
清單 2. StandardService. addConnector
public void addConnector(Connector connector) {
synchronized (connectors) {
connector.setContainer(this.container);
connector.setService(this);
Connector results[] = new Connector[connectors.length + 1];
System.arraycopy(connectors, 0, results, 0, connectors.length);
results[connectors.length] = connector;
connectors = results;
if (initialized) {
try {
connector.initialize();
} catch (LifecycleException e) {
e.printStackTrace(System.err);
}
}
if (started && (connector instanceof Lifecycle)) {
try {
((Lifecycle) connector).start();
} catch (LifecycleException e) {
;
}
}
support.firePropertyChange("connector", null, connector);
}
}
複製程式碼
上面是 addConnector 方法,這個方法也很簡單,首先是設定關聯關係,然後是初始化工作,開始新的生命週期。
注意: Connector 用的是陣列而不是 List 集合,這個從效能角度考慮可以理解,有趣的是這裡用了陣列但是並沒有向我們平常那樣,一開始就分配一個固定大小的陣列,它這裡的實現機制是:重新建立一個當前大小的陣列物件,然後將原來的陣列物件 copy 到新的陣列中,這種方式實現了類似的動態陣列的功能,這種實現方式,值得我們以後拿來借鑑。
認識StandardServer
Server 的任務:就是要能夠提供一個介面讓其它程式能夠訪問到這個 Service 集合、同時要維護它所包含的所有 Service 的生命週期,包括如何初始化、如何結束服務、如何找到別人要訪問的 Service。
Server 類結構圖
它的標準實現類 StandardServer 實現了上面這些方法,同時也實現了 Lifecycle、MbeanRegistration 兩個介面的所有方法,下面主要看一下 StandardServer 重要的一個方法 addService 的實現:
public void addService(Service service) {
service.setServer(this);
synchronized (services) {
Service results[] = new Service[services.length + 1];
System.arraycopy(services, 0, results, 0, services.length);
results[services.length] = service;
services = results;
if (initialized) {
try {
service.initialize();
} catch (LifecycleException e) {
e.printStackTrace(System.err);
}
}
if (started && (service instanceof Lifecycle)) {
try {
((Lifecycle) service).start();
} catch (LifecycleException e) {
;
}
}
support.firePropertyChange("service", null, service);
}
}
複製程式碼
從上面第一句就知道了 Service 和 Server 是相互關聯的,Server 也是和 Service 管理 Connector 一樣管理它,也是將 Service 放在一個陣列中,後面部分的程式碼也是管理這個新加進來的 Service 的生命週期。Tomcat6 中也是沒有什麼變化的。