基于前两篇《Maven浅窥一:基础》《Maven浅窥二:复杂项目》,应该已经可以创建Maven项目,甚至是较大的Maven项目。

然而,第一个经常遇到的问题是,通过archetype “maven-archetype-quickstart”(版本1.4)创建的project,都需要手动修改pom.xml。譬如,如果不想使用默认的junit 4.11而想使用junit 5,不得不每次都修改pom,更麻烦的,junit 4到junit 5是breaking change,所以只修改pom文件显然不够,还得修改默认的test文件,才能解决最起码的语法错误。

那么,archetype到底是个啥东东?查看官方文档:

Archetype is a Maven project templating toolkit. An archetype is defined as an original pattern or model from which all other things of the same kind are made

官方Lifecyle图:

Archetype

说白了,archetype是个脚手架。跟Angular的”ng generate”类似,但是更原始且不会up to date。那么,如果想要避免每次都手工修改一大堆文件,创建一个local的archetype看起来是个不错的选择。

本文代码使用Github Repo: link

步骤一、创建一个基于archetype的空project

在想要创建的目录下,运行如下命令:

mvn -B archetype:generate -DgroupId="com.alvachien.app" -DartifactId="maven-tutorial-3" -DarchetypeArtifactId="maven-archetype-quickstart" -DarchetypeVersion="1.4"

这时,文件夹maven-tutorial-3应该被创建成功。

步骤二、修改POM以及相关的文件

修改POM.xml如下:

<?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.alvachien.learning</groupId>
  <artifactId>maven-tutorial-3</artifactId>
  <version>1.0-SNAPSHOT</version>

  <name>maven-tutorial-3</name>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>11</java.version>
    <junit.version>5.7.0</junit.version>

    <!-- Plugin versions -->
    <maven.shade>3.2.2</maven.shade>
    <maven.clean>3.1.0</maven.clean>
    <maven.resources>3.1.0</maven.resources>
    <maven.compiler>3.8.1</maven.compiler>
    <maven.surefire>3.0.0-M5</maven.surefire>
    <maven.jar>3.2.0</maven.jar>
    <maven.install>3.0.0-M1</maven.install>
    <maven.deploy>2.8.2</maven.deploy>
    <maven.site>3.7.1</maven.site>

    <maven.compiler.source>${java.version}</maven.compiler.source>
    <maven.compiler.target>${java.version}</maven.compiler.target>
    <maven.compiler.release>${java.version}</maven.compiler.release>
  </properties>

  <dependencies>
    <dependency>
			<groupId>org.junit.jupiter</groupId>
			<artifactId>junit-jupiter</artifactId>
      <version>${junit.version}</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>${maven.clean}</version>
        </plugin>
        <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>${maven.resources}</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>${maven.compiler}</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>${maven.surefire}</version>
        </plugin>
        <plugin>
          <artifactId>maven-jar-plugin</artifactId>
          <version>${maven.jar}</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>${maven.install}</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>${maven.deploy}</version>
        </plugin>
        <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
        <plugin>
          <artifactId>maven-site-plugin</artifactId>
          <version>${maven.site}</version>
        </plugin>
        <plugin>
          <artifactId>maven-project-info-reports-plugin</artifactId>
          <version>3.0.0</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

修改AppTest.java如下:

import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;

public class AppTest {
    @Test
    public void shouldAnswerWithTrue() {
        assertTrue(true);
    }
}

步骤三、生成一个复用的archetype

运行如下命令:

mvn archetype:create-from-project

输出结果:

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  6.499 s
[INFO] Finished at: 2020-11-29T18:47:55+08:00
[INFO] ------------------------------------------------------------------------
[INFO] Archetype project created in D:\srccodes\git\learning-notes\maven-tutorial-3\target\generated-sources\archetype
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  11.063 s
[INFO] Finished at: 2020-11-29T18:47:55+08:00
[INFO] ------------------------------------------------------------------------

在对应的target目录,会有一个

target
└─generated-sources
   └─archetype
       └─src
          ├─main
          │  └─resources
          │      ├─archetype-resources
          │      │  ├─.settings
          │      │  ├─.vscode
          │      │  └─src
          │      │      ├─main
          │      │      │  └─java
          │      │      └─test
          │      │          └─java
          │      └─META-INF
          │          └─maven
          └─test
              └─resources
                  └─projects
                      └─basic

步骤四、安装自定义的archetype到local repository

这时,在目录\target\generated-sources\archetype下,运行命令:

mvn install

该命令会将目录\target\generated-sources\archetype下的archetype.jar安装在local repository中。

Windows下,Local repository对应的目录为:C:\Users\ ~windows_user~ \ .m2\repository中。

该目录下会有一个archetype-catalog.xml文件,打开之后会发现其内容就是刚刚创建的archetype:

<?xml version="1.0" encoding="UTF-8"?>
<archetype-catalog xsi:schemaLocation="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-catalog/1.0.0 http://maven.apache.org/xsd/archetype-catalog-1.0.0.xsd"
    xmlns="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-catalog/1.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <archetypes>
    <archetype>
      <groupId>com.alvachien.learning</groupId>
      <artifactId>maven-tutorial-3-archetype</artifactId>
      <version>1.0-SNAPSHOT</version>
      <description>maven-tutorial-3-archetype</description>
    </archetype>
  </archetypes>
</archetype-catalog>

该文件夹下,\com\alvachien\learning\maven-tutorial-3-archetype内容如下:

C:.
│  maven-metadata-local.xml
│
└─1.0-SNAPSHOT
        maven-metadata-local.xml
        maven-tutorial-3-archetype-1.0-SNAPSHOT.jar
        maven-tutorial-3-archetype-1.0-SNAPSHOT.pom
        _remote.repositories

其中maven-metadata-local.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<metadata>
  <groupId>com.alvachien.learning</groupId>
  <artifactId>maven-tutorial-3-archetype</artifactId>
  <versioning>
    <versions>
      <version>1.0-SNAPSHOT</version>
    </versions>
    <lastUpdated>20201129115103</lastUpdated>
  </versioning>
</metadata>

步骤五、创建一个新project

在新的目录下,运行:

mvn archetype:generate -DarchetypeCatalog=local

这时系统会罗列当前local repository中所有的archetype:

[INFO] Scanning for projects...
[INFO]
[INFO] ------------------< org.apache.maven:standalone-pom >-------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] --------------------------------[ pom ]---------------------------------
[INFO]
[INFO] >>> maven-archetype-plugin:3.2.0:generate (default-cli) > generate-sources @ standalone-pom >>>
[INFO]
[INFO] <<< maven-archetype-plugin:3.2.0:generate (default-cli) < generate-sources @ standalone-pom <<<
[INFO]
[INFO]
[INFO] --- maven-archetype-plugin:3.2.0:generate (default-cli) @ standalone-pom ---
[INFO] Generating project in Interactive mode
[INFO] No archetype defined. Using maven-archetype-quickstart (org.apache.maven.archetypes:maven-archetype-quickstart:1.0)
Choose archetype:
1: local -> com.alvachien.learning:maven-tutorial-3-archetype (maven-tutorial-3-archetype)
Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): :

按照提示可以继续创建project。打开生成的POM文件,就会发现所有的dependency都被正确设置。