Apache Maven

ビルドツールJavaPOM依存関係管理Apacheプロジェクト管理

ビルドツール・パッケージマネージャー

Apache Maven

概要

Apache Mavenは、主にJavaプロジェクトのビルド、依存関係管理、プロジェクト管理を行うためのソフトウェアツールです。「Convention over Configuration(設定より規約)」の哲学に基づき、標準化されたプロジェクト構造とビルドライフサイクルを提供し、複雑なJavaプロジェクトの管理を簡素化します。

詳細

アーキテクチャ

Mavenの中核にあるのはProject Object Model(POM)ファイルで、これはXML形式でプロジェクトの情報、依存関係、ビルド設定を定義します。

主要特徴

  • 標準化されたディレクトリ構造: src/main/javasrc/test/javaなど
  • 依存関係管理: 中央リポジトリからの自動ダウンロード
  • ビルドライフサイクル: validate → compile → test → package → install → deploy
  • プラグインアーキテクチャ: 豊富なプラグインエコシステム
  • マルチモジュールプロジェクト: 大規模プロジェクトの管理

リポジトリシステム

  • ローカルリポジトリ: ~/.m2/repository
  • 中央リポジトリ: Maven Central Repository
  • リモートリポジトリ: 企業内プライベートリポジトリ

ビルドライフサイクル

  1. validate: プロジェクトの妥当性確認
  2. compile: ソースコードのコンパイル
  3. test: 単体テストの実行
  4. package: JAR/WARファイルの作成
  5. verify: 統合テストの実行
  6. install: ローカルリポジトリへのインストール
  7. deploy: リモートリポジトリへのデプロイ

メリット・デメリット

メリット

  • 学習コストが低い: 標準化された構造で理解しやすい
  • 成熟したエコシステム: 豊富なプラグインとドキュメント
  • IDE サポート: IntelliJ IDEA、Eclipse などでの優れたサポート
  • 企業での採用率: 67% の Java 開発者が使用(2021年調査)
  • CI/CD 統合: Jenkins、GitLab CI などとの優れた統合
  • 依存関係管理: トランジティブ依存関係の自動解決
  • 安定性: 長年にわたる実績と安定性

デメリット

  • XML の冗長性: 設定ファイルが冗長になりがち
  • 柔軟性の制限: カスタマイズが困難な場合がある
  • ビルド速度: Gradle と比較して 2-10 倍遅い
  • 複雑な設定: 高度なカスタマイズには XML の深い理解が必要
  • インクリメンタルビルド: 限定的なサポート

参考ページ

書き方の例

プロジェクトの作成

# Maven プロジェクトの新規作成
mvn archetype:generate \
  -DgroupId=com.example.myapp \
  -DartifactId=my-app \
  -DarchetypeArtifactId=maven-archetype-quickstart \
  -DinteractiveMode=false

# Spring Boot プロジェクトの作成
mvn archetype:generate \
  -DgroupId=com.example \
  -DartifactId=spring-boot-app \
  -DarchetypeGroupId=org.springframework.boot \
  -DarchetypeArtifactId=spring-boot-starter-parent

POMファイルの設定

<?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">
    <modelVersion>4.0.0</modelVersion>
    
    <groupId>com.example</groupId>
    <artifactId>my-app</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>
    
    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>3.2.0</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

依存関係の管理

<!-- 依存関係管理 -->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>3.2.0</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<!-- 依存関係の除外 -->
<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>com.sun</groupId>
    <artifactId>tools</artifactId>
    <version>1.8</version>
    <scope>system</scope>
    <systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>

ビルドライフサイクル

# クリーンビルド
mvn clean compile

# テストの実行
mvn test

# パッケージング
mvn package

# ローカルリポジトリへのインストール
mvn install

# リモートリポジトリへのデプロイ
mvn deploy

# 特定のフェーズまで実行
mvn clean test

# テストをスキップしてパッケージング
mvn package -DskipTests

# オフラインモード
mvn -o package

プラグインの使用

<build>
    <plugins>
        <!-- Compiler Plugin -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.11.0</version>
            <configuration>
                <source>17</source>
                <target>17</target>
                <encoding>UTF-8</encoding>
            </configuration>
        </plugin>
        
        <!-- Surefire Plugin (テスト実行) -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>3.1.2</version>
            <configuration>
                <includes>
                    <include>**/*Test.java</include>
                </includes>
            </configuration>
        </plugin>
        
        <!-- JAR Plugin -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>3.3.0</version>
            <configuration>
                <archive>
                    <manifest>
                        <mainClass>com.example.App</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
    </plugins>
</build>

マルチモジュールプロジェクト

<!-- 親POM -->
<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>parent-project</artifactId>
    <version>1.0.0</version>
    <packaging>pom</packaging>
    
    <modules>
        <module>core</module>
        <module>web</module>
        <module>api</module>
    </modules>
    
    <properties>
        <spring.version>5.3.21</spring.version>
    </properties>
</project>

<!-- 子モジュールPOM -->
<project>
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.example</groupId>
        <artifactId>parent-project</artifactId>
        <version>1.0.0</version>
    </parent>
    
    <artifactId>core</artifactId>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
    </dependencies>
</project>