
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の内部コードを調べた結果をまとめました。
今回調査したこと
今回確認したかったのは次の流れです。
- ブラウザから
/employeesにアクセスする - Spring MVCがリクエストを受け取る
EmployeeController#index()を特定する- メソッドを実行する
特にどのようにしてControllerメソッドを選んでいるのかに着目しました。
DispatcherServletから処理を追う
Spring内部の動きを追うにあたり、自身が作成したメソッドの呼び出し階層をさかのぼって確認したところ、DispatcherServletクラスにgetHandlerメソッドがありました。ハンドラとはHTTPリクエストを処理するControllerメソッドのことを指すため、ここでどのハンドラを呼び出すか決めているだろうと推測し、まずは、DispatcherServletを起点に処理の流れを確認しました。
リクエストを受け取ると、DispatcherServletの doDispatch() メソッドが実行されます。内部コードを確認すると、次の処理がありました。
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が登録されています。
-
SimpleUrlHandlerMapping:URLパターンとHandlerを直接かつ明示的にマップするためのHandlerMappingです。 BeanNameUrlHandlerMapping:リクエストURLのパス(末尾の拡張子などを除く)と、Springコンテナに登録されているBean名を直接対応付けるHandlerMappingです。
URLとメソッドをどのように対応付けているのか
Springは起動時にControllerの情報を収集し、メモリ上に整理して保持しています。
| 登録されたURL | HTTPメソッド | 呼び出すControllerメソッド |
| /employees | GET | EmployeeController#index() |
| /employees | POST | EmployeeController#create() |
| /users | GET | 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」コースをご用意しています。興味のある方はぜひご検討ください。
バックエンド開発を学ぶ研修一覧