1. 程式人生 > >【Tomcat9原始碼分析】Container、Pipeline和Vavle設計

【Tomcat9原始碼分析】Container、Pipeline和Vavle設計

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(); } }
  1. 啟動領域物件
  2. 啟動子容器
  3. 啟動Pipeline
  4. 設定狀態,啟動本執行緒

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);
    }
}
  1. 根據request定位到可以處理的host物件
  2. 依次呼叫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);
                }
            }
        } 
    }
}
  1. 由request獲取context
  2. 呼叫context裡的pipeline上的valve
  3. 如果有錯誤,重定向到錯誤頁

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);
    }
}
  1. 由request獲取wrapper
  2. 呼叫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
    }
}
  1. 獲取wrapper, context
  2. 載入servlet
  3. 新建一個 filter 連結串列,servlet會放在 filter 連結串列最後,並且最後會呼叫servlet的service方法
  4. 呼叫 filter 連結串列上的 doFilter

5 總結