【Tomcat9原始碼分析】Container、Pipeline和Vavle設計
阿新 • • 發佈:2019-01-02
1 概述
如果你對Tomcat的整個框架、元件、請求流程不熟悉,建議你先閱讀以下3篇Tomcat概述性的文章,再來看本篇文章:
Container是Tomcat中很重要的容器,主要包含Engine、Host、Context和Wrapper,其採用了責任鏈的設計模式,來處理一次請求。
2 Container分析
Container
是一個介面,Tomcat提供了ContainerBase
作為其實現的基類。
2.1 欄位
public abstract class ContainerBase implements Container {
// 子容器
protected final HashMap<String, Container> children = new HashMap<>();
// 監聽事件
protected final List<ContainerListener> listeners = new CopyOnWriteArrayList<>();
// Container對應的Pipeline
protected final Pipeline pipeline = new StandardPipeline(this);
// 領域物件
private volatile Realm realm = null;
}
2.2 啟動
public abstract class ContainerBase implements Container {
@Override
protected synchronized void startInternal() throws LifecycleException {
// 1 啟動領域物件
Realm realm = getRealmInternal();
if (realm instanceof Lifecycle) {
((Lifecycle) realm).start();
}
// 2 啟動子容器
Container children[] = findChildren();
List<Future<Void>> results = new ArrayList<>();
for (int i = 0; i < children.length; i++) {
results.add(startStopExecutor.submit(new StartChild(children[i])));
}
// 3 啟動Pipeline
if (pipeline instanceof Lifecycle)
((Lifecycle) pipeline).start();
// 4 設定狀態,啟動本執行緒
setState(LifecycleState.STARTING);
threadStart();
}
}
- 啟動領域物件
- 啟動子容器
- 啟動Pipeline
- 設定狀態,啟動本執行緒
3 Pipeline分析
Pipeline
是一個介面,其實現類是StandardPipeline
。
public class StandardPipeline extends LifecycleBase implements Pipeline {
// 基礎閥門
protected Valve basic = null;
// 關聯的容器
protected Container container = null;
// 第一個閥門
protected Valve first = null;
@Override
protected synchronized void startInternal() throws LifecycleException {
Valve current = first;
if (current == null) {
current = basic;
}
// 依次啟動所有Value,Value是一個連結串列結構
while (current != null) {
if (current instanceof Lifecycle)
((Lifecycle) current).start();
current = current.getNext();
}
setState(LifecycleState.STARTING);
}
}
4 Valve分析
Valve
是一個介面,其基本實現的BaseValve
類。
public abstract class ValveBase extends LifecycleMBeanBase implements Contained, Valve {
// 關聯的Container
protected Container container = null;
// 下一個Valve
protected Valve next = null;
@Override
public Container getContainer() {
return container;
}
// 初始化
@Override
protected void initInternal() throws LifecycleException {
super.initInternal();
containerLog = getContainer().getLogger();
}
// 啟動
@Override
protected synchronized void startInternal() throws LifecycleException {
setState(LifecycleState.STARTING);
}
}
5 幾個重要的Valve
5.1 StandardEngineValve
final class StandardEngineValve extends ValveBase {
public final void invoke(Request request, Response response)
throws IOException, ServletException {
// 1 由request獲取host
Host host = request.getHost();
if (host == null) {
// ...省略
return;
}
// 2 呼叫host的pipeline的vavle
host.getPipeline().getFirst().invoke(request, response);
}
}
- 根據request定位到可以處理的host物件
- 依次呼叫host裡的pipeline上的valve
5.2 StandardEngineValve
final class StandardHostValve extends ValveBase {
public final void invoke(Request request, Response response)
throws IOException, ServletException {
// 1 由request獲取context
Context context = request.getContext();
try {
// 2 呼叫context裡的pipeline上的valve
context.getPipeline().getFirst().invoke(request, response);
// response已經返回
response.setSuspended(false);
Throwable t = (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
// 3 如果有錯誤,重定向到錯誤頁
if (response.isErrorReportRequired()) {
if (t != null) {
throwable(request, response, t);
} else {
status(request, response);
}
}
}
}
}
- 由request獲取context
- 呼叫context裡的pipeline上的valve
- 如果有錯誤,重定向到錯誤頁
5.3 StandardContextValve
final class StandardContextValve extends ValveBase {
@Override
public final void invoke(Request request, Response response)
throws IOException, ServletException {
// 由request獲取wrapper
Wrapper wrapper = request.getWrapper();
// ...省略
// 呼叫wrapper裡的pipeline上的valve
wrapper.getPipeline().getFirst().invoke(request, response);
}
}
- 由request獲取wrapper
- 呼叫wrapper裡的pipeline上的valve
5.4 StandardWrapperValve
final class StandardWrapperValve extends ValveBase {
public final void invoke(Request request, Response response)
throws IOException, ServletException {
// 1 獲取wrapper, context
StandardWrapper wrapper = (StandardWrapper) getContainer();
Servlet servlet = null;
Context context = (Context) wrapper.getParent();
// 2 載入servlet
try {
if (!unavailable) {
servlet = wrapper.allocate();
}
} // ...省略catch
// 3 新建一個 filter 連結串列
ApplicationFilterChain filterChain =
ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);
// servlet會放在 filter 連結串列最後,並且最後會呼叫servlet的service方法
try {
if ((servlet != null) && (filterChain != null)) {
// Swallow output if needed
if (context.getSwallowOutput()) {
// 4 呼叫 filter 連結串列上的 doFilter
filterChain.doFilter(request.getRequest(),
response.getResponse());
}
}
} // ...省略catch
}
}
- 獲取wrapper, context
- 載入servlet
- 新建一個 filter 連結串列,servlet會放在 filter 連結串列最後,並且最後會呼叫servlet的service方法
- 呼叫 filter 連結串列上的 doFilter