文章目录
- 一、maven 工程结构
- 1.1. jar 工程结构
- 1.2. war 工程结构
- 二、archetype 模板
- 2.1. 推荐的 archetype 模板
- 2.2. 自定义 archetype 模板
- 2.2.1 自定义模板示例
有没有好奇过,通过 Maven 生命周期命令构建项目时,我们并没有指定源文件目录和编译后的输出目录,为什么 Maven 可以自动能找到它们,并可以正确执行构建任务?
一、maven 工程结构
这是因为我们一直都是按照 Maven 默认的目录结构来创建 Maven 项目的,所以 Maven 在进行构建时就可以找到需要的文件,假设我们随意创建目录结构,这时执行 Maven 生命周期构建命令就不会成功
Maven 的默认目录结构的本质取决于我们构建项目时使用的生命周期插件,也就是说生命周期插件变化时,默认的目录结构也会发生变化,改变 Maven 生命周期插件大概有下面两种方式:
- 项目中明确指定构建项目时的生命周期插件
- 使用默认的生命周期插件
由于第一种方式的不确定性太大,所以本文主要针对第二种方式的目录结构进行记录
虽然是默认的生命周期插件,但是 Maven 却定义了多个默认的插件,运行生命周期构建命令时,其会根据我们项目中 pom.xml 里的 <packaging>
来决定具体使用的生命周期插件
1.1. jar 工程结构
在项目的 pom.xml
里设置 <packaging>jar</packaging>
时,以 package
阶段为终点,Maven 会默认使用 maven-resources-plugin
、maven-compiler-plugin
、maven-surefire-plugin
、maven-jar-plugin
这几个插件,此时要求的默认目录结构为:
项目根目录
目录 | 描述 | 是否需要提前准备 |
---|---|---|
pom.xml | Maven 项目的核心文件,配置依赖和构建信息 | 需要 |
src | 存放 Java 源文件和资源文件 | 需要 |
target | 存放 Maven 执行构建后生成的文件 | 不需要 |
src 目录
目录 | 描述 | 是否需要提前准备 |
---|---|---|
main | 存放 Java 源文件和资源文件 | 需要 |
test | 存放测试用的 Java 源文件和资源文件 | 按需 |
main 目录
目录 | 描述 | 是否需要提前准备 |
---|---|---|
java | 以包路径的形式存放 Java 源文件, compile 阶段会对该目录下的 Java 源文件进行编译 | 需要 |
resources | 存放资源文件,process-resources 阶段会复制该目录下的文件 | 按需 |
test 目录
目录 | 描述 | 是否需要提前准备 |
---|---|---|
java | 以包路径的形式存放 Java 源文件这里的 Java 源文件一般搭配测试框架 junit 等 ,test-compile 阶段会对该目录下的 Java 源文件进行编译 | 按需 |
resources | 存放测试用的资源文件,process-test-resources 阶段会复制该目录下的文件 | 按需 |
target 目录
目录 | 描述 | 是否需要提前准备 |
---|---|---|
classes | 1. 执行 compile 后会编译 main->java 中的 Java 源文件,并将编译后的二进制文件存放到此2. 执行 process-resources 后会从 main->resources 中将文件复制过来 | 不需要 |
test-classes | 1. 执行 test-compile 后会编译 test->java 中的 Java 源文件,并将编译后的二进制文件存放到此2. 执行 process-test-resources 后会从 test->resources 中将文件复制过来 | 不需要 |
以上就是 Maven 生成 jar
包时最标准的目录结构(最后生成的 jar
文件的内部结构和 classes
文件夹结构相同)
我们执行一下 package
阶段,看看效果:
1.2. war 工程结构
在项目的 pom.xml
里设置 <packaging>war</packaging>
时,以 package
阶段为终点,Maven 会默认使用 maven-resources-plugin
、maven-compiler-plugin
、maven-surefire-plugin
、maven-war-plugin
这几个插件,此时要求的默认目录结构为:
项目根目录
目录 | 描述 | 是否需要提前准备 |
---|---|---|
pom.xml | Maven 项目的核心文件,配置依赖和构建信息 | 需要 |
src | 存放 Java 源文件和资源文件 | 需要 |
target | 存放 Maven 执行构建后生成的文件 | 不需要 |
src 目录
目录 | 描述 | 是否需要提前准备 |
---|---|---|
main | 存放 Java 源文件和资源文件 | 需要 |
main 目录
目录 | 描述 | 是否需要提前准备 |
---|---|---|
java | 以包路径的形式存放 Java 源文件, compile 阶段会对该目录下的 Java 源文件进行编译 | 需要 |
resources | 存放资源文件,process-resources 阶段会复制该目录下的文件 | 按需 |
webapp | 这个目录的命名是 Maven 构建 servlet 项目的特点,一般看见 webapp 就知道是 Maven 构建的需要放 到外置容器执行的 servlet web 项目, package 阶段执行时,会复制该目录下的全部内容,该目录的内部结构需要符合 web 容器的解析结构,既 war 包结构 | 必须 |
我们执行一下 package
阶段,看看效果:
二、archetype 模板
知道了 Maven 项目的标准结构,就可以按照这个结构创建 Maven 项目了,如果觉得创建这些目录结构很繁琐,或者自己经常记不住,那我们也可以使用 mvn archetype:generate
命令,这种方式可以选择别人定义好的模板,然后按照选定的模板自动帮我们创建一个 Maven 项目
2.1. 推荐的 archetype 模板
别人写好的 maven archetype 模板实在是太多了,这里我推荐两个官方发布的
- 生成
<packaging>jar</packaging>
时的目录结构:maven-archetype-quickstart
- 生成
<packaging>war</packaging>
时的目录结构:maven-archetype-webapp
使用模板生成项目的命令:
mvn archetype:generate
-DarchetypeGroupId=模板的gourpId
-DarchetypeArtifactId=模板的artifactId
-DarchetypeVersion=模板的version
-DgroupId=要生成的项目的groupId
-DartifactId=要生成的项目的artifactId
-Dversion=要生成的项目的version
指定模板的 groupId
、artifactId
、version
,和待生成项目的 groupId
、artifactId
、version
如果敲命令时不会换行,就把命令敲在同一行
以 maven-archetype-quickstart
模板为例效果如下:
使用 maven-archetype-quickstart
模板生成项目后的结构如下:
可以看到生成的目录结构基本算是一个标准的结构了,而且还帮我们生成了一个基础类 App
,剩下的我们按照自己的需求,在这个结构基础上改造就可以了
2.2. 自定义 archetype 模板
如果找不到满意的第三方模板,也可以自己定义一个,这样以后每次生成项目的时候就可以使用自己的模板了
想创建自己的模板,这时候我们 Maven 的目录结构又有新要求了,其核心的目录结构如下:
简单介绍下重要的地方:
1.archetype-resources
目录内容,就是我们的模板内容,用来定义模板结构
2.META-INF/maven/archetype.xml
把要生成的文件声明在这个文件中,这个文件也可以命名为 archetype-metadata.xml
,
但是语法也会有变化,我个人比较推荐 archetype.xml
,感觉语法比较简单
2.2.1 自定义模板示例
现在就演示一下,如何定义一个模板,然后通过这个模板创建项目
1. 按照目录要求,创建模板项目
手动创建或通过已有模板 maven-archetype-archetype
创建都可以,只要最后的结构对了就可以
2. 定义使用该模板生成项目时的结构和文件
在 archetype-resources
下,按自己的想法定义结构,下图红框里的结构,就是后期使用这个模板生成的项目结构
3. 给待生成的文件内填点内容
在 archetype-resources/src/main/java/config/Config.java
中随便加点代码,其中 ${package}
可以获取到我们通过模板创建时指定的 package
,之后生成项目时会自动填充到这里
package ${package}.config;
public class Config {
}
在 archetype-resources/pom.xml
中随便加点配置, ${groupId}
可以获取到我们通过模板创建时指定的 groupId
,${artifactId}
可以获取到我们通过模板创建时指定的 artifactId
,${version}
可以获取到我们通过模板创建时指定的 version
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>${groupId}</groupId>
<artifactId>${artifactId}</artifactId>
<version>${version}</version>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>
</dependencies>
</project>
4. 定义生成时要输出的文件
在 META-INF/maven/archetype.xml
中添加配置
<archetype>
<id>ares5k-archetype</id>
<sources>
<source encoding="UTF-8">src/main/java/config/Config.java</source>
</sources>
<resources>
<resource encoding="UTF-8">src/main/resources/env.properties</resource>
</resources>
<testSources>
<source encoding="UTF-8">src/test/java/config/ConfigTest.java</source>
</testSources>
</archetype>
5. 安装部署插件
运行 mvn install
或 mvn deploy
将项目打包安装或部署
6. 使用模板,验证生成的结构
正常用 Maven 使用模板的命令就可以了,mvn archetype:generate -DarchetypeGroupId=com.ares5k -DarchetypeArtifactId=ares5k-archetype -DarchetypeVersion=1.0-SNAPSHOT -DgroupId=com.ares5k -DartifactId=test-archetype -Dversion=1.0
生成后的结构如下,:
可以看到,生成的结构和我们在 archetype-resources/pom.xml
中定义的结构几乎一样,为啥说是几乎一样呢,因为我们在 archetype-resources
中定义的结构是 src/main/java/config/Config.java
,而生成的结构中自动帮我们加上了包名 src/main/java/com/ares5k/config/Config.java
,可以说是非常智能,test/java
目录同理也加上了包名
接下来验证一下生成的文件内容:
Config.java
中的 ${package}
被成功的替换成生成时指定的 package
:
package com.ares5k.config;
public class Config {
}
pom.xml
中的 ${groupId}
、${artifactId}
、${version}
也被成功替换
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.ares5k</groupId>
<artifactId>test-archetype</artifactId>
<version>1.0</version>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>
</dependencies>
</project>