首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

深入理解 Tomcat:從零手寫簡易 HTTP 服務器

     編輯:Java 綜合教學

深入理解 Tomcat:從零手寫簡易 HTTP 服務器

做過 Java Web 的同學對 Tomcat 再熟悉不過。但在享受其便利時,是否思考過 Tomcat 內部如何運作?本質上 Tomcat 是一個 HTTP 服務器,本文將帶你從零構建一個簡易 HTTP 服務器,窺探核心原理。

1. Catalina 核心模型

Tomcat 核心是 Servlet 容器,代號 Catalina。核心組件:

  • Connector:接收 HTTP 請求,構造 Request/Response 對象,委派給容器
  • Container:接收請求對象,載入 Servlet、驗證用戶、管理 Session,最後調用 service()

這只是冰山一角,容器內部還涉及類加載、安全驗證、會話管理等大量工作。以此為藍圖,開始構建之旅。

2. 簡易服務器架構設計

功能點

  1. 接收 HTTP 請求的類
  2. 自定義 Request/Response 封裝請求響應
  3. 根據 URL 決定:返回靜態資源 或 轉發至 Servlet
  4. Servlet 執行業務邏輯

UML 類圖

UML 類圖

2.1 HttpServer - 入口與調度

public class HttpServer {
    private static final String SHUTDOWN_COMMAND = "/SHUTDOWN";
    private static boolean shutdown = false;

    public static void main(String[] args) {
        new HttpServer().await();
    }

    public void await() {
        ServerSocket serverSocket = null;
        int port = 8080;
        try {
            serverSocket = new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"));
        } catch (IOException e) { e.printStackTrace(); System.exit(1); }

        while (!shutdown) {
            Socket socket = null;
            InputStream input = null;
            OutputStream output = null;
            try {
                socket = serverSocket.accept();
                input = socket.getInputStream();
                output = socket.getOutputStream();

                Request request = new Request(input);
                request.parseUrl();

                Response response = new Response(output);
                response.setRequest(request);

                if (request.getUri().startsWith("/v2/")) {
                    new ServletProcessor().process(request, response);
                } else {
                    new StaticResourceProcessor().process(request, response);
                }
                socket.close();
                shutdown = request.getUri().equals(SHUTDOWN_COMMAND);
            } catch (Exception e) { e.printStackTrace(); System.exit(1); }
        }
    }
}

關鍵點:ServerSocket 監聽端口,accept() 阻塞等待連接,返回 Socket 進行通信。構造 Request/Response,按 URI 分發處理器。

2.2 Request / Response - 封裝請求響應

Request 實現 ServletRequest,核心 parseUrl() 讀取輸入流,解析請求行獲取 URI。

Response 實現 ServletResponse,核心 sendStaticResource() 根據 URI 讀取本地文件輸出,或返回 404。

2.3 PrimitiveServlet - 示例 Servlet

public class PrimitiveServlet implements Servlet {
    public void service(ServletRequest req, ServletResponse res) {
        PrintWriter out = res.getWriter();
        out.println("Hello. Roses are red.");
        out.print("Violets are blue.");
    }
    // 生命週期方法略
}

2.4 處理器:ServletProcessor & StaticResourceProcessor

  • ServletProcessor:根據 URI 反射實例化 Servlet,調用 service()
  • StaticResourceProcessor:委派 Response.sendStaticResource()

2.5 Constants - 靜態資源根目錄

public class Constants {
    public static final String WEB_ROOT = System.getProperty("user.dir") + File.separator + "webroot";
}

3. 啟動驗證

  1. 啟動 HttpServer.main()
  2. 瀏覽器訪問 https://localhost:8080/test → 返回 webroot/test 文件內容
  3. 訪問 https://localhost:8080/v2/PrimitiveServlet → 輸出 Servlet 定義的文字

靜態資源訪問效果 Servlet 訪問效果

4. 總結

雖功能簡陋,但通過這個最小模型,可清晰理解:

  • Socket 接收請求
  • Request/Response 封裝協議細節
  • 靜態資源與動態 Servlet 分發
  • Servlet 生命週期管理

這正是 Tomcat 核心架構的縮影。參考資料:《深入剖析 Tomcat》。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved