Tomcat 的整體結構圖: java
Connector | Container |
---|---|
負責和外界取得聯繫,即創建鏈接(一個Connetor組件只能處理一種請求協議,例如一個Connector組件不能既處理http方式的請求又能處理https請求,所以須要多個Connector組件。) | 負責處理Connector接受的請求,主要是處理內部事務(Container包含了Engine,Host,Context,Wrapper四個組件,負責處理請求相關的邏輯) |
Service 只是在 Connector 和 Container 外面多包一層,把它們組裝在一塊兒,對外提供服務,一個 Service 能夠設置多個 Connector,可是隻能有一個 Container 容器。 Server控制Tomcat的整個生命週期。數組
Service接口 | Lifecycle接口 |
---|---|
關聯Connector和Container,同時初始化它下面的其餘組件 | 控制全部組件的生命週期 |
StandardService實現了Service接口和Lifecycle接口,這樣它就能夠控制它下面組件的生命週期了;除了對Service和Lifecycle接口方法的實現它還有幾個方法是用於事件監聽方法的實現。app
圖 Service 接口 性能
源碼剖析:
下面看一下 StandardService 中主要的幾個方法實現的代碼,下面是 setContainer 和 addConnector 方法的源碼:
清單 1. StandardService. SetContainerthis
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. addConnectorspa
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 方法,這個方法也很簡單,首先是設置關聯關係,而後是初始化工做,開始新的生命週期。code
注意: Connector 用的是數組而不是 List 集合,這個從性能角度考慮能夠理解,有趣的是這裏用了數組可是並無向咱們日常那樣,一開始就分配一個固定大小的數組,它這裏的實現機制是:從新建立一個當前大小的數組對象,而後將原來的數組對象 copy 到新的數組中,這種方式實現了相似的動態數組的功能,這種實現方式,值得咱們之後拿來借鑑。cdn
Server 的任務:就是要可以提供一個接口讓其它程序可以訪問到這個 Service 集合、同時要維護它所包含的全部 Service 的生命週期,包括如何初始化、如何結束服務、如何找到別人要訪問的 Service。對象
Server 類結構圖 blog
它的標準實現類 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 中也是沒有什麼變化的。