Spring MVCはURLからどのようにControllerメソッドを選んでいるのか調査してみた

こんにちは。カサレアルで研修講師をしている末永です。

Spring MVCでは、Controllerにアノテーションを付与するだけでURLとメソッドを対応付けられます。

@Controller
@RequestMapping("/employees")
public class EmployeeController {
    @GetMapping
    public String index() {
        return "employees/index";
    }
}

このように、SpringはクラスやメソッドにアノテーションをつけるだけでHTTPリクエストを受け取れます。この時、フレームワークはHTTPリクエストとControllerメソッドをどのように関連付けているのでしょうか。

今回はSpring MVCの内部コードを調べた結果をまとめました。

今回調査したこと

今回確認したかったのは次の流れです。

  1. ブラウザから/employees にアクセスする
  2. Spring MVCがリクエストを受け取る
  3. EmployeeController#index() を特定する
  4. メソッドを実行する

特にどのようにしてControllerメソッドを選んでいるのかに着目しました。

DispatcherServletから処理を追う

Spring内部の動きを追うにあたり、自身が作成したメソッドの呼び出し階層をさかのぼって確認したところ、DispatcherServletクラスにgetHandlerメソッドがありました。ハンドラとはHTTPリクエストを処理するControllerメソッドのことを指すため、ここでどのハンドラを呼び出すか決めているだろうと推測し、まずは、DispatcherServletを起点に処理の流れを確認しました。

リクエストを受け取ると、DispatcherServletdoDispatch() メソッドが実行されます。内部コードを確認すると、次の処理がありました。

mappedHandler = getHandler(processedRequest);

ここでリクエストに対応するHandler(Controllerのメソッドなど、リクエストを処理する仕組みの総称)を取得しています。
さらに内部を追っていくと、HandlerMappingを利用してHandlerを探していることが分かりました。

for (HandlerMapping mapping : this.handlerMappings) {
  HandlerExecutionChain handler = mapping.getHandler(request);
  if (handler != null) {
    return handler;
  }
}

RequestMappingHandlerMappingにたどり着く

今回のサンプルでは @RequestMapping@GetMapping を利用しています。そのため最終的に処理を担当していたのは RequestMappingHandlerMapping でした。このクラスの役割は、リクエストに対応するControllerメソッドを探すことです。

※なお、Spring内部にはRequestMappingHandlerMapping以外にも、以下のようなHandlerMappingが登録されています。

  1.  SimpleUrlHandlerMapping:URLパターンとHandlerを直接かつ明示的にマップするためのHandlerMappingです。
  2. BeanNameUrlHandlerMapping:リクエストURLのパス(末尾の拡張子などを除く)と、Springコンテナに登録されているBean名を直接対応付けるHandlerMappingです。

URLとメソッドをどのように対応付けているのか

Springは起動時にControllerの情報を収集し、メモリ上に整理して保持しています。

登録されたURLHTTPメソッド
呼び出すControllerメソッド
/employeesGET
EmployeeController#index()
/employeesPOST
EmployeeController#create()
/usersGET
UserController#list()

リクエストが到着すると、その情報と受信したURLを比較し、一致するものを探します。一致した場合は HandlerMethod として返却されます。

実際に取得されるHandlerMethod

取得されたHandlerMethodには次のような情報が含まれています。

  • Controllerクラス名(EmployeeController
  • メソッド名(index
  • パラメータ情報

Springは、事前に登録されたマッピング情報の中から一致するメソッドを検索して探しています。

調査して分かったこと

これらを確認した結果、全体の処理は次のような流れで行われていました。

  • DispatcherServletがリクエストを受け取る
  • HandlerMappingに処理を任せる
  • RequestMappingHandlerMappingがマッピング情報を検索する
  • HandlerMethodを返却する

アノテーションを書くだけでHTTPリクエストに対応したメソッドが呼び出されていましたが、その裏側では多くのコンポーネントが連携して動作しています。

まとめ

今回はSpring MVCがURLからControllerメソッドを特定する仕組みを調査しました。フレームワークはブラックボックスに見えがちですが、実際に内部コードを追ってみると、普段利用している機能がどのように実現されているのかを理解できます。Spring Frameworkの仕組みをより深く学びたい方は、一度内部コードを追ってみるのもおすすめです。
弊社ではSpring Frameworkの内部実装を読み解く「Spring Inside」コースをご用意しています。興味のある方はぜひご検討ください。

バックエンド開発を学ぶ研修一覧 https://www.casareal.co.jp/ls/service/openseminar/search/backend

--------------------------
開発支援・技術研修のご要望・ご相談はこちらから
--------------------------
【この技術ブログを読んだエンジニアの皆様へ】
カサレアルブログをお読みいただき、ありがとうございます!

私たちは、常に新しい技術に挑戦し、ユーザーのニーズに応えるサービスを提供しています。
もし、当社の技術への情熱や、会社・チーム・社員の雰囲気に共感いただけたなら、
ぜひ私たちと一緒に働きませんか?
現在、株式会社カサレアルでは事業拡大に伴い、新たな仲間となるエンジニアを積極的に募集しています。

少しでも興味をお持ちいただけましたら、まずは弊社のことを知っていただけると嬉しいです。
▼採用サイト
https://www.casareal.co.jp/recruit/career
▼社員インタビュー
https://hrmos.co/pages/casareal/jobs/0000016
▼エンジニアの仲間になる! エントリーはこちらから
https://hrmos.co/pages/casareal/jobs

皆様のエントリーを心よりお待ちしています!

プログラミングフォント使ってますか

コメントを残す

メールアドレスが公開されることはありません。 ※ が付いている欄は必須項目です

コメント ※

名前 ※

メール ※

サイト