Casual Developers Note

エンジニアやデザイナー向けの技術情報・英語学習情報・海外留学情報・海外旅行情報を提供中。世界を旅して人生を楽しもう。

  • ホーム
  • 技術 Tips & Tutorials
  • 技術塾
  • ライフハック
  • 海外留学
  • 英語学習
  • コラム
  • お問い合わせ
現在の場所:ホーム / 技術 Tips & Tutorials / Springプロジェクトをマルチモジュールで構成する方法(Maven編)

2018年9月17日 By KD コメントを書く

Springプロジェクトをマルチモジュールで構成する方法(Maven編)

Springプロジェクトをマルチモジュールで構成する方法(Maven編)

マルチモジュール化は機能のまとまりを明確化し、プロジェクト再利用性やメンテナンス性を高める良い方法です。今回は、Mavenでのマルチモジュール化の方法と、それをSpringプロジェクトに適用する方法を紹介します。

見出し

  • 1 はじめに
  • 2 Springプロジェクトのマルチモジュール構成
    • 2.1 前提
    • 2.2 サンプルのベースのプロジェクトを作る
    • 2.3 マルチモジュール作成方法①IntelliJからモジュール追加する
    • 2.4 マルチモジュール作成方法②MavenコマンドからGenerateする
    • 2.5 サンプルをSpringプロジェクトにする
  • 3 最後に
  • 4 環境
    • 4.1 関連記事

はじめに

マルチモジュール化とは、プロジェクト内に複数のプロジェクトを閉じ込めるようにプロジェクトを構成することです。MavenのPOMには親子関係を示す記述方法があり、それを利用することで複数のプロジェクトに機能分割しつつ、ビルドをまとめて実施することが可能です。当然汎用的な機能を分割しておけば他のプロジェクトに再利用できますし、プロジェクトの肥大化を防げるのでメンテナンスが容易になります。

それでは、Mavenによるマルチモジュール化の方法と、Springプロジェクトへの適用方法を見ていきましょう。

Springプロジェクトのマルチモジュール構成

前提

以下がインストールされている前提で進めます。

  • Java10
  • Maven3

細かいバージョンは「環境」を参照して下さい。

サンプルのベースのプロジェクトを作る

まずはMavenでベースのプロジェクトを作りましょう。

$ mvn -B archetype:generate \
> -DarchetypeGroupId=org.apache.maven.archetypes \
> -DgroupId=com.example.project \
> -DartifactId=sample-multi-modules-app

マルチモジュール作成方法①IntelliJからモジュール追加する

IntelliJのIDEを使ってモジュールを追加しましょう。

まずIDEで「sample-multi-modules-app」を開き、「src」フォルダを削除します。

Ide 1

続いて、プロジェクトから「New -> Module」を選択します。

Ide 2

「Next」をクリックします。

Ide 3

モジュール名(今回は「core」)を入力して「Next」をクリックします。

Ide 4

「Finish」をクリックすれば完了です。

Ide 5

同様に「main」というモジュールも追加します。

そうすると以下のようになります。2つのモジュールが追加されており、POMファイルが3つになっています。

Ide 6

デフォルトで作成されたPOMファイルは以下のようになっています。

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 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example.project</groupId>
  <artifactId>sample-multi-modules-app</artifactId>
  <packaging>pom</packaging>
  <version>1.0-SNAPSHOT</version>
  <modules>
    <module>core</module>
    <module>main</module>
  </modules>
  <name>sample-multi-modules-app</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

pom.xml(coreモジュール)

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <parent>
    <artifactId>sample-multi-modules-app</artifactId>
    <groupId>com.example.project</groupId>
    <version>1.0-SNAPSHOT</version>
  </parent>
  <modelVersion>4.0.0</modelVersion>

  <artifactId>core</artifactId>


</project>

pom.xml(mainモジュール)

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <parent>
    <artifactId>sample-multi-modules-app</artifactId>
    <groupId>com.example.project</groupId>
    <version>1.0-SNAPSHOT</version>
  </parent>
  <modelVersion>4.0.0</modelVersion>

  <artifactId>main</artifactId>


</project>

マルチモジュール作成方法②MavenコマンドからGenerateする

もちろん、Mavenコマンドからマルチモジュールを構成することが可能です。

$ cd sample-multi-modules-app2/
$ tree
.
├── pom.xml
└── src
    ├── main
    │   └── java
    │       └── com
    │           └── example
    │               └── project
    │                   └── App.java
    └── test
        └── java
            └── com
                └── example
                    └── project
                        └── AppTest.java
$ rm -rf src/
$ tree
.
└── pom.xml
$ vi pom.xml
...
  <packaging>pom</packaging>
...
$ mvn -B archetype:generate \
> -DarchetypeGroupId=org.apache.maven.archetypes \
> -DgroupId=com.example.project.core \
> -DartifactId=core
$ mvn -B archetype:generate \
> -DarchetypeGroupId=org.apache.maven.archetypes \
> -DgroupId=com.example.project.main \
> -DartifactId=main
$ tree
.
├── core
│   ├── pom.xml
│   └── src
│       ├── main
│       │   └── java
│       │       └── com
│       │           └── example
│       │               └── project
│       │                   └── core
│       │                       └── App.java
│       └── test
│           └── java
│               └── com
│                   └── example
│                       └── project
│                           └── core
│                               └── AppTest.java
├── main
│   ├── pom.xml
│   └── src
│       ├── main
│       │   └── java
│       │       └── com
│       │           └── example
│       │               └── project
│       │                   └── main
│       │                       └── App.java
│       └── test
│           └── java
│               └── com
│                   └── example
│                       └── project
│                           └── main
│                               └── AppTest.java
└── pom.xml

ただし、IntelliJと違って自動でPOMファイルをうまく修正してくれないので、手動での修正が多くなります。

サンプルをSpringプロジェクトにする

サンプルを動く形に手直ししましょう。

IDEで以下の構成でファイルを作成します。

$ tree
.
├── core
│   ├── core.iml
│   ├── pom.xml
│   └── src
│       ├── main
│       │   ├── java
│       │   │   └── com
│       │   │       └── example
│       │   │           └── project
│       │   │               └── core
│       │   │                   ├── AppConfig.java
│       │   │                   ├── ApplicationServerImpl.java
│       │   │                   └── Server.java
│       │   └── resources
│       │       └── logback.xml
│       └── test
│           └── java
├── main
│   ├── main.iml
│   ├── pom.xml
│   └── src
│       ├── main
│       │   ├── java
│       │   │   └── com
│       │   │       └── example
│       │   │           └── project
│       │   │               └── main
│       │   │                   └── Main.java
│       │   └── resources
│       └── test
│           └── java
└── pom.xml

ソースコードは以下になります。マルチモジュール化したことで、POMを親子で構成している点がポイントです。

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 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.example.project</groupId>
  <artifactId>sample-multi-modules-app</artifactId>
  <packaging>pom</packaging>
  <version>1.0-SNAPSHOT</version>
  <modules>
    <module>core</module>
    <module>main</module>
  </modules>
  <name>sample-multi-modules-app</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <java.version>10</java.version>
    <spring.version>5.0.7.RELEASE</spring.version>
    <logback.version>1.2.3</logback.version>
    <lombok-version>1.18.0</lombok-version>
  </properties>

  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
      </dependency>

      <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>${logback.version}</version>
      </dependency>

      <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>${lombok-version}</version>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.7.0</version>
        <configuration>
          <target>${java.version}</target>
          <source>${java.version}</source>
          <release>${java.version}</release>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

pom.xml(coreモジュール)

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <parent>
    <artifactId>sample-multi-modules-app</artifactId>
    <groupId>com.example.project</groupId>
    <version>1.0-SNAPSHOT</version>
  </parent>
  <modelVersion>4.0.0</modelVersion>

  <artifactId>core</artifactId>

  <dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
    </dependency>

    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
    </dependency>

    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
    </dependency>
  </dependencies>


</project>

logback.xml(coreモジュール)

<configuration>
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
      <pattern>%date [%thread] [%-5level] %logger{40} = %message%n</pattern>
    </encoder>
  </appender>

  <logger name="com.example.project" level="DEBUG"/>
  <logger name="org.springframework" level="WARN"/>

  <root level="INFO">
    <appender-ref ref="STDOUT"/>
  </root>
</configuration>

Server.java(coreモジュール)

package com.example.project.core;

import lombok.Getter;

public interface Server {

  enum Status {
    STOPPED("stopped"), RUNNING("running");

    @Getter
    private String value;

    Status(String value) {
      this.value = value;
    }

  }

  public void run();

  public String status();

  public void stop();

}

ApplicationServerImpl.java(coreモジュール)

package com.example.project.core;

import org.springframework.stereotype.Component;

@Component("applicationServer")
public class ApplicationServerImpl implements Server {

  private Status status = Status.STOPPED;

  public void run() {
    status = Status.RUNNING;
  }

  public String status() {
    return status.getValue();
  }

  public void stop() {
    status = Status.STOPPED;
  }
}

AppConfig.java(coreモジュール)

package com.example.project.core;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.example.project")
public class AppConfig {

}

pom.xml(mainモジュール)

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <parent>
    <artifactId>sample-multi-modules-app</artifactId>
    <groupId>com.example.project</groupId>
    <version>1.0-SNAPSHOT</version>
  </parent>
  <modelVersion>4.0.0</modelVersion>

  <artifactId>main</artifactId>

  <dependencies>
    <dependency>
      <groupId>com.example.project</groupId>
      <artifactId>core</artifactId>
      <version>${project.version}</version>
    </dependency>
  </dependencies>

</project>

Main.java(mainモジュール)

package com.example.project.main;

import com.example.project.core.AppConfig;
import com.example.project.core.Server;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

@Slf4j
public class Main {

  public static void main(String[] args) {

    ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);

    Server server = (Server) ctx.getBean("applicationServer");
    server.run();
    log.info("Server is {}.", server.status());
    server.stop();
    log.info("Server is {}.", server.status());

    ctx.close();

  }
}

実行してみましょう。

$ mvn clean install -pl main -am
$ cd main/
$ mvn exec:java -Dexec.mainClass="com.example.project.main.Main"
2018-07-12 23:07:50,137 [com.example.project.main.Main.main()] [INFO ] com.example.project.main.Main = Server is running.
2018-07-12 23:07:50,141 [com.example.project.main.Main.main()] [INFO ] com.example.project.main.Main = Server is stopped.

正しく動作しました。これでSpringプロジェクトをマルチモジュール化できました。

最後に

いかがでしたか?これでMavenを使ってSpringプロジェクトをマルチモジュール化できるようになりましたね。ほとんどのプロジェクトで有効な方法ですので、実践していきましょう。では。

環境

  • JDK: openjdk 10.0.1 2018-04-17
  • Maven: Apache Maven 3.5.3
  • SpringFramework: 5.0.7.RELEASE
The following two tabs change content below.
  • この記事を書いた人
  • 最新の記事
KD
Twitter のプロフィール

KD

世界を旅し日本を愛するエンジニア。大学でコンピュータサイエンスの楽しさを学び、日本の大手IT企業で働く中で、新しい技術やスケールするビジネスが北米にある事に気づく。世界に挑戦するための最大の壁が英語であったため、フィリピン留学およびカナダ留学を経て英語を上達させた。現在は日本在住でエンジニアとして働きつつ、次の挑戦に備えて世界の動向を注視している。挑戦に終わりはない。このブログでは、エンジニアやデザイナー向けの技術情報から、海外に留学したい人向けの留学情報、海外に興味がある人向けの海外旅行情報など、有益な情報を提供しています。
KD
Twitter のプロフィール

最新記事 by KD (全て見る)

  • 2020年JS周辺のバックエンド寄りの注目技術!ネクストNodeJSの「Deno」と分散型パッケージレジストリの「Entropic」の紹介 - 2020年1月13日
  • 今さら聞けないJavaによる関数型プログラミング入門 ~ラムダ式、ストリーム、関数型インターフェース~ - 2019年11月4日
  • ReactのためのEslintおよびPrettierの設定方法 ~Airbnb JavaScript Style Guideの適用~ - 2019年10月30日

関連記事

  • [tips][Tumblr] Tumblrでソースコードをシンタックスハイライトする方法

    プログラマがTumblrをメインのブログにした時に困るのは、シンタックスハイライトです。私はめんどくさがりなので、シンタ…

  • MarsEditのプレビューをサイトとほとんど同じにする方法

    MarsEditを使うことのメリットはライブプレビュー(記事を書いている時にリアルタイムでサイトのプレビューが見れること…

  • 動かして分かる! SpringFrameworkのIoCの方法およびDIの使い方

    JavaやKotlinでWebアプリケーションを作るのであればSpringFrameworkを利用するのが一般的であり、…

  • SLF4JとLogbackによるJavaのロギング入門(SLF4J + Logback + Lombok)

    アプリケーションにおいてロギング処理は無くてはならない必需品です。現在ではログは故障の解析はもちろんのこと、セキュリティ…

  • 初級JavascriptフルスタックエンジニアのためのReactとExpressの同時開発チュートリアル(基本的なアプリ作成と同時開発環境構築編)

    フルスタックエンジニアの需要はスタートアップであればあるほど強いものです。そして、エンジニアにとってフロントエンドとバッ…

カテゴリ : 技術 Tips & Tutorials タグ : maven, multi-module, springframework

コメントを残す コメントをキャンセル

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください。

ブログ更新情報や海外の関連情報などを配信する無料メルマガ

Sponsored Links

About Author

KD

世界を旅し日本を愛するエンジニア。大学でコンピュータサイエンスの楽しさを学び、日本の大手IT企業で働く中で、新しい技術やスケールするビジネスが北米にある事に気づく。世界に挑戦するための最大の壁が英語であったため、フィリピン留学およびカナダ留学を経て英語を上達させた。現在は日本在住でエンジニアとして働きつつ、次の挑戦に備えて世界の動向を注視している。挑戦に終わりはない。このブログでは、エンジニアやデザイナー向けの技術情報から、海外に留学したい人向けの留学情報、海外に興味がある人向けの海外旅行情報など、有益な情報を提供しています。

https://casualdevelopers.com/

最近の投稿

  • 2020年JS周辺のバックエンド寄りの注目技術!ネクストNodeJSの「Deno」と分散型パッケージレジストリの「Entropic」の紹介

    2020年JS周辺のバックエンド寄りの注目技術!ネクストNodeJSの「Deno」と分散型パッケージレジストリの「Entropic」の紹介

    2020年1月13日
  • 今さら聞けないJavaによる関数型プログラミング入門 ~ラムダ式、ストリーム、関数型インターフェース~

    今さら聞けないJavaによる関数型プログラミング入門 ~ラムダ式、ストリーム、関数型インターフェース~

    2019年11月4日
  • ReactのためのEslintおよびPrettierの設定方法 ~Airbnb JavaScript Style Guideの適用~

    ReactのためのEslintおよびPrettierの設定方法 ~Airbnb JavaScript Style Guideの適用~

    2019年10月30日
  • BashからZshに移行する方法(Mac編)

    BashからZshに移行する方法(Mac編)

    2019年10月21日
  • Create React Appを使わないでゼロからReactの開発環境を構築する方法(Webpack/Docker編)

    Create React Appを使わないでゼロからReactの開発環境を構築する方法(Webpack/Docker編)

    2019年9月30日

カテゴリ

  • 技術 Tips & Tutorials (100)
  • 技術塾 (6)
  • ライフハック (26)
  • 海外留学 (12)
  • 英語学習 (3)
  • コラム (6)

アーカイブ

最高の学習のために

人気記事ランキング

  • MySQLで「ERROR 2003 (HY000): Can't connect to MySQL server」と怒られた時の対処法
    MySQLで「ERROR 2003 (HY000): Can't connect to MySQL server」と怒られた時の対処法
  • SAKURAのメールボックスで独自ドメインのメールを設定し、Gmail経由で送受信する方法
    SAKURAのメールボックスで独自ドメインのメールを設定し、Gmail経由で送受信する方法
  • Jupyter Notebookで「The kernel appears to have died. It will restart automatically.」というエラーが出た場合の原因と対処法
    Jupyter Notebookで「The kernel appears to have died. It will restart automatically.」というエラーが出た場合の原因と対処法
  • Expressで「Cannot set headers after they are sent to the client」と怒られた時の対処法
    Expressで「Cannot set headers after they are sent to the client」と怒られた時の対処法
  • SLF4JとLogbackによるJavaのロギング入門(SLF4J + Logback + Lombok)
    SLF4JとLogbackによるJavaのロギング入門(SLF4J + Logback + Lombok)
  • Amazon EC2インスタンスにSSHできなくなった時の対処法
    Amazon EC2インスタンスにSSHできなくなった時の対処法
  • SpringBootのProfile毎にプロパティを使い分ける3つの方法
    SpringBootのProfile毎にプロパティを使い分ける3つの方法
  • [tips][perl] Perlで文字コードをいい感じに処理する方法
    [tips][perl] Perlで文字コードをいい感じに処理する方法
  • 爆速でJenkinsをマスターしよう(GitHubアカウント統合編) ~ JenkinsのGitHub Organizationの設定方法 ~
    爆速でJenkinsをマスターしよう(GitHubアカウント統合編) ~ JenkinsのGitHub Organizationの設定方法 ~
  • Go言語のためのVisual Studio Codeの設定方法
    Go言語のためのVisual Studio Codeの設定方法

Bitcoin寄付 / BTC Donation

Bitcoinを寄付しよう

BTC
Select Payment Method
Personal Info

Donation Total: BTC 0.0010

このブログの運営のためにBitcoinでの寄付を募集しています。お気持ち程度の寄付を頂けると管理者の励みになります。

Bitcoin寄付について知りたい方はこちらの記事へ

The following two tabs change content below.
  • この記事を書いた人
  • 最新の記事
KD
Twitter のプロフィール

KD

世界を旅し日本を愛するエンジニア。大学でコンピュータサイエンスの楽しさを学び、日本の大手IT企業で働く中で、新しい技術やスケールするビジネスが北米にある事に気づく。世界に挑戦するための最大の壁が英語であったため、フィリピン留学およびカナダ留学を経て英語を上達させた。現在は日本在住でエンジニアとして働きつつ、次の挑戦に備えて世界の動向を注視している。挑戦に終わりはない。このブログでは、エンジニアやデザイナー向けの技術情報から、海外に留学したい人向けの留学情報、海外に興味がある人向けの海外旅行情報など、有益な情報を提供しています。
KD
Twitter のプロフィール

最新記事 by KD (全て見る)

  • 2020年JS周辺のバックエンド寄りの注目技術!ネクストNodeJSの「Deno」と分散型パッケージレジストリの「Entropic」の紹介 - 2020年1月13日
  • 今さら聞けないJavaによる関数型プログラミング入門 ~ラムダ式、ストリーム、関数型インターフェース~ - 2019年11月4日
  • ReactのためのEslintおよびPrettierの設定方法 ~Airbnb JavaScript Style Guideの適用~ - 2019年10月30日

関連記事

  • [tips][Tumblr] Tumblrでソースコードをシンタックスハイライトする方法

    プログラマがTumblrをメインのブログにした時に困るのは、シンタックスハイライトです。私はめんどくさがりなので、シンタ…

  • MarsEditのプレビューをサイトとほとんど同じにする方法

    MarsEditを使うことのメリットはライブプレビュー(記事を書いている時にリアルタイムでサイトのプレビューが見れること…

  • 動かして分かる! SpringFrameworkのIoCの方法およびDIの使い方

    JavaやKotlinでWebアプリケーションを作るのであればSpringFrameworkを利用するのが一般的であり、…

  • SLF4JとLogbackによるJavaのロギング入門(SLF4J + Logback + Lombok)

    アプリケーションにおいてロギング処理は無くてはならない必需品です。現在ではログは故障の解析はもちろんのこと、セキュリティ…

  • 初級JavascriptフルスタックエンジニアのためのReactとExpressの同時開発チュートリアル(基本的なアプリ作成と同時開発環境構築編)

    フルスタックエンジニアの需要はスタートアップであればあるほど強いものです。そして、エンジニアにとってフロントエンドとバッ…

ビットコイン取引ならここ

  • ホーム
  • 技術 Tips & Tutorials
  • 技術塾
  • ライフハック
  • 海外留学
  • 英語学習
  • コラム
  • サイトマップ
  • タグ一覧
  • プライバシーポリシー
  • お問い合わせ

Copyright © 2023 KD - Casual Developers Notes