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
生成的)的内容如下所示(请主要关注groupId
和artifactId
):
<?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
步骤
- 执行maven-archetype-archetype,生成archetype自定义框架
- 根据需要修改
archetype-resources
目录下的文件(如只是初步了解,可以不修改)。 - 根据需要修改
src/main/resources/META-INF/maven/archetype-metadata.xml
(如只是初步了解,可以不修改) - 一切完毕后,执行
mvn install
将自定义的archetype部署到本地repository。 - 如果想部署到远程仓库,可以执行
mvn deploy
- 使用刚生成的archetype生成工程。
在参数中没有指定artifactId
、groupId
等参数时,会使用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
中,显然是不够的。需要在这个目录下有多个文件夹。
具体怎么配置,可以参考这几篇博客(写得太累,不想写了,以后再补吧):
关键点在于:
- 文件夹使用
__rootArtifactId__
作为前缀,maven会自动把__rootArtifactId__
替换成你写的artifactId。
举个例子:
如果archetype-resources
目录下的目录结构是:
|--archetype-resources
|--pom.xml
|--|--__rootArtifactId__-db
|--|--__rootArtifactId__-service
最终通过这个archetype生成的工程时,如果设定的artifactId=account,目录结构会是:
|--pom.xml
|--|--account-db
|--|--account-service
有木有很方便
-
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