maven自定义archetype项目脚手架

背景

maven是一个很好的代码构建工具,采用“约定优先于配置”的原则进行项目管理,相信很多的java开发者应该都了解maven并可能在工作当中都是通过maven来管理项目的,在创建的项目的时候,我们往往会使用maven内置的项目骨架也就是archetype来快速生成项目结构。但是在一个团队做开发的过程中,可能仅仅依靠maven预先提供的archetyp可能是不够的,团队之间协作有自己的定义方式,每个人的结构定义风格也不尽相同,在这样的背景下我们有必要去定义一个统一的代码骨架供团队使用,这样做的好处是当团队需要开始一个新项目的时候,可以利用自定义的maven骨架一键生成项目。

archetype是在maven-archetype-plugin插件执行generate目标的时候进行配置的,我们经常使用到maven的内嵌的骨架包括:maven-archetype-webapp、maven-archetype-quickstart。前者用来快速搭建一个web工程项目,后者用来快速搭建一个普通的java工程项目。

单模块项目的archetype

单模块项目的archetype脚手架项目的结构
avatar
上图中的各个文件详解:

  • 根目录beast-archetype下的pom.xml和一般的maven项目一样主要定义archetype项目的坐标等信息。
  • 所有的项目骨架内容都集中在src/main/resources/archetype-resources文件夹下。
  • archetype-resources中的pom.xml定义了待生成项目的pom文件的内容,/src/main/java、/src/test/java中分别定义了待生成项目中相应目录下的内容
  • /src/main/resources/META-INF/maven/archetype-metadata.xml中定义相关的元数据描述(其中该文件的位置固定为resources/META-INF/maven文件夹下,且名称固定为archetype-metadata.xml)。

1.beast-archetype/pom.xml内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<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.thebeastshop</groupId>
<artifactId>beast-archetype</artifactId>
<version>1.1</version>
<packaging>jar</packaging>

<name>beast-archetype</name>
<url>http://maven.apache.org</url>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>beast-archetype</finalName>
</build>
</project>

其中:上面${}标识的变量都是通过maven中的命令行传进来的,如:mvn archetype:generate -DgroupId=com.thebeastshop
2.src/main/resources/archetype-resources/pom.xml内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<?xml version="1.0"?>
<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>${groupId}</groupId>
<artifactId>${artifactId}</artifactId>
<version>${version}</version>
<name>${artifactId}</name>

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-archetype-plugin</artifactId>
<version>2.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

其中:上面${}标识的变量都是通过maven中的命令行传进来的,如:mvn archetype:generate -DgroupId=com.thebeastshop
3.src/main/resources/META-INF/maven/archetype-metadata.xml内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<?xml version="1.0" encoding="UTF-8"?>
<archetype-descriptor name="beast-archetype"
xmlns="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0
http://maven.apache.org/xsd/archetype-descriptor-1.0.0.xsd">

<requiredProperties>
<requiredProperty key="package-name" />
</requiredProperties>

<fileSets>
<fileSet filtered="true" packaged="true" encoding="UTF-8">
<directory>src/main/java</directory>
<includes>
<include>**/*.java</include>
</includes>
</fileSet>
<fileSet filtered="true" encoding="UTF-8">
<directory>src/main/resources</directory>
<includes>
<include>**/*.*</include>
</includes>
</fileSet>
<fileSet filtered="true" packaged="true" encoding="UTF-8">
<directory>src/test/java</directory>
<includes>
<include>**/*.java</include>
</includes>
</fileSet>
<fileSet encoding="UTF-8">
<directory>src/test/resources</directory>
<includes>
<include>**/*.*</include>
</includes>
</fileSet>
</fileSets>
</archetype-descriptor>

说明:

  • packaged=”true”标识src/main/resources/archetype-resources/src/main/java中对应的内容是否要放入到package中,比如package为com.thebeastshop,那么如果该属性为true,则对应的java文件会放到com/thebeastshop文件夹下,也就是包路径下。
  • filtered=”true”标识下面提到的${}是否要进行替换

4.src/main/resources/archetype-resources/src/main/java/Demo.java内容如下:

1
2
3
4
5
6
7
8
package ${package};

public class Demo{
public static void main( String[] args )
{
System.out.println( "Hello My Archetype!" );
}
}

5.这样我们就手写好了一个自定义的maven的archetype骨架项目,我们只需要通过mvn clean install 命令把该jar包安装到本地仓库,然后通过本地仓库中的该jar包来生成一个项目看看效果,使用如下命令:

1
2
3
4
5
6
mvn archetype:generate 
  -DgroupId=comthebeastshop
  -DartifactId=beast-test
  -Dpackage="com.thebeastshop.test"
  -DarchetypeGroupId=com.thebeastshop
  -DarchetypeArtifactId=beast-archetype -DarchetypeVersion=1.1 -X -DarchetypeCatalog=local

多模块项目的archetype

1.多模块骨架项目的项目结构
avatar

这跟单模块项目区别不大,但是有几个概念需要说明:

  • rootArtifactId”占位符会被parent项目的artifactId替换
  • ${rootArtifactId}也会被parent项目的artifactId替换
  • src/main/resources/archetype-resources里必须要有一个顶级pom文件(如果是单工程就是工程pom文件),同时子文件夹代表了模块定义
    2.模板工程定义描述文件:META-INF/maven/archetype-metadata.xml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    <?xml version="1.0" encoding="UTF-8"?>
    <archetype-descriptor name="beast-archetype"
    xmlns="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
    http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0
    http://maven.apache.org/xsd/archetype-descriptor-1.0.0.xsd">

    <requiredProperties>
    <requiredProperty key="groupId">
    <defaultValue>com.thebeastshop</defaultValue>
    </requiredProperty>
    <requiredProperty key="artifactId">
    <defaultValue>test</defaultValue>
    </requiredProperty>
    <requiredProperty key="package">
    <defaultValue>com.thebeastshop.test</defaultValue>
    </requiredProperty>
    </requiredProperties>

    <modules>
    <module id="${rootArtifactId}-api" name="${rootArtifactId}-api" dir="__rootArtifactId__-api">
    <fileSets>
    <fileSet filtered="true" encoding="UTF-8" packaged="true">
    <directory>src/main/java</directory>
    <includes>
    <include>**/*.*</include>
    </includes>
    </fileSet>
    <fileSet filtered="true" encoding="UTF-8" packaged="true">
    <directory>src/test/java</directory>
    <includes>
    <include>**/*.*</include>
    </includes>
    </fileSet>
    <fileSet encoding="UTF-8">
    <directory>src/main/resources</directory>
    <includes>
    <include>**/*.*</include>
    </includes>
    </fileSet>
    <fileSet encoding="UTF-8">
    <directory>src/test/resources</directory>
    <includes>
    <include>**/*.*</include>
    </includes>
    </fileSet>
    </fileSets>
    </module>
    <module id="${rootArtifactId}-core" name="${rootArtifactId}-core" dir="__rootArtifactId__-core">
    <fileSets>
    <fileSet filtered="true" encoding="UTF-8" packaged="true">
    <directory>src/main/java</directory>
    <includes>
    <include>**/*.*</include>
    </includes>
    </fileSet>
    <fileSet filtered="true" encoding="UTF-8" packaged="true">
    <directory>src/test/java</directory>
    <includes>
    <include>**/*.*</include>
    </includes>
    </fileSet>
    <fileSet filtered="true" encoding="UTF-8">
    <directory>src/main/resources</directory>
    <includes>
    <include>**/*.*</include>
    </includes>
    </fileSet>
    <fileSet encoding="UTF-8">
    <directory>src/test/resources</directory>
    <includes>
    <include>**/*.*</include>
    </includes>
    </fileSet>
    </fileSets>
    </module>
    <module id="${rootArtifactId}-dao" name="${rootArtifactId}-dao" dir="__rootArtifactId__-dao">
    <fileSets>
    <fileSet filtered="true" encoding="UTF-8" packaged="true">
    <directory>src/main/java</directory>
    <includes>
    <include>**/*.*</include>
    </includes>
    </fileSet>
    <fileSet filtered="true" encoding="UTF-8" packaged="true">
    <directory>src/test/java</directory>
    <includes>
    <include>**/*.*</include>
    </includes>
    </fileSet>
    <fileSet filtered="true" encoding="UTF-8">
    <directory>src/main/resources</directory>
    <includes>
    <include>**/*.*</include>
    <include>mapper</include>
    </includes>
    </fileSet>
    <fileSet encoding="UTF-8">
    <directory>src/test/resources</directory>
    <includes>
    <include>**/*.*</include>
    </includes>
    </fileSet>
    </fileSets>
    </module>
    <module id="${rootArtifactId}-main" name="${rootArtifactId}-main" dir="__rootArtifactId__-main">
    <fileSets>
    <fileSet filtered="true" encoding="UTF-8" packaged="true">
    <directory>src/main/java</directory>
    <includes>
    <include>**/*.*</include>
    </includes>
    </fileSet>
    <fileSet filtered="true" encoding="UTF-8" packaged="true">
    <directory>src/test/java</directory>
    <includes>
    <include>**/*.*</include>
    </includes>
    </fileSet>
    <fileSet filtered="true" encoding="UTF-8">
    <directory>src/main/resources</directory>
    <includes>
    <include>**/*.*</include>
    </includes>
    </fileSet>
    <fileSet encoding="UTF-8">
    <directory>src/test/resources</directory>
    <includes>
    <include>**/*.*</include>
    </includes>
    </fileSet>
    <fileSet encoding="UTF-8">
    <directory>src/main/assembly</directory>
    <includes>
    <include>**/*.*</include>
    </includes>
    </fileSet>
    <fileSet encoding="UTF-8">
    <directory>src/main/bin</directory>
    <includes>
    <include>**/*.*</include>
    </includes>
    </fileSet>
    </fileSets>
    </module>
    <module id="${rootArtifactId}-mybatisGen" name="${rootArtifactId}-mybatisGen" dir="__rootArtifactId__-mybatisGen">
    <fileSets>
    <fileSet filtered="true" encoding="UTF-8" packaged="true">
    <directory>src/main/java</directory>
    <includes>
    <include>**/*.*</include>
    </includes>
    </fileSet>
    <fileSet filtered="true" encoding="UTF-8" packaged="true">
    <directory>src/test/java</directory>
    <includes>
    <include>**/*.*</include>
    </includes>
    </fileSet>
    <fileSet encoding="UTF-8">
    <directory>src/main/resources</directory>
    <includes>
    <include>**/*.*</include>
    </includes>
    </fileSet>
    <fileSet encoding="UTF-8">
    <directory>src/test/resources</directory>
    <includes>
    <include>**/*.*</include>
    </includes>
    </fileSet>
    </fileSets>
    </module>
    </modules>
    </archetype-descriptor>
  • 属性变量定义,这些属性可以在资源元文件里的任意一个文件里通过${var}来引用,所以的元文件最终都可以选择通过velocity引擎来执行替换后生成。默认的属性有:groupId,artifactId,packeage,version等