🤹 Maven#
🧫 背景#
私たちのソフトウェアライフサイクルは基本的に次のように分けられます:要件(ビジネスが要件を提起し、製品が文書を作成し、技術がスケジュールを決定)、開発(要件分析、データベース設計、コーディング、単体テストなどの自己テストを含む)、テスト、パッケージングと外部リリース、バージョン更新(時間とビジネス要件の変化に応じて以前の開発テストプロセスを繰り返す)。
プロジェクトの自動化ビルド
Maven (pom.xml)。Java で開発されていますが、機能はより包括的で強力です。関連する設定ファイル(pom.xml)を変更することで、ソフトウェアライフサイクルのほぼすべてのプロセス(コンパイル、テスト、パッケージング、リリース、インストール)を自動化でサポートし、もう一つの強力な機能:JAR パッケージ依存機能があります。
👨💻 コマンド#
- mvn clean
以前のコンパイル結果を削除し、再コンパイルの準備をします。 - mvn compile
Java ソースプログラムをバイトコードファイルにコンパイルします。 - mvn test
プロジェクトの重要なポイントをテストし、イテレーション開発中の重要なポイントの正確性を確保します。 - レポート():各テストの後に標準形式でテスト結果を記録し表示します。
- mvn package
多くのファイルを含むプロジェクトを圧縮ファイルにパッケージングし、インストールまたはデプロイに使用します。Java プロジェクトはjar
パッケージに対応し、Web プロジェクトはwar
パッケージに対応します。 - mvn install
Maven 環境下で特にパッケージ化された結果 ——jar
パッケージまたはwar
パッケージをローカルリポジトリにインストールします。 - mvn deploy
パッケージ化された結果をリモートリポジトリにデプロイするか、war
パッケージをサーバーにデプロイして実行します。
mvn -version/-v
バージョン情報を表示します。
各操作の前に mvn clean を実行することをお勧めします。mvn clean を実行するだけで target ディレクトリが削除されます (疑問?)。
Maven コマンドを実行する際の特徴は、以前のプロセスを先に完了させることです。例えば:
mvn clean package を実行する際、実際には mvn clean compile を先に実行し、その後 test を実行し、最後に package を実行します。
🥑 コア概念#
Maven が自動化ビルドを実現できるのは、その内部原理と切り離せません。ここでは Maven の 9 つのコア概念から始めて、Maven がどのように自動化ビルドを実現しているのかを見ていきます。
- POM
- 規約のディレクトリ構造
- 座標
- 依存関係管理
- リポジトリ管理
- ライフサイクル
- プラグインとゴール
- 継承
- 集約
Maven のコアプログラムでは抽象的なライフサイクルのみが定義されており、具体的な操作は Maven のプラグインによって実行されます。しかし、Maven のプラグインは Maven のコアプログラムには含まれておらず、初めて使用する際にはインターネットに接続してダウンロードする必要があります。ダウンロードされたプラグインはローカルリポジトリに保存されます。ローカルリポジトリのデフォルトの位置は:~/.m2/repository
です。
🤖 POM#
Project Object Model:プロジェクトオブジェクトモデル。 Java プロジェクトの関連情報をオブジェクトとしてカプセル化し、操作と管理を容易にするモデルです。
<?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>demo</artifactId>
<version>1.0-SNAPSHOT</version>
<name>demo</name>
<packaging>war</packaging>
<properties>
</properties>
<dependencies>
</dependencies>
<build>
<plugins>
</plugins>
</build>
</project>
⚓ 座標#
Maven プロジェクトのコア設定。
G-A-V:3 つのベクトルを使用して、子リポジトリ内で Maven プロジェクトを一意に特定します。
- groupid:会社または組織のドメイン名を逆順に
- artifactid:モジュール名、実際のプロジェクト名でもあります
- version:現在のプロジェクトのバージョン
<groupId>ink.onei</groupId>
<artifactId>Hello</artifactId>
<version>0.0.1-SNAPSHOT</version>
座標を使ってリポジトリ内でパッケージを検索するには?
- gav の 3 つのベクトルをつなげる
ink.onei+Hello+0.0.1-SNAPSHOT
- つなげた文字列をディレクトリ構造としてリポジトリ内で検索
ink/onei/0.0.1-SNAPSHOT/Hello-0.0.1-SNAPSHOT.jar
注意:自分の Maven プロジェクトはインストール操作を実行しなければリポジトリに入ることはありません。インストールのコマンドは:mvn install
🏗️ 構造#
Java 開発分野で広く認識されている見解:規約 > 設定 > コーディング(設定で解決できる問題はコーディングしない、規約に基づくものは設定しない)
Maven プロジェクトディレクトリ
プロジェクトルートディレクトリ プロジェクト名をルートディレクトリとして
├─src ソースコードディレクトリ
│ ├─main メインプログラムディレクトリ
│ │ ├─java メインプログラムのJavaソースファイルディレクトリ
│ │ │
│ │ └─resources メインプログラムのリソースファイルディレクトリ
│ │
│ └─test テストプログラムディレクトリ
│ ├─java テストプログラムディレクトリ
│ │
│ └─resources テストプログラムのリソースファイルディレクトリ
└─target コンパイル構造
├─classes
│
└─generated-sources
└─annotations
🎨 依存関係#
Maven の最も重要な部分であり、私たちが Maven を使用する主な理由はその依存関係管理機能です。Maven の依存関係管理を理解し、習得するためには、以下のいくつかの問題を解決する必要があります。
依存関係の目的#
A パッケージが B パッケージのいくつかのクラスを使用する場合、A は B に依存しています。これは概念的な説明です。では、プロジェクトに依存関係として必要なパッケージをどのように導入するのでしょうか? 答えは非常に簡単で、dependency
タグを使用して依存パッケージの座標を指定するだけです。
<dependency>
<groupId>ink.onei</groupId>
<artifactId>Hello</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
依存関係の範囲#
時には依存情報にターゲットパッケージの座標に加えて scope 設定があり、これが依存関係の範囲です。依存関係の範囲にはいくつかの選択肢があり、一般的に使用されるのは:compile
、test
、provided
の 3 つで、もちろんあまり使用されないruntime
、system
もあります...
- compile:デフォルトの範囲で、コンパイル、テスト、実行すべてに有効
- provided:コンパイルとテスト時に有効
- runtime:テストと実行時に有効
- test:テスト時のみ有効
- system:コンパイルとテスト時に有効で、ローカルシステムに関連し、移植性が低い
一般的な依存範囲の有効性のまとめ
compile | test | provided | |
---|---|---|---|
メインプログラム | ✔️ | ❌ | ✔️ |
テストプログラム | ✔️ | ✔️ | ✔️ |
デプロイに参加 | ✔️ | ❌ | ❌ |
依存関係の伝播性#
A が B に依存し、B が C に依存する場合、A は C を使用できるのでしょうか?それは B が C に依存する範囲が compile であるかどうかによります。もしそうであれば使用可能ですが、そうでなければ使用できません。
依存関係の除外#
現在のプロジェクトに A という依存関係を導入した場合、A が B に依存していると、Maven は自動的に A が依存している B を現在のプロジェクトに導入しますが、特定の状況では B が不安定なバージョンであるか、現在のプロジェクトに悪影響を及ぼす可能性があります。この場合、A を導入する際に B を除外することができます。
<dependency>
<groupId>ink.onei</groupId>
<artifactId>Hello</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
依存関係のバージョンを統一管理#
依存パッケージのバージョンを統一管理し、同じフレームワークの一群のパッケージはできるだけ同じバージョンを使用するのが望ましいです。フレームワークのアップグレードを容易にするために、パッケージのバージョン情報を統一して抽出します。
- バージョン番号を統一宣言
<properties> <starfish.spring.version>4.1.1.RELEASE</starfish.spring.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties>
- 前に宣言したバージョン番号を参照
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${starfish.spring.version}</version> <scope>compile</scope> </dependency>
依存関係の原則#
パッケージの衝突を解決する
- パスが最短のものを優先
- パスが同じ場合は先に宣言したものを優先
📦 リポジトリ管理#
- ローカルリポジトリ
現在のコンピュータ上のすべての Maven プロジェクトにサービスを提供します。 - リモートリポジトリ
- 中央リポジトリ これはデフォルトのリポジトリです。
インターネット上に設置されており、全世界のすべての Maven プロジェクトにサービスを提供します。 - ミラーリポジトリ
settings.xml
のsettings.mirrors.mirror
設定を通じて構築されます。
各大陸に設置され、中央リポジトリのトラフィックを分担します。中央リポジトリの負担を軽減し、ユーザーのリクエストにより迅速に応答します。例えば、阿里云ミラーリポジトリ。 - プライベートリポジトリ
現在のローカルエリアネットワーク環境に設置され、現在のローカルエリアネットワーク内のすべての Maven プロジェクトにサービスを提供します。
- 中央リポジトリ これはデフォルトのリポジトリです。
リポジトリ内のファイル
- Maven のプラグイン
- 私たち自身が開発したプロジェクトのモジュール
- サードパーティのフレームワークやツールのパッケージ
どのようなパッケージでも、リポジトリ内では座標に基づいてディレクトリ構造が生成されるため、統一された方法で検索または依存関係を管理できます。
その他のリポジトリ#
グローバルプロファイルリポジトリは、settings.xml
の settings.repositories.repository
設定を通じて構築されます。
プロジェクトリポジトリは、pom.xml
の project.repositories.repository
設定を通じて構築されます。
プロジェクトプロファイルリポジトリは、pom.xml
の project.profiles.profile.repositories.repository
設定を通じて構築されます。
🌱 ライフサイクル#
Maven のライフサイクルとは何か#
Maven ライフサイクルは、各ビルドステップの実行順序を定義します。このリストがあれば、Maven は自動的にビルドコマンドを実行できます。
Maven には 3 つの相互に独立したライフサイクルがあります。それぞれは:
- Clean Lifecycle 実際のビルドを行う前にいくつかのクリーンアップ作業を行います。
- Default Lifecycle ビルドのコア部分で、コンパイル、テスト、パッケージング、インストール、デプロイなどを行います。
- Site Lifecycle プロジェクトレポート、サイトを生成し、サイトを公開します。
これらは相互に独立しており、clean を呼び出して作業ディレクトリをクリーンアップすることも、site を呼び出してサイトを生成することもできます。もちろん、mvn clean install site
を直接実行してこれら 3 つのライフサイクルをすべて実行することもできます。各ライフサイクルは一連のフェーズ(Phase)で構成されており、通常、コマンドラインで入力するコマンドは特定のフェーズに対応します。例えば、mvn clean
を実行すると、この clean は Clean ライフサイクルの一つのフェーズです。Clean ライフサイクルもあれば、clean フェーズもあります。
Clean ライフサイクル#
Clean ライフサイクルは合計 3 つのフェーズを含みます:
- pre-clean clean の前に完了する必要がある作業を実行します。
- clean 前回のビルドで生成されたすべてのファイルを削除します。
- post-clean clean の後にすぐに完了する必要がある作業を実行します。
Site ライフサイクル#
- pre-site サイト文書を生成する前に完了する必要がある作業を実行します。
- site プロジェクトのサイト文書を生成します。
- post-site サイト文書を生成した後に完了する必要がある作業を実行し、デプロイの準備をします。
- site-deploy 生成されたサイト文書を特定のサーバーにデプロイします。ここでよく使用されるのは site フェーズと site-deploy フェーズで、Maven サイトを生成し公開するために使用されます。これは Maven の非常に強力な機能であり、マネージャーが非常に好むもので、文書や統計データが自動生成され、非常に見栄えが良いです。
Default ライフサイクル#
Default ライフサイクルは Maven ライフサイクルの中で最も重要なものであり、ほとんどの作業はこのライフサイクル内で発生します(いくつかの重要なフェーズを列挙します)。
- validate プロジェクトが正しいか、すべての必要なリソースが利用可能かを検証します。
- compile プロジェクトのソースコードをコンパイルします。
- test 適切な単体テストフレームワークを使用してコンパイルされたソースコードをテストします。これらのテストはパッケージ化およびデプロイされる必要はありません。
- package コンパイルされたコードをリリース可能な形式(例えば jar、war など)にパッケージ化します。
- integration-test 必要に応じて、パッケージを処理し、統合テストが可能な環境にデプロイします。
- verify すべてのチェックを実行し、パッケージが有効であり、品質基準を満たしているかを検証します。
- install パッケージを Maven のローカルリポジトリにインストールし、他のプロジェクトが依存関係として使用できるようにします。
- deploy 統合またはリリース環境で実行し、最終バージョンのパッケージをリモートリポジトリにコピーし、他の開発者やプロジェクトが共有できるようにします。
ライフサイクルと自動化ビルド#
任意のフェーズを実行する際には、その前のすべてのフェーズが実行されます。例えば、mvn install を実行すると、コードがコンパイルされ、テストされ、パッケージ化されます。これが Maven がなぜビルドプロセスの各ステップを自動的に実行できる理由です。さらに、Maven のプラグインメカニズムは完全に Maven のライフサイクルに依存しているため、ライフサイクルを理解することは非常に重要です。
🔌 プラグインとゴール#
- Maven のコアは抽象的なライフサイクルのみを定義しており、具体的なタスクはプラグインによって実行されます。
- 各プラグインは複数の機能を実現でき、各機能はプラグインゴールです。
- Maven のライフサイクルとプラグインゴールは相互に結びついており、特定のビルドタスクを完了します。
例えば:compile はプラグインmaven-compiler-plugin
の一つのゴールです;pre-clean はプラグインmaven-clean-plugin
の一つのゴールです。
🧬 継承#
なぜ継承メカニズムが必要なのか?
非compile
範囲の依存情報は「依存チェーン」で伝播できないため、必要なプロジェクトは個別に設定する必要があります。
- 親プロジェクトを作成 親プロジェクトの作成は一般的な Java プロジェクトの操作と同じですが、唯一注意が必要なのは:パッケージ方式を
pom
に設定することです。 - 子プロジェクトで親プロジェクトを参照し、現在のディレクトリから親プロジェクトの
pom.xml
ファイルへの相対パスを指定します。
<parent>
<groupId>com.starfish.maven</groupId>
<artifactId>Parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!-- 現在のファイルを基準とした親プロジェクトpom.xmlファイルの相対パス -->
<relativePath>../Parent/pom.xml</relativePath>
</parent>
この時、子プロジェクトのgroupId
とversion
が親プロジェクトと重複している場合は削除できます。
-
親プロジェクトで依存関係を管理します。Parent プロジェクト内の
dependencies
タグをdependencyManagement
タグで括ります。<dependencyManagement> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.9</version> <scope>test</scope> </dependency> </dependencies> </dependencyManagement>
-
子プロジェクトで必要な依存関係を再指定し、範囲とバージョン番号を削除します。
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> </dependency>
💞 集約#
なぜ集約を使用するのか?
複数のプロジェクトをモジュールに分割した後、手動でそれぞれをリポジトリにインストールしなければ依存関係が有効になりません。ソースコードを変更した後も、それぞれ手動で clean 操作を行う必要があります。しかし、集約を使用すると、Maven プロジェクトのインストールやクリーン作業を一括で行うことができます。
集約を構成するには、全体の集約プロジェクト内で modules/module タグを使用して組み合わせ、モジュールプロジェクトの相対パスを指定します。
<!-- 集約を構成 -->
<modules>
<!-- 各子プロジェクトの相対パスを指定 -->
<module>starfish-learn-grpc</module>
<module>starfish-learn-kafka</module>
<module>starfish-web-demo</module>
</modules>