🐈

Tomcat のルーティングと Spring Boot のルーティングの違いを整理する

に公開

1. はじめに

Tomcat の主要コンポーネントを調査していた際、以下のような記述に出会いました。

StandardContext#initInternal() の中で ContextConfig(LifecycleListener)が動く。主に

  • web.xml(グローバル+アプリ両方)
  • @WebServlet / @WebFilter / @WebListener 等アノテーションスキャン
  • ServletContainerInitializer(SPI)

を処理して Servlet 定義を Wrapper として実体化する。

このとき、ふと @WebServlet@RestController の違いを明確に説明できないことに気づきました。

調査の結果をざっくりまとめると、

  • Tomcat では Servlet 単位でルーティングされる
  • Spring Boot (Spring MVC) では Controller メソッド単位でルーティングされる

というシンプルな違いに整理できました。本記事ではそれぞれのルーティングの仕組みを具体例とともにざっくりと整理していきます。

2. Tomcat におけるルーティングの仕組み

Servlet とは

Servlet は Java EE 仕様で定義されたコンポーネントで、HttpServlet を継承してリクエストを処理します。

例えば次のように @WebServlet を付与すると、/hello へのリクエストはこのクラスへルーティングされます。

import jakarta.servlet.http.*;
import jakarta.servlet.annotation.*;

@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
        resp.setContentType("text/plain");
        try {
            resp.getWriter().println("Hello from Servlet!");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Wrapper の役割

Tomcat の内部では Servlet を Wrapper というオブジェクトで管理します。

  • URL パターン /hello に対して Wrapper が登録される
  • リクエストが来ると、Wrapper が該当する Servlet を呼び出す

つまりルーティングの流れは次のとおりです。

リクエストURL → Wrapper → Servlet

3. Spring Boot (Spring MVC) におけるルーティング

DispatcherServlet の存在

Spring Boot では通常、Servlet は DispatcherServlet ひとつしか登録されません。
(spring-webmvc が自動的に登録してくれます)

Controller メソッド単位のルーティング

DispatcherServlet がすべてのリクエストを受け取り、アノテーションで定義された Controller メソッドへ振り分けます。

import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/hello")
public class HelloController {
    @GetMapping
    public String sayHello() {
        return "Hello from Controller!";
    }
}

ルーティングの流れは次のとおりです。

リクエストURL → DispatcherServlet → Controller メソッド

4. Tomcat と Spring Boot の対比

特徴 Tomcat (Servlet) Spring Boot (Spring MVC)
ルーティングの単位 Servlet クラス Controller メソッド
エントリポイント Wrapper が Servlet を呼び出す DispatcherServlet が Controller に委譲
設定方法 @WebServlet / web.xml @RestController + @RequestMapping

Spring Boot は Tomcat を内部で利用していますが、独自のルーティングレイヤーを追加することで、より細かな(メソッド単位の)ルーティングを実現 と理解できます!

5. まとめ

  • Tomcat:Wrapper 経由で Servlet 単位にルーティングされる
  • Spring Boot:DispatcherServlet 経由で Controller メソッド単位にルーティングされる
  • どちらも Servlet コンテナを前提にしているが、リクエストを処理する単位が異なる

この違いを押さえておくと、Spring Boot が Tomcat の上にどのような抽象化レイヤーを築いているのか も見えてくるはずです!

6. 最後に

この記事が Tomcat と Spring Boot の違いを整理するヒントになれば幸いです。

もし興味を持っていただけたら、ぜひ X (旧 Twitter) でも繋がりましょう!
普段は Spring Boot / Kotlin / AWS / 設計まわりの話題をつぶやきがちです。

👉 https://x.com/morizoe_bloomer

Discussion