はじめに
mavenのビルドツールを使用しマルチモジュールで動作する場合の例を作成します。
mavenのビルドツールの理解において、とりあえず動いたものからpom.xmlについて理解、mavenのビルド等を理解していくという習うより慣れろです。
実施内容
WSL 上で動作確認できるシンプルな Maven マルチモジュールプロジェクトのサンプルです。my-app-parent
という親プロジェクトの下に my-app-model
(モデル)と my-app-web
(Webアプリ)という構成になります。Spring Boot を使って、http://localhost:8080/hello
にアクセスできる簡単なWebアプリを動かします。
ディレクトリ構成
my-app-parent/
├── pom.xml
├── my-app-model/
│ └── pom.xml
│ └── src/main/java/com/example/model/Greeting.java
├── my-app-web/
└── pom.xml
└── src/main/java/com/example/web/WebApplication.java
└── src/main/java/com/example/web/HelloController.java
Spring Bootセット手順
1. Spring Initializr でプロジェクト雛形をダウンロード
設定は次のようにしてください:
項目 | 値 |
---|---|
Project | Maven |
Language | Java |
Spring Boot | 任意(例: 3.2.3) |
Project Metadata | group: com.example
|
artifact: my-app-parent
|
|
Packaging | Jar |
Java | 17 |
Dependencies | Web(spring-boot-starter-web) |
Generate
ボタンを押すと zip ファイルがダウンロードされます。
2. ダウンロード&展開(WSL内)
cd ~/Desktop/work # 作業ディレクトリに移動(例)
unzip /mnt/c/Users/apple/Downloads/my-app-parent.zip
cd my-app-parent
Windows 側の ZIP ファイルを WSL から使う
WSL から Windows ファイルを見るには /mnt/c/
を使います。
ダウンロード場所を確認
通常、ブラウザでダウンロードした ZIP は以下にあります:
C:\Users\apple\Downloads\my-app-parent.zip
WSL では次のように見えます:
/mnt/c/Users/apple/Downloads/my-app-parent.zip
マルチモジュール構成へ変換
① my-app-model
フォルダを追加
mkdir my-app-model
mkdir -p my-app-model/src/main/java/com/example/model
my-app-model/pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.example</groupId>
<artifactId>my-app-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>my-app-model</artifactId>
<packaging>jar</packaging>
</project>
my-app-model/src/main/java/com/example/model/Greeting.java
package com.example.model;
public class Greeting {
private String message;
public Greeting(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
}
② my-app-web
フォルダを追加
mkdir my-app-web
mkdir -p my-app-web/src/main/java/com/example/web
my-app-web/pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.example</groupId>
<artifactId>my-app-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>my-app-web</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.example</groupId>
<artifactId>my-app-model</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
my-app-web/src/main/java/com/example/web/WebApplication.java
package com.example.web;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class WebApplication {
public static void main(String[] args) {
SpringApplication.run(WebApplication.class, args);
}
}
my-app-web/src/main/java/com/example/web/HelloController.java
package com.example.web;
import com.example.model.Greeting;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/hello")
public Greeting hello() {
return new Greeting("こんにちは、Spring Boot + マルチモジュール from WSL!");
}
}
③ 親プロジェクトの pom.xml
を修正
現在は Spring Boot の "親" になっていますが、マルチモジュールの "親" に変更しましょう。
置き換え後の my-app-parent/pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>my-app-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>my-app-model</module>
<module>my-app-web</module>
</modules>
<properties>
<java.version>17</java.version>
<spring.boot.version>3.4.4</spring.boot.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
✅ ビルドと起動確認
# 親プロジェクトのルートで実行
cd ~/Desktop/work/my-app-parent
# 依存関係ビルド
mvn clean install
# Webアプリ起動(my-app-web内で)
cd my-app-web
mvn spring-boot:run
🌐確認
ブラウザでアクセス:
http://localhost:8080/hello
👇 JSONが出れば成功!
{"message":"こんにちは、Spring Boot + マルチモジュール from WSL!"}
pom.xml
pom.xml
の主な構成要素と役割
以下のような感じで分類できます:
1. <parent>
:親プロジェクトの定義
マルチモジュールプロジェクトで共通設定をまとめたいときに使います。
<parent>
<groupId>com.example</groupId>
<artifactId>my-parent-project</artifactId>
<version>1.0.0</version>
</parent>
🔹 役割:
- バージョンや依存ライブラリの共通化
- プラグインやプロパティの共通設定
- 子プロジェクトでの
<build>
や<dependencies>
の継承
2. <dependencies>
:使用するライブラリの定義
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.7.0</version>
</dependency>
</dependencies>
🔹 役割:
- プログラムで使う外部ライブラリを指定
- Maven が自動でダウンロードしてクラスパスに追加
3. <build>
:ビルドに関する設定
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
🔹 役割:
- コンパイルやパッケージ化の設定
- WAR/JAR のビルド手順
- コンパイラのバージョン指定や JAR 名の指定など
4. <properties>
:変数の定義
<properties>
<java.version>1.8</java.version>
<spring.boot.version>2.7.0</spring.boot.version>
</properties>
🔹 役割:
- バージョンや環境設定の共通化・再利用
-
<dependency>
や<plugin>
の中で${}
を使って参照可能
🍝 他言語との違い
言語 / フレームワーク | 依存管理ファイル | 普段どれだけ意識するか |
---|---|---|
PHP (Laravel) | composer.json |
ほぼ意識せず自動でOK(artisan がやってくれる) |
JavaScript (React) | package.json |
開発者が必要最低限だけ記述 |
Java (Spring Boot) | pom.xml |
ビルドもテストも全部ここが基盤 |
Python (Django等) |
requirements.txt or pyproject.toml
|
ライブラリ管理用で軽量 |
Java では pom.xml
に「親子関係」「バージョン依存」「プラグイン設定」などをガッツリ書くのが前提です。
親プロジェクトにあるこの記述って何なのか
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
これは:
子モジュールが
spring-boot-starter-web
などを バージョン番号なしで使えるようにする共通設定
つまり、「バージョンはここでまとめて管理するから、子モジュールでは書かなくていいよ」っていう Maven の仕組みです。
子モジュール(my-app-web)では何をしているの?
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
これは:
「このモジュールは Webアプリケーションとして起動するから、必要なライブラリ一式(Tomcat, Jackson, Spring MVCなど)を入れてね」という指定です。
実際、これ1行で以下を全部まとめてくれるのが「starter」方式のいいところです:
- Spring MVC
- Jackson(JSON変換)
- 内蔵Tomcat
- エラーハンドリング etc...
Springの動き
「どうして /hello
にアクセスすると JSON が返ってくるのか?」 を、Spring Boot の仕組みを含めて記載します。
流れ
Spring Boot は、以下の流れで動いています:
- ブラウザが
/hello
にアクセス -
HelloController.hello()
メソッドが呼ばれる -
new Greeting(...)
を返す - Spring Boot(Spring MVC)が Greeting オブジェクトを 自動で JSON に変換
- ブラウザに JSON として表示される
各パーツの役割を分解して解説
🔹 @RestController
@RestController
public class HelloController {
-
@Controller
+@ResponseBody
の省略形 - 「戻り値はHTMLではなくJSONなどのデータとして返します」という意味
🔹 @GetMapping("/hello")
@GetMapping("/hello")
public Greeting hello() {
-
/hello
にアクセスが来たらこのメソッドを実行するというルーティング(URLマッピング) - 戻り値に
Greeting
を返す(=POJO)
🔹 new Greeting(...)
return new Greeting("こんにちは、Spring Boot + マルチモジュール from WSL!");
- 単に
Greeting
クラスのインスタンスを作って返してるだけ
🔹 Greeting
クラス
public class Greeting {
private String message;
public Greeting(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
}
-
message
フィールドを持っただけのデータクラス - getter(getMessage)を持っているのがポイント!
🔹 自動で JSON にしてくれるのは誰?
Spring Boot に含まれる spring-boot-starter-web
が内部で Jackson というライブラリを使っています。
- Javaオブジェクト → JSON文字列 に変換
- これは「シリアライズ」と呼ばれます
🔸 Jackson は以下のように変換します:
new Greeting("こんにちは")
こうなる
{"message":"こんにちは"}
Spring Bootの特徴だらけ
-
@RestController
をつけるだけで「返すものはJSONだな」と判断してくれる -
@GetMapping("/hello")
でURLルーティング -
Greeting
はただのJavaクラスでも、getterがあれば勝手にJSONにしてくれる - 明示的に「JSONに変換しろ」って書かなくてもよい
まとめ
概念 | 実装したもの | Springの役割 |
---|---|---|
URLに応じた処理 | @GetMapping("/hello") |
URLルーティング |
コントローラー | @RestController |
JSONとして返す |
データを返す | return new Greeting(...) |
Javaオブジェクトとして返す |
JSONへの変換 |
Greeting + getter
|
Jackson による自動変換 |
前準備
WSL設定
- WSL 上に Java(JDK 8 以上)と Maven がインストール済み
maven
sudo apt update
sudo apt install maven
そして、優先パスを変えるか .bashrc
や .zshrc
に以下を追記:
export PATH="/usr/share/maven/bin:$PATH"
source ~/.bashrc
Java
readlink -f $(which java)
例:/usr/lib/jvm/java-17-openjdk-amd64/bin/java
その後、以下を実行:
echo 'export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64' >> ~/.bashrc
echo 'export PATH=$JAVA_HOME/bin:$PATH' >> ~/.bashrc
source ~/.bashrc