Spring MVCは、Servlet APIの上に構築されたJava向けのWebアプリケーションフレームワークです。公式ドキュメントでは正式名称を「Spring Web MVC」とし、その名前がソースモジュール spring-webmvc に由来すること、通称として「Spring MVC」が広く使われていることが明記されています。つまりSpring MVCとspring-webmvcは別物ではなく、同じものを通称とモジュール名で呼び分けているだけです。
2026年に入ってから、この記事で扱う範囲でひとつ大きな変更が起きました。Spring Boot 4.0で spring-boot-starter-web が非推奨になり、後継として spring-boot-starter-webmvc が導入されています。検索でよく見かける「starter-webとstarter-webmvcはどちらを書けばよいのか」という疑問は、この改称が原因です。以下では定義・処理の流れ・依存関係の書き方・非同期処理・WebFluxとの分岐までを、公式ドキュメントとMaven Centralの実データに沿って整理します。
まとめ:Spring MVCの要点と2026年9月時点の依存関係
- Spring MVCの正式名称は「Spring Web MVC」で、実体はSpring Frameworkの
spring-webmvcモジュールです。単体の製品ではありません。 - 中心にあるのは
DispatcherServletというフロントコントローラで、URLとメソッドの対応付け・ビューの解決・例外処理を、DIコンテナから見つけた委譲部品に振り分けます。 - Spring Boot 4.0以降、Web依存の推奨は
spring-boot-starter-webmvcです。spring-boot-starter-webはpomのdescriptionに非推奨と明記され、将来のリリースで削除される予定です。 - ただし両者が最終的に取り込む
spring-webmvcは同一バージョン(Spring Boot 4.1.1では7.0.9)です。名前が変わっただけで、動くコードは変わりません。 - Spring MVCは1リクエスト1スレッドのブロッキングモデルです。ノンブロッキングが必要なら別モジュールの Spring WebFlux を選びます。
ここから先は、この5点それぞれの根拠と、実際にpom.xmlへ何を書くかを見ていきます。
Spring MVCの定義とspring-webmvcモジュールの位置づけ
正式名称「Spring Web MVC」とモジュール名の対応関係
Spring Frameworkのリファレンスは、Spring Web MVCについて「Servlet APIの上に構築された最初のWebフレームワークであり、Spring Frameworkの当初から含まれている」と説明しています。続く一文が名前の由来です。正式名称の「Spring Web MVC」はソースモジュール spring-webmvc の名前から来ており、より一般的には「Spring MVC」として知られている、と書かれています。
この一文を押さえておくと、検索結果に並ぶ表記のゆれがすべて同じものを指していると分かります。Spring MVC、Spring Web MVC、spring-webmvc、そしてMavenの座標である org.springframework:spring-webmvc。呼び方が4通りあるだけで、指しているモジュールは1つです(Spring Framework リファレンス Spring Web MVC)。
Spring Bootを使わずにSpring MVCだけを導入する場合は、次の依存を書きます。2026年9月時点のGA最新は7.0.9です(7.1.0-M1はマイルストーン版のため本番向けではありません)。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>7.0.9</version>
</dependency>
この形はレガシー環境の保守や、外部のサーブレットコンテナへWARを配備する構成で今も使われます。新規開発でこの書き方を選ぶ理由はほとんどありません。DIコンテナ・組み込みTomcat・自動構成をすべて手で組む作業が戻ってくるためです。
Model・View・Controllerの3要素がSpring MVCで対応する部品
MVCという設計パターン自体は、アプリケーションをModel(データとビジネスロジック)、View(表示)、Controller(入力の受け付けと調整)の3つに分ける考え方です。Spring MVCでは、Controllerが @Controller または @RestController を付けたクラス、Viewが ThymeleafなどのテンプレートエンジンやJSON変換、Modelがコントローラからビューへ渡すデータ入れ物(Model インターフェース)と、その裏にあるドメインオブジェクトに対応します。
ここで注意したい誤解が1つあります。ModelはDB保存の担当者ではありません。永続化はリポジトリ層の仕事で、ModelはあくまでViewへ渡す値とドメインの状態を指します。パターンとしてのMVCの整理や、MVVM・MVPとの違いは MVCとMVVM・MVPの違いで扱っているのでそちらを参照してください。
@RestController
public class GreetingController {
@GetMapping("/api/greeting")
public Map<String, String> greeting(@RequestParam String name) {
return Map.of("message", "Hello, " + name);
}
}
@RestController を使うと戻り値がそのままレスポンスボディへ変換され、HTMLテンプレートを経由しません。画面を返すなら @Controller を使い、ビュー名を文字列で返します。REST APIか画面かで注釈を使い分けるのが、Spring MVCで最初に覚える分岐です。
DispatcherServletを起点としたリクエスト処理の流れ
Spring MVCの処理はすべて DispatcherServlet を通ります。公式ドキュメントはこれをフロントコントローラパターンと呼び、中央のServletである DispatcherServlet がリクエスト処理の共通アルゴリズムを提供し、実際の作業は差し替え可能な委譲部品が行う、と説明しています。そして DispatcherServlet は、リクエストのマッピング・ビューの解決・例外処理に必要な委譲部品を、Springの設定(DIコンテナ)から見つけ出します。
実際の1リクエストは次の順に流れます。
- Servletコンテナが受け取ったリクエストを
DispatcherServletが引き取る HandlerMappingがURLとHTTPメソッドから呼び出すハンドラ(コントローラのメソッド)を決めるHandlerAdapterが引数を解決してハンドラを呼び、戻り値を受け取る- 戻り値がビュー名なら
ViewResolverが実ファイル(テンプレート)へ解決し、ボディならメッセージコンバータがJSONなどへ変換する - 途中で例外が出た場合は
HandlerExceptionResolverがレスポンスへ変換する
この5段のどこも自分で書く必要はありません。書き換えたくなったときだけ、対応するBeanを差し替えます。たとえばURLの解決規則を変えたいなら HandlerMapping、テンプレートの探索パスを変えたいなら ViewResolver、エラー応答の形式を統一したいなら @ControllerAdvice と例外リゾルバ、という対応です。Spring Bootを使う場合、これらは自動構成が既定値で登録するため、設定ファイルに1行も書かずに動きます。
Spring Boot 4で変わった依存名:starter-webからstarter-webmvcへ
非推奨になったstarterと置き換え先の対応
Spring Boot 4.0のマイグレーションガイドには、モジュールの再編に伴っていくつかのstarter POMが改称されたこと、そして旧来のstarterは残るものの非推奨とみなすべきで、将来のリリースで削除されると書かれています。Web関連では次の2つが該当します。
| 非推奨のstarter | 置き換え先 | 非推奨になった版 |
|---|---|---|
| spring-boot-starter-web | spring-boot-starter-webmvc | 4.0.0 |
| spring-boot-starter-web-services | spring-boot-starter-webservices | 4.0.0 |
非推奨の時期はMaven Centralのpomから確認できます。spring-boot-starter-web のdescriptionは3.5.16では従来どおりの説明文ですが、4.0.0以降は末尾に「deprecated in favor of spring-boot-starter-webmvc」が追記されています。つまり境界はSpring Boot 4.0.0で、3.x系を使い続ける限り書き換えは不要です。
依存ツリーの実体は同一:改称に伴う挙動変化はない
名前が変わると中身も変わったのではないかと身構えますが、そうではありません。Spring Boot 4.1.1のpomをたどると、spring-boot-starter-webmvc は spring-boot-starter・spring-boot-starter-jackson・spring-boot-starter-tomcat・spring-boot-http-converter・spring-boot-webmvc に依存し、その spring-boot-webmvc:4.1.1 が spring-web:7.0.9 と spring-webmvc:7.0.9 を引き込みます。旧来の spring-boot-starter-web も同じ spring-boot-webmvc:4.1.1 を経由するため、最終的に載るSpring MVCは同一バージョンです。各Spring Bootリリースが管理する依存バージョンは、公式のDependency Versions Coordinatesで確認できます。
新規プロジェクトで迷う必要もありません。start.spring.ioでSpring Boot 4.1.1とSpring Webを選んで生成されるpom.xmlには、次の2つが書き出されます(spring-boot-starter-web は現れません)。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc-test</artifactId>
<scope>test</scope>
</dependency>
判断はこうなります。既存の3.x系プロジェクトは、Spring Boot 4へ上げるタイミングまで書き換えない。4系へ上げるなら、その移行作業の一部として spring-boot-starter-webmvc へ置き換える。置き換えは親POM(またはBOM)を4系へ上げる変更と同時か、その後に行ってください。spring-boot-starter-webmvc は4.0.0-M1以降にしか公開されていないため、3.x系のまま依存名だけを差し替えると依存解決に失敗します。なお、Spring Boot 4.0はJava 17以降を要求し、Spring Framework 7.x系とセットで使う前提です(Spring Boot 4.0 Migration Guide)。依存名以外の4系の変更点は Spring Bootの依存名変更と最小Web APIの作り方とSpring Boot 4の変更点にまとめています。
Spring MVCとSpring Bootの違いと、どちらを学ぶかの判断
この2つは競合しません。Spring MVCはリクエストを処理するWebフレームワーク、Spring Bootはそれを含むSpringのモジュール群を組み立てて起動可能にする仕組みです。関係を1行で言えば、Spring BootはSpring MVCを設定済みの状態で載せてくれる土台です。
| 観点 | Spring MVC | Spring Boot |
|---|---|---|
| 正体 | spring-webmvcモジュール | 自動構成と起動の仕組み |
| 提供元 | Spring Framework 7.0.9 | Spring Boot 4.1.1 |
| 設定 | 手動(XMLまたはJava Config) | 自動構成+application.yml |
| 実行形態 | Servletコンテナ上で動作 | 実行可能JARまたはWAR |
| 単独利用 | 可能 | Web以外の用途にも使う |
学習順で迷ったら、Spring Bootから入って構いません。Spring Bootで動くアプリを作れば、その中でコントローラを書く部分がそのままSpring MVCです。逆順、つまりXML設定からSpring MVCを組み立てる学習は、既存のレガシー案件を保守する予定がある人以外には遠回りになります。Spring Framework全体のDI/AOPの仕組みを先に押さえておくと、自動構成が何を代行しているかが読み解けます。
Servletスレッドを解放するCallableとDeferredResultの使い分け
Spring MVCは1リクエストを1スレッドで処理します。ただし、コントローラの戻り値を Callable や DeferredResult で包むと、処理の途中でServletコンテナのスレッドを解放できます。公式ドキュメントは Callable の挙動をこう説明しています。Spring MVCが request.startAsync() を呼び、Callable を AsyncTaskExecutor へ投入して別スレッドで実行する。その間に DispatcherServlet とすべてのフィルタはServletコンテナのスレッドから抜けるが、レスポンスは開いたままになる、という動きです。
@GetMapping("/reports/monthly")
public Callable<String> monthlyReport() {
return () -> {
// Servletのスレッドではなく AsyncTaskExecutor 上で実行される
return reportService.build();
};
}
使い分けの基準は、結果を誰が作るかです。自分のアプリ内で重い計算やI/Oを回すだけなら Callable で十分です。外部イベント(JMSメッセージやスケジュールされたタスクなど)を待って、まったく別のスレッドから結果を差し込みたい場合は DeferredResult を使い、後から setResult() を呼びます。
ここは過剰に手を出さないほうがよい領域でもあります。単に処理が遅いという理由で全エンドポイントを Callable にすると、スレッドプールが2段構えになって障害時の切り分けが難しくなるだけです。Callable はコンテナのスレッドを解放する代わりに AsyncTaskExecutor のスレッドを使うので、ブロッキングI/O自体が消えるわけではありません。効くのはコンテナのスレッド数が先に頭打ちになる構成です。適用するエンドポイントを絞り、executorのサイズとタイムアウトは負荷試験の結果で決めてください(Spring Framework リファレンス Asynchronous Requests)。
Spring MVCを選ばない場面:WebFluxへ切り替える条件
Spring MVCはServlet API上で動くため、通常の同期処理では1リクエストがコンテナのスレッドを1本占有します。前章の Callable や DeferredResult でそのスレッドを途中で解放できますが、レスポンスの書き込みまで含めたスタック全体がノンブロッキングになるわけではありません。Spring Boot 4.0が依存するJakarta Servletは6.1です。Spring Framework 5.0で追加されたSpring WebFluxは、これとは別の spring-webflux モジュールで、ノンブロッキングのリアクティブスタックを提供します。
切り替えを検討する条件は次の2つに絞れます。第1に、1リクエストの大半が外部への通信待ちで、同時接続数がスレッド数の上限に張り付く場合。第2に、サーバ送信イベントやストリーミングのように、応答を少しずつ流し続ける必要がある場合です。
逆に、次の場合はWebFluxに移すべきではありません。JDBCで同期的にDBを叩く処理が中心のアプリ、チームにリアクティブの読み書き経験がないケース、そして単に流行を理由にした置き換えです。リアクティブ化には非同期・宣言的な処理モデルを学ぶコストが伴うので、現行のSpring MVCで要件を満たせているなら全面移行はせず、対象エンドポイントを絞って負荷試験で効果を確かめてから広げてください。判断材料は Spring WebFluxのノンブロッキング設計で整理しています。既存のStrutsアプリからの移行先を検討している場合は、StrutsからSpring MVCへの移行手順のほうが実務に近い内容です。
Spring MVCの依存関係・公式資料・移行に関するよくある質問
「Spring Boot MVC」という名前のフレームワークはありますか?
そうした名前の製品はありません。Spring Bootを使ってSpring MVCでWebアプリを作る構成を、慣用的にSpring Boot MVCと呼んでいるだけです。Maven Centralに存在するのは org.springframework:spring-webmvc(Spring Framework側の本体)と org.springframework.boot:spring-boot-starter-webmvc(Spring Boot側のstarter)の2つで、前者を後者が取り込む関係になっています。検索で出てくる「Spring Boot MVCとは」という質問は、実質的に「Spring BootでSpring MVCを使うとどうなるか」という問いだと読み替えると迷いません。
Spring MVCの公式ドキュメントはどこにありますか?
Spring Frameworkリファレンスの Web on Servlet Stack セクション(docs.spring.io の spring-framework/reference/web/webmvc.html)が一次情報です。日本語で読みたい場合はPleiadesによる翻訳版(spring.pleiades.io)が同じ構成で公開されています。ただし翻訳版は本家に追随するまでの時差があるため、バージョン依存の記述や新機能を確認するときは英語の本家を見てください。APIの個別仕様はJavadocの org.springframework.web.servlet パッケージが該当します。
Spring MVCとMVVM・MVPの違いは何ですか?
Spring MVCはServlet API上でHTTPリクエストを処理するサーバ側のフレームワークで、MVVMやMVPはUI層の責務分割を論じるときに使われる設計パターンです。層が違うため、Spring MVCの代わりにMVVMを採用するという選択関係にはなりません。サーバ側をSpring MVC、ブラウザ側をMVVM系のフレームワークで組む構成も一般的です。パターンどうしの比較は MVCとMVVM・MVPの違いで扱っています。
ViewResolverはどんな役割の部品ですか?
コントローラが返した文字列のビュー名を、実際に描画するテンプレートへ解決する部品です。たとえばコントローラが hello という文字列を返したとき、ViewResolver が設定された接頭辞と拡張子を組み合わせてテンプレートファイルを特定します。Spring Bootでは、Thymeleafの依存を追加した時点で対応する ViewResolver が自動構成で登録されるため、通常は明示的な設定が要りません。@RestController を使うAPIでは、そもそもビュー解決が行われずメッセージコンバータがJSONへ変換します。
Seasar2やStrutsからの移行先としてSpring MVCは選べますか?
選べます。Seasar2は2016年9月にサポートが終了しており、Struts 1系も同様に開発が止まっているため、現行のJava Web案件で新規採用する理由はありません。移行先としてSpring MVCが有力なのは、DIコンテナと画面遷移の考え方が近く、業務ロジックを大きく書き換えずに層を移せるためです。実際の移行では、アクションクラスをコントローラへ、設定ファイルの遷移定義を注釈へ置き換える作業が中心になります。