「这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战」
mvn help:effective-pom
Maven 使用 effective pom(Super pom 加上工程自己的配置)来执行相关的目标,它帮助开发者在 pom.xml 中做尽可能少的配置,当然这些配置可以被方便的重写。
查看 Super POM 默认配置的一个简单方法是执行以下命令:mvn help:effective-pom
构建生命周期
一个典型的 Maven 构建生命周期是由以下几个阶段的序列组成的
| 阶段 | 处理 | 描述 |
|---|---|---|
| prepare-resources | 资源拷贝 | 本阶段可以自定义需要拷贝的资源 |
| compile | 编译 | 本阶段完成源代码编译 |
| package | 打包 | 本阶段根据 pom.xml 中描述的打包配置创建 JAR / WAR 包 |
| install | 安装 | 本阶段在本地 / 远程仓库中安装工程包 |
\
mvn dependency:copy-dependencies
maven把依赖包拷贝到lib下。标准web工程在eclipse中利用m2eclipse插件添加依赖管理后,在部署过程中没有将依赖的jar包自动拷贝到/WEB-INF/lib中。参考了一些朋友的做法手动执行mvn dependency:copy-dependencies -DoutputDirectory=src/main/webapp/WEB-INF/lib -DincludeScope=runtime 命令将jar包拷贝到/WEB-INF/lib目录下。 \
Default (or Build) 生命周期
这是 Maven 的主要生命周期,被用于构建应用。包括下面的 23 个阶段。
| 生命周期阶段 | 描述 |
|---|---|
| validate | 检查工程配置是否正确,完成构建过程的所有必要信息是否能够获取到。 |
| initialize | 初始化构建状态,例如设置属性。 |
| generate-sources | 生成编译阶段需要包含的任何源码文件。 |
| process-sources | 处理源代码,例如,过滤任何值(filter any value)。 |
| generate-resources | 生成工程包中需要包含的资源文件。 |
| process-resources | 拷贝和处理资源文件到目的目录中,为打包阶段做准备。 |
| compile | 编译工程源码。 |
| process-classes | 处理编译生成的文件,例如 Java Class 字节码的加强和优化。 |
| generate-test-sources | 生成编译阶段需要包含的任何测试源代码。 |
| process-test-sources | 处理测试源代码,例如,过滤任何值(filter any values)。 |
| test-compile | 编译测试源代码到测试目的目录。 |
| process-test-classes | 处理测试代码文件编译后生成的文件。 |
| test | 使用适当的单元测试框架(例如JUnit)运行测试。 |
| prepare-package | 在真正打包之前,为准备打包执行任何必要的操作。 |
| package | 获取编译后的代码,并按照可发布的格式进行打包,例如 JAR、WAR 或者 EAR 文件。 |
| pre-integration-test | 在集成测试执行之前,执行所需的操作。例如,设置所需的环境变量。 |
| integration-test | 处理和部署必须的工程包到集成测试能够运行的环境中。 |
| post-integration-test | 在集成测试被执行后执行必要的操作。例如,清理环境。 |
| verify | 运行检查操作来验证工程包是有效的,并满足质量要求。 |
| install | 安装工程包到本地仓库中,该仓库可以作为本地其他工程的依赖。 |
| deploy | 拷贝最终的工程包到远程仓库中,以共享给其他开发人员和工程。 |
有一些与 Maven 生命周期相关的重要概念需要说明:
当一个阶段通过 Maven 命令调用时,例如 mvn compile,只有该阶段之前以及包括该阶段在内的所有阶段会被执行。
不同的 maven 目标将根据打包的类型(JAR / WAR / EAR),被绑定到不同的 Maven 生命周期阶段。
在下面的例子中,我们将 maven-antrun-plugin:run 目标添加到 Build 生命周期的一部分阶段中。这样我们可以显示生命周期的文本信息。
mvn -P 多场景profiles
\
Maven 的 Profile 能够通过几种不同的方式激活。
- 显式使用命令控制台输入
- 通过 maven 设置
- 基于环境变量(用户 / 系统变量)
- 操作系统配置(例如,Windows family)
- 现存 / 缺失 文件
\
常用插件
\
| 插件 | 描述 |
|---|---|
| clean | 构建之后清理目标文件。删除目标目录。 |
| compiler | 编译 Java 源文件。 |
| surefile | 运行 JUnit 单元测试。创建测试报告。 |
| jar | 从当前工程中构建 JAR 文件。 |
| war | 从当前工程中构建 WAR 文件。 |
| javadoc | 为工程生成 Javadoc。 |
| antrun | 从构建过程的任意一个阶段中运行一个 ant 任务的集合。 |
\
解决依赖
\
<dependency>
<groupId>ldapjdk</groupId>
<artifactId>ldapjdk</artifactId>
<scope>system</scope>
<version>1.0</version>
<systemPath>${basedir}\src\lib\ldapjdk.jar</systemPath> </dependency>
\
构建自动化
构建自动化定义为一种场景:一旦该工程成功构建完成,其相关的依赖工程即开始构建,目的是为了保证其依赖项目的稳定。
依赖范围
| 范围 | 描述 |
|---|---|
| 编译阶段 | 该范围表明相关依赖是只在工程的类路径下有效。默认取值。 |
| 供应阶段 | 该范围表明相关依赖是由运行时的 JDK 或者 网络服务器提供的。 |
| 运行阶段 | 该范围表明相关依赖在编译阶段不是必须的,但是在执行阶段是必须的。 |
| 测试阶段 | 该范围表明相关依赖只在测试编译阶段和执行阶段。 |
| 系统阶段 | 该范围表明你需要提供一个系统路径。 |
| 导入阶段 | 该范围只在依赖是一个 pom 里定义的依赖时使用。同时,当前工程的POM 文件的 部分定义的依赖关系可以取代某特定的 POM。 |
compile:编译依赖范围,默认值。此选项对编译、测试、运行三种 classpath 都有效。
provided:已提供依赖范围。编译和测试有效,运行无效。如 servlet-api ,在项目运行时,tomcat 等容器已经提供,无需 Maven 重复引入
runtime:运行时依赖范围。表示编译时不是必须的,但测试和运行是必须的。如 jdbc 驱动实现,编译时只需接口,测试或运行时才需要具体的 jdbc 驱动实现
test:测试依赖范围。只对测试有效,表明只在测试的时候需要,在编译和运行时将无法使用该类依赖,如 junit
system:系统依赖范围。和 provided 依赖范围一致,需要通过 显示指定,且可以引用环境变量
依赖图表的细节:
- App-UI-WAR 依赖于 App-Core-lib 和 App-Data-lib.
- Root 是 App-Core-lib 和 App-Data-lib 的父类。
- Root 在其依赖模块里定义了 Lib1,lib2, Lib3 3个依赖关系。
内置变量
${basedir} 项目根目录
${project.build.directory} 构建目录,缺省为target
${project.build.outputDirectory} 构建过程输出目录,缺省为target/classes
{project.artifactId}-${project.version}
${project.packaging} 打包类型,缺省为jar
${project.xxx} 当前pom文件的任意节点的内容
\
依赖继承与传递
parent.pom使用dependencies和dependencyManagement管理子项目的公共的依赖
dependencies即使在子项目中不写该依赖项,那么子项目仍然会从父项目中继承该依赖项(全部继承)
dependencyManagement里只是声明依赖,并不实现引入,因此子项目需要显式的声明需要用的依赖。如果不在子项目中声明依赖,是不会从父项目中继承下来的;只有在子项目中写了该依赖项,并且没有指定具体版本,才会从父项目中继承该项,并且version和scope都读取自父pom;另外如果子项目中指定了版本号,那么会使用子项目中指定的jar版本。
\
自动化部署
一般情况下,在一个工程开发进程里,一次部署的过程包含需如下步骤:
- 合入每个子工程下的代码到 SVN 或者源代码库,并标记它。
- 从 SVN 下载完整的源代码。
- 构建应用程序。
- 保存构建结果为 WAR 或者 EAR 类型文件并存放到一个共同的指定的网络位置上。
- 从网络上获得该文件并且部署该文件到产品线上。
- 更新文档日期和应用程序的版本号。
问题陈述
通常,将会有很多不同的人参与到上述部署过程中。一个团队可以负责代码的合入工作,另外一个可以负责构建,以此类推。上述的任何一个步骤都可能因为人为的原因没有被执行。例如,较旧的版本没有在网络机器上更新,负责部署的团队再一次部署了旧的版本。
解决方案
通过结合如下的方案来实现自动化部署:
- Maven 构建和发布项目,
- SubVersion, 源代码库用以管理源代码,
- 远程仓库管理工具 (Jfrog/Nexus) 用以管理工程的二进制文件。
更新工程的 POM.xml
我们将会使用 Maven 发布的插件来创建一个自动化发布过程:
例如: bus-core-api 工程的 POM.xml 如下 \
<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>bus-core-api</groupId>
<artifactId>bus-core-api</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<scm>
<url>http://www.svn.com</url>
<connection>scm:svn:http://localhost:8080/svn/jrepo/trunk/
Framework</connection>
<developerConnection>scm:svn:${username}/${password}@localhost:8080:
common_core_api:1101:code</developerConnection>
</scm>
<distributionManagement>
<repository>
<id>Core-API-Java-Release</id>
<name>Release repository</name>
<url>http://localhost:8081/nexus/content/repositories/
Core-Api-Release</url>
</repository>
</distributionManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.0-beta-9</version>
<configuration>
<useReleaseProfile>false</useReleaseProfile>
<goals>deploy</goals>
<scmCommentPrefix>[bus-core-api-release-checkin]-<
/scmCommentPrefix>
</configuration>
</plugin>
</plugins>
</build>
</project>
在 pom.xml 里,我们常常会使用到的重要元素如下表:
| 元素 | 描述 |
|---|---|
| SCM | 配置 SVN 的路径,Maven 将从该路径下将代码取下来。 |
| 仓库 | 成功构建出来的 WAR/EAR/JAR 或者其他的构建结果存放的路径。 |
| 插件 | maven-release-plugin 用以自动化部署的过程。 |
Maven Release 插件
Maven 通过 maven-release-plugin 来执行如下很有用的任务:
\
mvn release:clean
清理工作空间,保证最新的发布进程成功进行。
\
mvn release:rollback
回滚修改的工作空间代码和配置保证发布过程成功进行。
\
mvn release:prepare
执行如下多次操作:
- 检查本地是否存在还未提交的修改
- 确保没有快照的依赖
- 改变应用程序的版本信息用以发布
- 更新 POM 文件到 SVN
- 运行测试用例
- 提交修改后的 POM 文件
- 为代码在 SVN 上做标记
- 增加版本号和附加快照以备将来发布
- 提交修改后的 POM 文件到 SVN.
\
mvn release:perform
将代码切换到之前做标记的地方,运行 Maven 部署目标来部署 WAR 文件或者构建相应的结构到仓库里。
打开命令终端,进入到 C:\ > MVN >bus-core-api 目录下,然后执行如下的 mvn 命令。
\
C:\MVN\bus-core-api>mvn release:prepare
Maven 开始构建整个工程。一旦构建成功即可运行如下 mvn 命令。
\
C:\MVN\bus-core-api>mvn release:perform
一旦构建成功,你可以验证在你仓库下上传的 JAR 文件是否生效。