Maven - 自定义archetype

Maven – 自定义archetype

前言

要自定义archetype,首先要了解maven的archetype是做什么的。

试想这样一个问题:当我们要从头创建一个maven工程时,需要做什么?

maven的原则是“约定大于配置”,因此,一个maven工程一定会有一个约定的、默认的目录额结构,如下所示:

a-test-project
|-- pom.xml
`-- src
    |-- main
    |   `-- java
    |   `-- resources
    |-- test
    |   `-- java
    |   `-- resources

这些文件和目录难道要一个个手动创建吗?当然不需要!maven archetype就是用来帮我们创建这些东西的。只需要简单地执行一行命令,一个maven工程就生成了。

如:

mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart

这里就用到了maven-archetype-quickstart这样一个archetype。自动生成的目录结构如下所示:

my-app
|-- pom.xml
`-- src
    |-- main
    |   `-- java
    |       `-- com
    |           `-- mycompany
    |               `-- app
    |                   `-- App.java
    `-- test
        `-- java
            `-- com
                `-- mycompany
                    `-- app
                        `-- AppTest.java

通过官网Introduction to Archetypes中列出了Maven默认提供的一些archetype,如:

  • maven-archetype-quickstart
  • maven-archetype-webapp

有了Maven默认提供的archetype就够了吗?如果我们想在生成project的时候把我们自定义的依赖放到pom.xml文件中怎么办?如果我们生成的project想添加dubbo/spring cloud进去怎么办?

显然,通过Maven提供的archetype是实现不了的。

但是,Maven支持自定义archetype,我们就可以通过自定义的archetype,把我们想生成的东西定义到archetype中,然后自动生成project时,一个命令行就可以搞定所有。

自定义archetype是通过Maven的maven-archetype-archetype这样一个archetype做到的。

官网描述:Maven Archetype Archetype
这里还有一篇国外大佬写的博客,非常不错:Guide to Maven Archetype

通过自定义的archetype,我们可以生成一个单module工程。如果喜欢父子工程这种组织结构,当然也是可以实现的。下面看看如何实现。

核心内容

首先要执行maven-archetype-archetype,生成archetype自定义框架

mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-archetype -DarchetypeVersion=1.3 

生成的目录结构如下所示(关于test部分的文件结构省略了):

qijin-quickstart/
├── README.md
├── pom.xml
├── src
│   ├── main
│   │   └── resources
│   │       ├── META-INF
│   │       │   └── maven
│   │       │       └── archetype-metadata.xml
│   │       └── archetype-resources
│   │           ├── pom.xml
│   │           └── src
│   │               ├── main
│   │               │   └── java
│   │               │       └── App.java
│   │               └── test
│   │                   └── java
│   │                       └── AppTest.java
│   └── test

这里面的核心在于src/main/resources/META-INF/maven/archetype-metadata.xml文件,这个是自定义archetype的描述文件。也就是说,你想生成怎样的自定义archetype,都是需要在这个文件中配置的。

关于archetype-metadata.xml文件的配置,可参看官网ArchetypeDescriptor,这里就不做一一解释了。

这里注意,archetype-metadata.xml文件只是定义了文件的复制规则、文件的过滤规则、占位符是否替换等。我们要生成的project,pom.xml文件的内容是怎样的,自动生成哪些目录和文件,是在src/main/resources/archetype-resources中定义的。

│   │       └── archetype-resources
│   │           ├── pom.xml
│   │           └── src
│   │               ├── main
│   │               │   └── java
│   │               │       └── App.java
│   │               └── test
│   │                   └── java
│   │                       └── AppTest.java

看到archetype-resources的目录结构,是不是感到很熟悉?没错,这个就是一个标准的maven目录结构。实际的情况是,默认配置下,archetype-resources目录下的文件内容和目录结构,就是我们要生成project的文件内容和目录结构。因此,archetype-resources下的pom.xml文件,即是最终生成project中的pom.xml文件。这样,我们就可以根据需要,随意在archetype-resources目录下,添加和修改内容了。

我们自定义的archetype写完后,mvn install一下,就像普通的jar包一样,安装到本地仓库了。注意,我们刚才做的所有事情只是自定义了一个archetype,并不是我们最终要生成的工程,我们需要像使用maven-archetype-quickstart一样使用它,才能得到最终的工程。

假设qijin-quickstart/pom.xml(这个文件是通过maven-archetype-archetype生成的)的内容如下所示(请主要关注groupIdartifactId):

<?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>tech.qijin.archetype</groupId>
    <artifactId>qijin-quickstart</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>maven-archetype</packaging>

    <name>Archetype - archetype</name>

    <!-- FIXME change it to the project's website -->
    <url>http://www.example.com</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
    </properties>
    <build>
        <extensions>
            <extension>
                <groupId>org.apache.maven.archetype</groupId>
                <artifactId>archetype-packaging</artifactId>
                <version>3.0.1</version>
            </extension>
        </extensions>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
            <plugins>
                <plugin>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>3.0.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-archetype-plugin</artifactId>
                    <version>3.0.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>3.0.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-install-plugin</artifactId>
                    <version>2.5.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-deploy-plugin</artifactId>
                    <version>2.8.2</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

mvn install命令后,通过如下命令,就可以像使用maven-archetype-quickstart一样,自动生成一个我们想要的工程了:

mvn archetype:generate -DarchetypeGroupId=tech.qijin.archetype -DarchetypeCatalog=local -DarchetypeArtifactId=qijin-multimodules -DarchetypeVersion=1.0-SNAPSHOT 

注:
-DarchetypeCatalog=local的意思是从本地repository查找archetype。如果使用mvn deploy命令将我们自定义的archetype deploy到远程仓库,这个参数可以不要。

单Module

步骤

  1. 执行maven-archetype-archetype,生成archetype自定义框架
  2. 根据需要修改archetype-resources目录下的文件(如只是初步了解,可以不修改)。
  3. 根据需要修改src/main/resources/META-INF/maven/archetype-metadata.xml(如只是初步了解,可以不修改)
  4. 一切完毕后,执行mvn install将自定义的archetype部署到本地repository。
  5. 如果想部署到远程仓库,可以执行mvn deploy
  6. 使用刚生成的archetype生成工程。

在参数中没有指定artifactIdgroupId等参数时,会使用Interactive mode,提示输入这些参数,不输入不会通过,如下提示:

Generating project in Interactive mode
[INFO] Archetype repository not defined. Using the one from [org.apache.maven.archetypes:maven-archetype-archetype:1.3] found in catalog remote
Define value for property ‘groupId’: Define value for property ‘artifactId’: Define value for property ‘version’ 1.0-SNAPSHOT: : Define value for property ‘package’

单module实现起来比较简单,通过上面的6个步骤,不用做任何修改,都能跑通所有流程。

但是,在一些工程实践中,通常会用到Maven的多Module模式,也叫父子工程。这种架构的工程也可以通过自定义archetype生成吗?显然,是可以的!

这里有一个我自己写的Demo,可以在此基础上修改后,直接使用:GitHub地址

多Module

多Module中,每个Module的pom.xml文件和目录结构都可能不一样,多个子Module还需要添加到父pom中,这是多Module的关键

顺着这个思路去想,单Module所有文件在archetype-resources中,显然是不够的。需要在这个目录下有多个文件夹。

具体怎么配置,可以参考这几篇博客(写得太累,不想写了,以后再补吧):

关键点在于:

  1. 文件夹使用__rootArtifactId__作为前缀,maven会自动把__rootArtifactId__替换成你写的artifactId。

举个例子:
如果archetype-resources目录下的目录结构是:

|--archetype-resources
|--pom.xml
|--|--__rootArtifactId__-db
|--|--__rootArtifactId__-service

最终通过这个archetype生成的工程时,如果设定的artifactId=account,目录结构会是:

|--pom.xml
|--|--account-db
|--|--account-service

有木有很方便

  1. src/main/resources/META-INF/maven/archetype-metadata.xml文件中添加相应的module模块和定义
<module id="${rootArtifactId}-db" dir="__rootArtifactId__-db" name="${rootArtifactId}-db">
...
</module>
<module id="${rootArtifactId}-server" dir="__rootArtifactId__-server" name="${rootArtifactId}-server">
...
</module>

这里有一个我自己写的Demo,可以在此基础上修改后,直接使用:GitHub地址

修改完成后,使用方法与单Module完全一样,如:

mvn archetype:generate -DarchetypeGroupId=tech.qijin.archetype -DarchetypeCatalog=local -DarchetypeArtifactId=qijin-multimodules -DarchetypeVersion=1.0-SNAPSHOT -DgroupId=tech.qijin.account  -DartifactId=account  -Dversion=1.0.0-SNAPSHOT  -Dpackage=tech.qijin.account
    原文作者:齐晋
    原文地址: https://www.jianshu.com/p/ac9b7d0556d1
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞