Spring Initializrで「Spring Web」にチェックを入れると、pom.xmlに spring-boot-starter-web が入ってきますよね。チュートリアル通りに動くけれど、「これって結局何を持ち込んでいるの?」「webflux や webmvc と何が違うの?」と聞かれると答えに詰まる人は多いはずです。
一言でいうと、spring-boot-starter-web は Spring MVC と組み込み Tomcat で Web アプリや REST API を作るためのスターター です。この記事ではこのアーティファクト1つに絞って、中身・書き方・Tomcat の差し替え・webflux との違い・Spring Boot 4 での改名までを整理します。Starter という仕組み自体の話は Spring Boot Starterって何? に任せて、ここでは深追いしません。バージョンは Spring Boot 3.x を主軸にして、4.x の差分は注記します。
spring-boot-starter-webとは
spring-boot-starter-web は、サーブレットベースの Spring MVC、組み込み Tomcat、JSON 変換用の Jackson をまとめて持ち込むスターターです。これ1つ入れて @RestController を書けば、起動するだけで http://localhost:8080 が応答します。必要なライブラリと、それを配線する自動構成が一式揃うからです。
よく混同されるのが spring-boot-starter との違いです。こちらは Spring Boot 本体・自動構成・ロギングだけの「土台」で、Web 機能は入っていません。starter-web は starter を内包しているので、両方書く必要はありません。
mvn dependency:treeで中身を展開する
「何が入っているか」は自分の目で確認するのが一番です。Maven なら次のコマンドで推移的依存を展開できます。
mvn dependency:tree
# Gradle の場合
./gradlew dependencies --configuration runtimeClasspath
Spring Boot 3.3 系の出力から、spring-boot-starter-web 配下だけ抜粋するとこうなります。
+- org.springframework.boot:spring-boot-starter-web:jar:3.3.5:compile
| +- org.springframework.boot:spring-boot-starter:jar:3.3.5:compile
| | +- org.springframework.boot:spring-boot:jar:3.3.5:compile
| | +- org.springframework.boot:spring-boot-autoconfigure:jar:3.3.5:compile
| | \- org.springframework.boot:spring-boot-starter-logging:jar:3.3.5:compile
| +- org.springframework.boot:spring-boot-starter-json:jar:3.3.5:compile
| | +- com.fasterxml.jackson.core:jackson-databind:jar:2.17.2:compile
| | +- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:jar:2.17.2:compile
| | \- (jdk8 / parameter-names モジュールなど)
| +- org.springframework.boot:spring-boot-starter-tomcat:jar:3.3.5:compile
| | +- org.apache.tomcat.embed:tomcat-embed-core:jar:10.1.31:compile
| | \- org.apache.tomcat.embed:tomcat-embed-websocket:jar:10.1.31:compile
| +- org.springframework:spring-web:jar:6.1.14:compile
| \- org.springframework:spring-webmvc:jar:6.1.14:compile
直下に並ぶのは5本です。
- spring-boot-starter は Boot 本体・自動構成・Logback ベースのロギング
- spring-boot-starter-json は Jackson 一式。
LocalDateTimeやOptionalを扱うモジュールもここに含まれる - spring-boot-starter-tomcat は組み込み Tomcat。これがあるから jar 単体で Web サーバーが立ち上がる
- spring-web は HTTP 周りの共通基盤(
RestTemplateやHttpMessageConverterなど) - spring-webmvc は
DispatcherServletと@RequestMappingを担う Spring MVC 本体
逆に 入っていないもの も押さえておきましょう。Bean Validation(Hibernate Validator)は Spring Boot 2.3 以降 starter-web から外れているので、@Valid を使うには spring-boot-starter-validation を別途追加する必要があります。「starter-web を入れたのに @Valid が無視される」という相談の正体はだいたいこれです。詳しくは @Validが効かない原因と対処 で扱っています。同じく Thymeleaf、Spring Data、Spring Security も入らないので、使うならそれぞれのスターターを足します。
ライブラリの重複やバージョン衝突を疑ったときも、まずは dependency:tree を見る癖をつけておくと切り分けが早くなります。
Maven / Gradleでの追加方法
座標はコピペで大丈夫です。ポイントはバージョンを書かないことです。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
// build.gradle(Groovy DSL)
implementation 'org.springframework.boot:spring-boot-starter-web'
// build.gradle.kts(Kotlin DSL)
implementation("org.springframework.boot:spring-boot-starter-web")
バージョンを省略できるのは、Maven なら spring-boot-starter-parent、Gradle なら io.spring.dependency-management プラグイン(内部で spring-boot-dependencies BOM を読み込む)が、Boot のバージョンに合わせた値を管理してくれているからです。parent を使わない構成では、dependencyManagement に spring-boot-dependencies を import スコープで取り込めば同じことができます。
組み込みTomcatをJetty / Undertowに差し替える
Tomcat 以外のサーバーを使いたい場合は、starter-web から spring-boot-starter-tomcat を除外して、代わりのスターターを足すだけです。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
implementation('org.springframework.boot:spring-boot-starter-web') {
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
}
implementation 'org.springframework.boot:spring-boot-starter-jetty'
Gradle では configurations.implementation { exclude module: 'spring-boot-starter-tomcat' } と書いて、プロジェクト全体から一括除外する手もあります。
バージョンの注意点が1つあります。Spring Boot 3.0 と 3.1 は Jetty 11(Servlet 5.0)系だったため、jakarta.servlet-api のバージョンを下げるプロパティ調整が必要でした。3.2 以降は Jetty 12 に対応しているので、そのまま差し替えるだけで動きます。Undertow は 3.x では使えますが、Spring Boot 4.0 ではサポートが削除されています。これから 4 系へ上げる予定があるなら Jetty を選んでおくのが無難です。
差し替えても server.port などの共通プロパティはそのまま使えます。一方で server.tomcat.* は効かなくなるので、Tomcat のまま性能を調整したい場合は 組み込みTomcatのスレッド数チューニング を参考にしてください。
spring-boot-starter-webfluxとの違い
Initializr には「Spring Web」と「Spring Reactive Web」が並んでいて、後者が spring-boot-starter-webflux です。
| 観点 | starter-web | starter-webflux |
|---|---|---|
| プログラミングモデル | サーブレット・ブロッキング | リアクティブ・ノンブロッキング |
| デフォルトサーバー | Tomcat | Reactor Netty |
| コントローラの書き方 | @RestController で値をそのまま返す | 同じアノテーションで Mono / Flux を返す |
| 相性のよい周辺 | JDBC / JPA / MyBatis | R2DBC / WebClient |
普通の Web アプリや REST API、既存の JDBC・JPA 資産があるなら starter-web で問題ありません。大量の同時接続を少ないスレッドで捌きたい、ストリーミングが主目的、といった要件が出てきたら webflux を検討する、くらいの温度感です。リアクティブの考え方そのものは Spring WebFluxで始めるリアクティブプログラミング にまとめています。
両方入れたらどうなる?
WebClient だけ使いたくて webflux を足した、というケースで両方同居することがあります。このとき Spring Boot は Spring MVC を優先 し、サーブレットアプリとして Tomcat で起動します。明示したいときは application.properties で起動種別を指定できます。
# servlet / reactive / none のいずれか
spring.main.web-application-type=servlet
Spring Boot 4でspring-boot-starter-webmvcに改名された
最近「spring-boot-starter-webmvc」というスターター名を見かけて戸惑った人もいるでしょう。Spring Boot 4.0 でモジュールが技術ごとに再編され(spring-boot-webmvc など)、スターター名もそれに合わせて spring-boot-starter-webmvc に改名されました。
<dependency>
<groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
+ <artifactId>spring-boot-starter-webmvc</artifactId>
</dependency>
4.0 時点では旧名の spring-boot-starter-web も非推奨(deprecated)として残っていて、すぐに壊れるわけではありません。ただし将来のリリースで削除される予定なので、4 系へ上げるタイミングで書き換えてしまうのが確実です。あわせて他のスターターにも改名があるので、公式の移行ガイドで一覧を確認しておきましょう。
逆に Spring Boot 3.x を使っているなら読み替えは不要 です。3.x で spring-boot-starter-webmvc と書いても該当するアーティファクトが存在しないので、後述の Could not find artifact になります。「web と webmvc どちらを書くべきか」の答えは、使っている Boot のメジャーバージョンで決まる、これだけです。
動作確認用の最小@RestController
スターターがちゃんと効いているかは、1ファイルで確認できます。
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@RestController
static class HelloController {
@GetMapping("/hello")
Map<String, String> hello() {
return Map.of("message", "Hello, Spring Boot!");
}
}
}
起動して次のログが出れば、starter-web と starter-tomcat は機能しています。
$ ./mvnw spring-boot:run
... Tomcat started on port 8080 (http) with context path '/'
$ curl http://localhost:8080/hello
{"message":"Hello, Spring Boot!"}
Map を返しただけで JSON になるのは、spring-boot-starter-json(Jackson)が効いている証拠でもあります。ここから Controller・Service・Repository の3層に分けて CRUD を作る手順は REST APIのCRUDを実装する に続きます。
導入直後につまずきやすい2つの症状
Whitelabel Error Pageしか出ない
ブラウザで開いたら真っ白なページに「Whitelabel Error Page」と 404 が出る、というやつです。Tomcat は起動しているので依存関係は正しく、問題はマッピングか配置にあります。確認する順番はこうです。
- そのパスに対応する
@GetMappingが本当に存在するか - Controller が
@SpringBootApplicationクラスと同じパッケージか、その配下にあるか。スキャン範囲外に置いてしまうのが定番の原因で、仕組みは @SpringBootApplicationとは で解説しています @Controllerと@RestControllerを取り違えていないか。前者だと戻り値がテンプレート名として解釈されます
Could not find artifact
Could not find artifact org.springframework.boot:spring-boot-starter-web:jar:unknown のようなエラーでビルドが止まる場合は、次の3点を見ます。
- artifactId の typo。3.x なのに
spring-boot-starter-webmvcと書いている、ハイフンが抜けている、など - parent も BOM も無いのにバージョンを省略している。
version:unknownやversion is missingと出ていたらこれです - 社内プロキシやオフライン環境で Maven Central に届いていない。
~/.m2/settings.xmlの proxy 設定を確認し、mvn -Uで再取得します
なお、起動自体が「APPLICATION FAILED TO START」で落ちる場合は依存ではなく構成側の問題がほとんどです。そちらは Spring Bootアプリが起動しない時の原因切り分け を参照してください。
まとめ
spring-boot-starter-web は、Spring MVC・組み込み Tomcat・Jackson を1行で持ち込むスターターです。中身は dependency:tree で確認でき、Bean Validation は含まれないので必要なら starter-validation を足します。座標はバージョン無しで書けばよく、Tomcat の差し替えは exclusion と代替スターターの2ステップです。webflux と同居させたときは MVC が優先され、Spring Boot 4 からは spring-boot-starter-webmvc という名前になりました。
「なぜバージョンを書かなくていいのか」「他にどんなスターターがあるのか」が気になったら、Spring Boot Starterって何? で全体像を押さえておくと、この記事の内容がさらに腑に落ちるはずです。