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 / 設計まわりの話題をつぶやきがちです。
Discussion