Spring Boot でマルチモジュールアプリを作成
依存関係を持つ複数のプロジェクトを用いてアプリをビルドする手順です。
cf. https://spring.pleiades.io/guides/gs/multi-module/
プロジェクト構成
multi-module
├─app-project
│ └─(Spring Bootプロジェクト)
├─web-project
│ └─(Spring Bootプロジェクト)
├─.mvn
├─mvnw
└─pom.xml
web-projectがapp-projectに依存します。
実装
app および web の実装方法を記載します。
app-project
web 側から呼ばれるモジュールです。
サービスインターフェース
ドキュメントとしてわかりやすいようにエンドポイントは設けませんが、こちらにも@RequestMapping などのアノテーションによってエンドポイントを付与できます。
package com.example.appproject.service;
import org.springframework.stereotype.Service;
/**
* サンプルのappインターフェースです。
*
*/
@Service
public interface SampleAppService {
/**
* サンプルのappメソッドです。
*
* @return 固定メッセージ
*/
String greeting();
}
サービス実装
固定メッセージを返却するだけの実装です。
package com.example.appproject.service.impl;
import org.springframework.stereotype.Service;
import com.example.appproject.service.SampleAppService;
/**
* サンプルappサービスの実装クラスです。
*
*/
@Service
public class SampleAppServiceImpl implements SampleAppService {
/**
* {@inheritDoc}
*
*/
@Override
public String greeting() {
return "Hello, multi module!";
}
}
pom.xml
実行可能 jar をビルドしないようにするため、<build>ブロックを丸ごと消します。
<?xml version="1.0" encoding="UTF-8"?>
<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>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>app-project</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>app-project</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<!-- <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build> -->
</project>
web-project
app-projectを呼び出すモジュールです。
メインクラス
依存関係に含まれる自作パッケージをスキャンする旨を追記します。
package com.example.webproject;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication(scanBasePackages = { "com.example" }) // 自身を含む、依存するパッケージを記載する
public class WebProjectApplication {
public static void main(String[] args) {
SpringApplication.run(WebProjectApplication.class, args);
}
}
サービスインターフェース
エンドポイントを設けて公開 API 実装とします。
package com.example.webproject.service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* サンプルのwebインターフェースです。
*
*/
@RestController
@RequestMapping(value = "/web")
public interface SampleWebService {
/**
* サンプルのwebメソッドです。
*
* @return
*/
@GetMapping(value = "/greet")
String greeting();
}
サービス実装クラス
@Autowiredで app 側のサービスを Bean 宣言して呼び出します。
package com.example.webproject.service.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.example.appproject.service.SampleAppService;
import com.example.webproject.service.SampleWebService;
/**
* サンプルwebサービスの実装クラスです。
*
*/
@Service
public class SampleWebServiceImpl implements SampleWebService {
// app serviceをBean宣言
@Autowired
private SampleAppService sampleAppService;
/**
* {@inheritDoc}
*
*/
@Override
public String greeting() {
// app service呼び出し
return sampleAppService.greeting();
}
}
pom.xml
app-project を依存関係に追加:
<dependency>
<groupId>com.example</groupId>
<artifactId>app-project</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
する以外はデフォルトのままです。
<?xml version="1.0" encoding="UTF-8"?>
<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>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>web-project</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>web-project</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- for app project -->
<dependency>
<groupId>com.example</groupId>
<artifactId>app-project</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
multi-module
親プロジェクトの設定です。
pom.xml
packagingタグをpomとし、modulesタグにビルドするモジュールたちを記載します。
<?xml version="1.0" encoding="UTF-8"?>
<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>org.springframework</groupId>
<artifactId>gs-multi-module</artifactId>
<version>0.1.0</version>
<packaging>pom</packaging>
<modules>
<module>app-project</module>
<module>web-project</module>
</modules>
</project>
mvn 関連
VSCode の機能で自動生成したものを app-project 等からコピーしてくるのが楽です。
cp -r mvnw* .mvn ..
ビルド
プロジェクトのルートディレクトリにて、下記コマンドで各モジュールがビルドされます。
./mvnw package
web-projectの jar を起動してエンドポイントにアクセスすると、app-projectモジュールを呼び出していることが確認できます。