Preface
本文将介绍 Maxwell-Admin 中后台管理系统的构建过程和开发环境配置,只会讲解其中所涉及到的知识点,并不会详细讲解这个项目。
其中包括:
- Maven 父子工程、聚合工程、项目版本号统一处理。
- IDEA 开发环境配置和常用插件。
Maven
实际的开发项目中绝大多数用的都是 Maven 父子工程及聚合工程相结合的方式构建项目。由于项目模块的不断增加,项目版本号的统一管理又成为了一个新的需求点,好在从 Maven 3.5.0-beta-1 开始提供了版本统一管理的功能。
父子工程
概念:
父子工程是一种通过继承关系来共享配置和依赖的项目结构。父工程定义了可以被多个子工程共享的配置、插件和依赖,子工程通过 parent
元素来继承这些配置。
作用:
- 继承配置:子工程可以继承父工程的依赖和插件配置,减少重复定义。
- 统一管理:通过父工程可以统一管理版本号、依赖管理、插件配置等。
示例:
首先创建父子工程,例如maxwell-admin
项目结构如下,包含 5 个子模块。
maxwell-admin
├─ pom.xml
├─ maxwell-admin-system
│ └─ pom.xml
├─ maxwell-admin-openapi
│ └─ pom.xml
├─ maxwell-admin-core
│ └─ pom.xml
├─ maxwell-admin-common
│ └─ pom.xml
└─ maxwell-admin-business
└─ pom.xml
父项目maxwell-admin
的pom.xml
中<modules>
标签中定义了它所拥有的子模块,并且作为父项目它的打包方式必须为pom
。
<?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>cool.ldw</groupId>
<artifactId>maxwell-admin</artifactId>
<version>0.0.1-SNAPSHOT<</version>
<packaging>pom</packaging>
<modules>
<module>maxwell-admin-common</module>
<module>maxwell-admin-core</module>
<module>maxwell-admin-system</module>
<module>maxwell-admin-openapi</module>
<module>maxwell-admin-business</module>
</modules>
</project>
子模块通过<parent>
标签来表示它的父项目是哪个,如:maxwell-admin-common
中的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>
<parent>
<groupId>cool.ldw</groupId>
<artifactId>maxwell-admin</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>maxwell-admin-common</artifactId>
</project>
同样的maxwell-admin-core
中的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>
<parent>
<groupId>cool.ldw</groupId>
<artifactId>maxwell-admin</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>maxwell-admin-core</artifactId>
</project>
其余的maxwell-admin-system
、maxwell-admin-openapi
、maxwell-admin-business
中也同样如此,不再赘述。
作为子模块,它们继承了父项目中的groupId
和version
,所以在它们的pom.xml
文件中只需要定义各自的artifactId
即可。
到这里不得不说一个热知识,在 Maven 工程中,由groupId
、artifactId
、version
这三个部分共同组成某个依赖的唯一标识符。
groupId
:可简单理解成公司名称或你个人的代号,如域名。artifactId
:项目的名称。version
:项目的版本,后缀为-SNAPSHOT
表示不是稳定版本,-RELEASE
代表是稳定版本。
Maven 会拿着这三个组成的唯一标识符去仓库里面寻找你定义的依赖,查询顺序是本地仓库 → 私服仓库 → 中央仓库
,因此子模块中的 <parent>
标签中必须要包含这三个部分;除此之外还有个<relativePath>
标签用来指定父项目pom.xml
文件的位置,我这里没有定义默认会从../pom.xml
寻找。
项目骨架创建完毕后另一个很重要的事情就是做好依赖的管理。
假设想要在子模块中maxwell-admin-system
和maxwell-admin-core
中引入hutool
工具包,常用的做法是这样的:
-
首先在父项目的
pom.xml
中添加<dependencyManagement>
:<?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>cool.ldw</groupId> <artifactId>maxwell-admin</artifactId> <version>0.0.1-SNAPSHOT<</version> <packaging>pom</packaging> <modules> <module>maxwell-admin-common</module> <module>maxwell-admin-core</module> <module>maxwell-admin-system</module> <module>maxwell-admin-openapi</module> <module>maxwell-admin-business</module> </modules> <dependencyManagement> <dependencies> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.29</version> </dependency> </dependencies> </dependencyManagement> </project>
-
子模块中
maxwell-admin-system
引入hutool
依赖,注意不用写版本号。<?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> <parent> <groupId>cool.ldw</groupId> <artifactId>maxwell-admin</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <artifactId>maxwell-admin-system</artifactId> <dependencies> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.29</version> </dependency> </dependencies> </project>
-
子模块中
maxwell-admin-core
引入hutool
依赖,注意不用写版本号。<?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> <parent> <groupId>cool.ldw</groupId> <artifactId>maxwell-admin</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <artifactId>maxwell-admin-core</artifactId> <dependencies> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.29</version> </dependency> </dependencies> </project>
父项目<dependencyManagement>
标签中定义的依赖仅仅是作为一个版本的管理,并不会真正的将配置的依赖导入到项目中,当子模块中定义了这个相同的依赖之后,会沿着父子层级向上寻找拥有<dependencyManagement>
元素的项目,然后使用它指定的版本号。
对于依赖的版本号管理还可以更进一步,通过在<properties>
自定义标签的方式设置依赖的版本号,以后项目中的依赖越来越多时只需要关注<properties>
标签中设置的依赖版本号数值即可,这也是目前很常用的方式。
<?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>cool.ldw</groupId>
<artifactId>maxwell-admin</artifactId>
<version>0.0.1-SNAPSHOT<</version>
<packaging>pom</packaging>
<modules>
<module>maxwell-admin-common</module>
<module>maxwell-admin-core</module>
<module>maxwell-admin-system</module>
<module>maxwell-admin-openapi</module>
<module>maxwell-admin-business</module>
</modules>
<properties>
<hutool.version>5.8.29</hutool.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
聚合工程
概念:
聚合工程是一种通过聚合多个模块来实现统一构建和管理的项目结构。父工程通过 <modules>
元素包含多个子模块,每个子模块都是独立的 Maven 项目。
作用:
- 统一构建:可以在父工程中一次性构建所有子模块,简化了构建过程。
- 模块化管理:方便管理多个相关联的项目,具有清晰的项目层次结构。
示例:
项目结构还是和上面的一样,包含这 5 个模块
maxwell-admin
├─ pom.xml
├─ maxwell-admin-system
│ └─ pom.xml
├─ maxwell-admin-openapi
│ └─ pom.xml
├─ maxwell-admin-core
│ └─ pom.xml
├─ maxwell-admin-common
│ └─ pom.xml
└─ maxwell-admin-business
└─ pom.xml
若子模块maxwell-admin-core
需要引用子模块maxwell-admin-common
可以这么配置:
在父项目的pom.xml
中将所有的子模块配置到<dependencyManagement>
标签中
<?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>cool.ldw</groupId>
<artifactId>maxwell-admin</artifactId>
<version>0.0.1-SNAPSHOT<</version>
<packaging>pom</packaging>
<modules>
<module>maxwell-admin-common</module>
<module>maxwell-admin-core</module>
<module>maxwell-admin-system</module>
<module>maxwell-admin-openapi</module>
<module>maxwell-admin-business</module>
</modules>
<properties>
<hutool.version>5.8.29</hutool.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>cool.ldw</groupId>
<artifactId>maxwell-admin-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cool.ldw</groupId>
<artifactId>maxwell-admin-core</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cool.ldw</groupId>
<artifactId>maxwell-admin-system</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cool.ldw</groupId>
<artifactId>maxwell-admin-openapi</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cool.ldw</groupId>
<artifactId>maxwell-admin-business</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
然后在子模块maxwell-admin-core
的pom.xml
中引入即可,就像上面引入hutool
依赖一样,同样的不需要写版本号
<?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>
<parent>
<groupId>cool.ldw</groupId>
<artifactId>maxwell-admin</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>maxwell-admin-core</artifactId>
<dependencies>
<dependency>
<groupId>cool.ldw</groupId>
<artifactId>maxwell-admin-common</artifactId>
</dependency>
</dependencies>
</project>
版本统一管理
在使用Maven多模块结构工程时,版本管理是一件很繁琐且容易出错的事情。每次升级版本号都要手动调整或者通过
mvn versions:set -DnewVerion=xx
命令去更改每一个子模块的版本号,非常的不方便,而且会改动所有的模块。
好在从 Maven 3.5.0-beta-1 开始提供了统一版本管理的功能,可以使用 ${revision}
、${sha1}
、 ${changelist}
这样的变量作为版本占位符。
具体来说使用${revision}
作为版本占位符搭配flatten-maven-plugin
插件来实现全局版本统一管理的功能。
该插件的工作原理是:
-
读取项目 POM 文件:
插件从项目的
pom.xml
文件中读取当前的 Maven 项目配置,包括所有的依赖、插件、构建配置等信息。 -
解析继承和聚合关系:
插件会解析 POM 文件中的继承关系和聚合关系,将父 POM 和模块 POM 文件中的配置合并到当前 POM 中。这意味着它会把父 POM 中定义的属性、依赖、插件等内容展开到当前 POM 文件中,消除层级结构。
-
生成扁平化的 POM 文件:
插件将合并后的配置生成一个新的
pom.xml
文件,这个文件包括所有的继承信息和依赖信息,但不再包含<parent>
或<modules>
元素。 -
输出或保存扁平化的 POM 文件:
最终生成的扁平化
pom.xml
文件可以被保存到指定的位置或输出到控制台。这个文件可以用于生成报告、做版本控制、或进行其他需要具体 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>cool.ldw</groupId>
<artifactId>maxwell-admin</artifactId>
<!-- 注意这里使用到了 revision 占位符 -->
<version>${revision}<</version>
<packaging>pom</packaging>
<modules>
<module>maxwell-admin-common</module>
<module>maxwell-admin-core</module>
<module>maxwell-admin-system</module>
<module>maxwell-admin-openapi</module>
<module>maxwell-admin-business</module>
</modules>
<properties>
<!-- 全局版本控制,如果要修改版本号,修改此处即可-->
<revision>0.0.1-SNAPSHOT</revision>
<hutool.version>5.8.29</hutool.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>cool.ldw</groupId>
<artifactId>maxwell-admin-common</artifactId>
<!-- 注意这里也要使用 revision 占位符,由之前的具体版本号 0.0.1-SNAPSHOT 变为 ${revision},下同 -->
<version>${revision}</version>
</dependency>
<dependency>
<groupId>cool.ldw</groupId>
<artifactId>maxwell-admin-core</artifactId>
<!-- 注意这里也要使用 revision 占位符 -->
<version>${revision}</version>
</dependency>
<dependency>
<groupId>cool.ldw</groupId>
<artifactId>maxwell-admin-system</artifactId>
<!-- 注意这里也要使用 revision 占位符 -->
<version>${revision}</version>
</dependency>
<dependency>
<groupId>cool.ldw</groupId>
<artifactId>maxwell-admin-openapi</artifactId>
<!-- 注意这里也要使用 revision 占位符 -->
<version>${revision}</version>
</dependency>
<dependency>
<groupId>cool.ldw</groupId>
<artifactId>maxwell-admin-business</artifactId>
<!-- 注意这里也要使用 revision 占位符 -->
<version>${revision}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<!-- 统一版本号插件 -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>flatten-maven-plugin</artifactId>
<version>1.6.0</version>
<configuration>
<updatePomFile>true</updatePomFile>
<flattenMode>resolveCiFriendliesOnly</flattenMode>
</configuration>
<executions>
<!-- 当Maven构建进入“process-resources”阶段时,会执行名为“flatten”的操作,运行“flatten”目标以生成扁平化的POM文件。-->
<execution>
<id>flatten</id>
<phase>process-resources</phase>
<goals>
<goal>flatten</goal>
</goals>
</execution>
<!-- 当Maven构建进入“clean”阶段时,会执行名为“flatten-clean”的操作,运行“clean”目标以清理生成的扁平化POM文件或其他相关的临时文件。-->
<execution>
<id>flatten-clean</id>
<phase>clean</phase>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
子模块maxwell-admin-common
的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>
<parent>
<groupId>cool.ldw</groupId>
<artifactId>maxwell-admin</artifactId>
<!-- 子模块中定义父项目的地方也要使用 revision 占位符,即便在这里写了和父项目版本号一样的数值如:0.0.1-SNAPSHOT 打包编译清理等步骤的都会报错,提示找不到父项目 -->
<version>${revision}</version>
</parent>
<artifactId>maxwell-admin-common</artifactId>
</project>
其余的 4 个子模块都如同上面这样配置,不再赘述。
到这里 Maven 多模块项目版本统一管理基本就结束了,不过为了了解的更加深入一点,这里再介绍一个知识点:Maven 构建流程。
Maven 有一套标准化的构建流程,可以自动化实现编译,打包,发布,等等。
平时我们编译,打包,发布 Maven 项目都是执行其生命周期来实现的,在 IDEA 中的右侧的 Maven 菜单中显示了可执行的所有生命周期。
每个生命周期又是由一系列阶段(Phase)组成的,以内置的生命周期default
为例,它包含以下Phase:
阶段 | 说明 |
---|---|
validate | 验证项目的 pom.xml 文件和环境配置的正确性。 |
initialize | 初始化构建状态。通常不直接使用。 |
generate-sources | 生成项目的源代码,如代码生成器的代码。 |
process-sources | 处理源代码,准备编译。 |
generate-resources | 生成资源文件,如资源处理工具生成的文件。 |
process-resources | 处理资源文件,将它们复制到目标目录。 |
compile | 编译源代码。 |
process-classes | 处理资源文件。 |
generate-test-sources | 生成测试代码的源文件。 |
process-test-sources | 处理测试源代码,为测试编译做准备。 |
generate-test-resources | 生成测试资源文件。 |
generate-resources | 生成资源文件,如资源处理工具生成的文件。 |
test-compile | 编译测试源代码。 |
process-test-classes | 处理已编译的测试类文件。 |
test | 运行单元测试。 |
prepare-package | 在打包之前进行准备工作。 |
package | 打包项目。 |
pre-integration-test | 集成测试前的准备工作。 |
integration-test | 运行集成测试。 |
post-integration-test | 集成测试后的清理工作。 |
verify | 验证包的有效性。 |
install | 将包安装到本地 Maven 仓库。 |
deploy | 将包发布到远程 Maven 仓库。 |
如果运行mvn package
,Maven就会执行default
生命周期,它会从开始一直运行到package
这个phase为止:
validate → initialize → ... → prepare-package → package
如果我们运行mvn compile
,Maven也会执行default
生命周期,但这次它只会运行到compile
,即以下几个phase:
validate → initialize → ... → process-resources → compile
Maven另一个常用的生命周期是clean
,它会执行以下 3 Phase:
阶段 | 说明 |
---|---|
pre-clean | 清理之前的准备工作。 |
clean (注意这个 clean 不是生命周期而是 Phase) | 删除 target 目录中的所有文件。 |
post-clean | 清理之后的后续工作。 |
所以,我们使用mvn
这个命令时,后面的参数是 Phase,Maven 自动根据生命周期运行到指定的 Phase。
更复杂的例子是指定多个 Phase,例如,运行mvn clean package
,Maven 先执行clean
生命周期并运行到clean
这个 Phase,然后执行default
生命周期并运行到package
这个 Phase,实际执行的 Phase 如下:
pre-clean → clean(注意这个 clean 是 Phase) → validat(开始执行 default 生命周期的第一个 Phase)) → initialize → ... → prepare-package → package
在实际开发过程中,经常使用的命令有:
-
mvn clean
:清理所有生成的 class 和 jar; -
mvn clean compile
:先清理,再执行到compile
; -
mvn clean test
:先清理,再执行到test
,因为执行test
前必须执行compile
,所以这里不必指定compile
; -
mvn clean package
:先清理,再执行到package
。
大多数 Phase 在执行过程中,因为我们通常没有在pom.xml
中配置相关的设置,所以这些 Phase 什么事情都不做。
因此经常用到的Phase 其实只有几个:
- clean:清理
- compile:编译
- test:运行测试
- package:打包
IDEA
这里记录一下创建一个新项目时一般要做的配置和一些好用的插件。
配置
-
配置编码方式为
UTF-8
File -> Settings
,在顶部的搜索框中搜索encode
,要配置的一般有下图中这四个地方,把每个选项卡中选择编码方式的地方都选成UTF-8
就行了。 -
配置项目的编译版本
-
File -> Settings -> Build,Execution,Deployment -> Compiler -> Java Compiler
,在Per-modulebytecodeversion:
部分选择编译版本。File -> Project Structure
,在Project
和Modules
中选择编译版本,要和上面选择的一致。 -
配置自动导包和删除无用的包
File -> Settings -> Editor -> General -> Auto Import
,勾选下面这两项,第一项是自动导入包,第二项是自动移除导入但未使用到的包。 -
配置创建类时自动添加
@author
信息File -> Settings -> Editor -> File And Code Templates
,在Includes
标签下中添加你想要在新的类文件被创建时统一添加的模板,例如:
插件
-
Translation:翻译插件,在选中的内容上右键选择
Translate Selection
或Ctrl + Shift + Y
翻译选中的内容;或者选择Translate Documentation
翻译整个注释内容。 -
GitToolBox:安装后可以方便的显示当前行代码的提交人和提交描述。
-
RESTFul-Tool:使用快捷键
Ctrl + Alt + /
可以快速搜索定位到某个请求url
所在的Controller
位置。 -
Key Promoter X:快捷键提示插件,当你用鼠标做了什么操作时,如果有快捷键可以代替的话就会在右小角弹出个消息提示你。
-
JRebel and XRebel:热更新,当修改某个类文件后按
Ctrl + F9
重新编译就会加载你刚写的代码无需重启项目,即便加的是一个新的Controller
接口也无需重启项目。激活方式参考这个项目:ilanyu/ReverseProxy: ReverseProxy in golang (github.com) -
Mybatis X:方便在
xxxMapper.xml
文件和xxxMapper.class
中来回跳。
参考资源
- ChatGPT | OpenAI
- 17-构建父子工程
- 18-聚合工程
- Maven构建 —— groupId、artifactId、version概念_groupid artifactid version-CSDN博客
- maven配置多仓库依赖的搜索顺序_maven pom和setting中仓库的查找顺序-CSDN博客
- maven pom relativePath属性的作用_relativepath的作用-CSDN博客
- dependencyManagement使用简介-CSDN博客
- 【工具篇】Maven使用${revision}实现多模块版本统一管理_maven revision-CSDN博客
- Maven – Maven CI 友好版本
- 构建流程 - 廖雪峰的官方网站 (liaoxuefeng.com)
评论区