Tomcat 源碼分析(二)——Request處理全過程


前一篇博客,我總結了Tomcat對於生命周期組件的管理。在了解了容器的啟動之后,我們開始剖析它的內部運行機制。今天我們來分析一下Tomcat如何處理Request。Socket作為網絡通信的基礎也是Request和Response的底層實現,有過Socket使用經驗的讀者一定不會對下面的偽代碼陌生:

// Java偽代碼
...
while(true) {
    Socket soc = ServerSocket.accept(); // 監聽並阻塞
    new Thread(new Runnable() {  // 開辟新的線程處理Socket
        inputStream(soc); // 讀取Socket中的數據
        outputStream(soc); // 寫入數據
    });
}
...

 一、從Socket到Request

Tomcat容器對Socket的處理思路與以上偽代碼基本一致,只是更加復雜。下圖展示了從Tomcat啟動到Socket到來后,主要類的調動過程(虛線箭頭表示有新的線程啟動):

Acceptor是定義在JIoEndpoint中的內部類實現了Runnable接口。在run方法中定義了循環語句while (running){...}重點是ServerSocketFactory獲取監聽端口(默認8080)上的Socket請求

Socket socket = null;
    try {
        // Accept the next incoming connection from the server
        // socket
        socket = serverSocketFactory.acceptSocket(serverSocket);
        ...

 

然后,這個Socket對象會被封裝成SocketWrapper對象並交給給JIoEndpoint的另一個內部類SocketProcessor處理。

protected boolean processSocket(Socket socket) {
    // Process the request from this socket
    try {
        SocketWrapper<Socket> wrapper = new SocketWrapper<Socket>(socket);
        wrapper.setKeepAliveLeft(getMaxKeepAliveRequests());
        wrapper.setSecure(isSSLEnabled());
...

 

一直到AbstractHttp11Processor.process方法,我們第一次見到了Request的身影。不過此時的Request實際上是org.apache.coyote.Request,它是Tomcat內部的定義類並且被final修飾。在CoyoteAdapter.service方法中,它又被處理成:org.apache.catalina.connector.Request,它繼承了HttpServletRequest。直到這時,從Socket到Request才真正完成。

二、Pipeline、FilterChain以及設計模式

ContainerBase是Tomcat中的生命周期組件。它包含了4個標准的實現類:StandardContext、StandardEngine、StandardHost和StandardWrapper。每一個Container對象都含有各自的Pipeline和Valve。

/**
 * The Pipeline object with which this Container is associated.
 */
protected Pipeline pipeline = new StandardPipeline(this);

/**
 * Create a new StandardContext component with the default basic Valve.
 */
public StandardContext() {

    super();
    pipeline.setBasic(new StandardContextValve());
    ...
}
...

 

它們通過Container的構造函數被初始化,並負責處理Request。每一個Containner組件都實現了各自的invoke方法,具體的業務邏輯讀者可以自己去分析。

經過4次invoke,Request會繼續交給FilterChain(責任鏈模式的核心對象)處理。

ApplicationFilterChain filterChain = factory.createFilterChain(request, wrapper, servlet);

try {
    if ((servlet != null) && (filterChain != null)) {
        if (context.getSwallowOutput()) {
            ...
        } else {
             if (request.isAsyncDispatching()) {
                ...
            } else if (comet) {
                ...
            } else {
                filterChain.doFilter(request.getRequest(), response.getResponse());
            }
        }
...

 

經過多個Filter的處理,才會交到Servlet的手中。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM