Dev Study
← Spring コース

52. DispatcherServlet と組み込み Tomcat

4.1.1 に を入れて から起動すると、同じプロセスで 11.0.24 がポートを開きます。登録される は 1つで、対応づけは / です。リクエストは Tomcat の、、DispatcherServlet と通り、最後に自分のがで呼ばれます。

Servlet の回では、アプリを にして Tomcat の中へ置きました。ここでは向きが逆で、Tomcat がアプリの の1つです。ただし Tomcat から見える相手は今も Servlet で、 は丸ごとその1つの Servlet の中にいます。リファレンスはこれをと呼び、中央の Servlet が共通の手順を持ち、実際の仕事は差し替えられる部品に任せると説明しています。

戻り値を JSON にするのは、その部品の1つである (を呼び出す係)が内部に持つ です。この最小アプリでは6つあり、JSON の担当は JacksonJsonHttpMessageConverter( 3.1.5)でした。ハンドラまでのフレームは44でしたが、これはこの版と構成での数で、フィルタを足すと増えます。

点線の付いた語はタップすると説明が出ます。用語集を開く →

1つのリクエストが通る層(Boot 4.1.1 の最小アプリで取ったスタックトレースをもとに作図)
クライアントGET /books/42
接続を受ける
Tomcat のスレッド1本http-nio-8080-exec-N
以下はすべてこのスレッドの上で進む
HTTP/1.1 を解釈する
Http11ProcessorTomcat
CoyoteAdapter と Valve 群Tomcat
フィルタを順に通す
ApplicationFilterChainSpring のフィルタ3つ + Tomcat の WsFilter
HttpServlet.service
DispatcherServlet/ に登録された、ただ1つの Servlet
ここから内側が Spring MVC
URL に合うメソッドを探して呼ぶ
RequestMappingHandlerAdapterハンドラを呼び出す係
Method.invokeリフレクション
BookController.book(42)自分のコード
戻り値を HttpMessageConverter に渡す
JacksonJsonHttpMessageConverterBook を JSON にして応答へ書く
  • ・フィルタは characterEncodingFilter、formContentFilter、requestContextFilter の3つが /* に登録されていました
  • ・DispatcherServlet の初期化は起動時ではなく、最初のリクエストを処理するスレッドの上で行われました
  • ・コントローラにプロキシが掛かっている場合の形は、このコースでは取っていません

サンプルコード(フレームワーク環境が必要なため表示のみ)

// WebApp.java(抜粋)— Spring Boot 4.1.1 / spring-boot-starter-webmvc
// ポートを開く処理も、JSON に変換する処理も、ここには書いていない
record Book(long id, String title, List<String> tags) {}

@SpringBootApplication
public class WebApp {
    public static void main(String[] args) {
        SpringApplication.run(WebApp.class, args);   // この中で Tomcat 11.0.24 が起動する
    }
}

@RestController
class BookController {
    @GetMapping("/books/{id}")
    Book book(@PathVariable long id) {
        return new Book(id, "Spring in Depth", List.of("java", "spring"));   // record を返すだけ
    }
}

// $ curl -i localhost:18080/books/42   (応答のうち Date の行は省略)
// HTTP/1.1 200
// Content-Type: application/json
// Content-Length: 60
//
// {"id":42,"title":"Spring in Depth","tags":["java","spring"]}
//
// このときの DEBUG ログ(行頭の時刻などを落とした抜粋)
// DEBUG [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : GET "/books/42", parameters={}
// DEBUG [nio-8080-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to l19.web.BookController#book(long)
// DEBUG [nio-8080-exec-1] m.m.a.RequestResponseBodyMethodProcessor : Using 'application/json', given [*/*] and supported [application/json, application/*+json]
// DEBUG [nio-8080-exec-1] m.m.a.RequestResponseBodyMethodProcessor : Writing [Book[id=42, title=Spring in Depth, tags=[java, spring]]]

図やコードに出てくる用語(タップで説明)

サンプルコードで身につける(5本) →

学んだ概念を、素朴な例から実務寄りの例まで5つの具体例で確認します。

公式ドキュメントで詳しく ↗