文章目录
- 一、Maven
- Maven生命周期介绍
- maven生命周期命令解析
- 二、如何编写maven打包脚本
- maven 配置详解
- setting.xml
- 主要配置元素
- setting.xml 详细配置
- 使用maven 打包springboot项目
- maven 引入
- 使用package命令来打包
- idea打包
- 三、使用shell脚本自动发布
- 四、使用maven不同环境配置加载不同的依赖
- Maven 不同环境引用依赖
- Maven 配置
- 切换不同环境
- 最佳实践
- Maven不同环境打包不同配置
- maven 配置
- 编译后的目录结构
- 五、如何加快maven打包速度
- 前言
- 1. maven-mvnd是什么?
- 2. 使用步骤
- 3. 打包速度对比
专栏快速目录链接
【JAVA WEB实用与优化技巧】Maven自动化构建与Maven 打包技巧
【JAVA WEB实用与优化技巧】如何自己封装一个自定义UI的Swagger组件,包含Swagger如何处理JWT无状态鉴权自动TOKEN获取
一、Maven
Maven 是一个强大的Java项目管理工具,由Jason van Zyl在2002年创建,最初是为了简化Apache Jakarta Turbine项目构建过程而设计的。它后来成为Apache软件基金会的一个项目,并迅速成为Java开发的标准工具之一。Maven的核心理念是通过项目对象模型(Project Object Model,简称POM)来管理和构建软件项目。
主要特点和功能:
- 项目对象模型(POM):
POM是一个XML文件,包含了项目的基本信息,如项目名称、版本、依赖、构建目标、构建过程等。
通过POM,Maven可以自动管理项目的构建、依赖和文档生成。 - 依赖管理:
Maven自动解决项目间的依赖关系,从远程仓库下载所需的库文件,并管理这些库的版本。
它遵循“约定优于配置”的原则,大多数情况下,不需要显式指定库的路径。 - 构建生命周期:
Maven有预定义的构建生命周期,包括clean、default和site三个主要生命周期,每个生命周期包含一系列的构建阶段(如compile、test、package、install和deploy)。 - 插件系统:
Maven通过插件执行构建任务,如编译、测试、打包、部署等。
插件可以扩展Maven的功能,提供自定义的构建行为。 - 项目聚合与继承:
多个相关项目可以通过Maven的聚合功能组合成一个大的项目结构。
通过继承,子项目可以从父项目继承POM配置,减少重复的配置。 - 文档生成:
Maven可以自动生成项目文档,如Javadoc、源代码文档等。 - 版本控制系统集成:
Maven可以与版本控制系统(如Git、SVN等)集成,方便版本控制和协作开发。 - 使用Maven的好处:
- 标准化:Maven提供了一种标准化的方式来构建Java项目,使得不同项目的构建过程具有可预测性。
- 自动化:大大减少了手动配置和构建的工作量。
- 可重用性:通过POM的继承和聚合,可以轻松复用构建配置和依赖管理。
- 协作:团队成员可以轻松地在相同的环境中构建项目,减少因环境差异导致的问题。
Maven的广泛使用使得Java开发者能够专注于编写代码,而不是构建过程,从而提高了开发效率和项目的可维护性。虽然Maven最初是为Java设计的,但现在也有用于其他语言的类似工具,如Gradle,它们也借鉴了Maven的一些概念和模式。
Maven生命周期介绍
Maven的生命周期是其核心功能之一,它定义了一系列有序的构建阶段,用于自动化构建过程,确保不同项目的构建步骤保持一致性和可预测性。Maven生命周期主要包含三个主要的部分:
- clean 生命周期:
pre-clean
:在开始清理之前运行的任何任务。clean
:删除之前构建的输出,比如target目录下的编译结果和测试报告。post-clean
:清理之后可能需要执行的任何操作。
default
生命周期(也称为default phase或核心生命周期):validate
:验证项目配置,确保构建可以成功。compile
:编译项目的源代码。test
:使用单元测试框架运行项目的所有测试,但不包括集成测试。package
:将编译后的代码打包成最终的格式,如JAR、WAR或EAR。verify
:验证打包的工件是否有效且质量达标。install
:将工件安装到本地仓库,供其他项目使用。deploy
:将最终的工件复制到远程仓库,供其他开发者或构建系统使用。
- site生命周期:
pre-site
:准备生成项目站点文档。site
:生成项目站点文档。post-site
:生成站点后执行的任务,例如部署站点。site-deploy
:将生成的站点部署到服务器上。
每个生命周期的阶段都是按顺序执行的,后面的阶段依赖于前面的阶段成功完成。开发者可以通过指定生命周期中的某个阶段来跳过前面的阶段,例如,运行mvn package
会从validate开始,直到package阶段结束,不会执行deploy及之后的阶段。
此外,Maven的生命周期并不是自我实现的,而是通过插件来完成具体的任务。每个阶段实际上是调用了相应的插件目标(plugin goal),这些目标执行实际的构建操作。通过在POM(Project Object Model)文件中配置插件和其目标,开发者可以定制生命周期的行为。
maven生命周期命令解析
Maven 命令通常以 mvn 开头,它们用于执行不同的构建任务。以下是一些最常用的 Maven 命令及其作用:
- 创建项目
mvn archetype:create
: 创建一个新的 Maven 项目,此命令已废弃,现在推荐使用 mvn archetype:generate。 - 初始化项目
mvn archetype:generate
: 生成一个新的 Maven 项目骨架,允许用户交互式地选择项目类型和属性。 - 编译
mvn compile
: 编译项目的源代码。 - 测试
mvn test-compile
: 编译项目的测试源代码。
mvn test
: 运行项目的测试,并生成测试报告。 - 打包
mvn package
: 编译、测试并打包项目(如 JAR、WAR 或 EAR 文件)。 - 验证
mvn verify
: 验证工件是否符合质量标准,通常会运行集成测试。 - 安装
mvn install
: 将构建好的工件安装到本地 Maven 仓库,供本地项目依赖。 - 部署
mvn deploy
: 将工件部署到远程仓库,供整个团队或公众使用。 - 清理
mvn clean
: 删除 target 目录及其所有内容,用于清理构建输出。 - 生成站点文档
mvn site
: 生成项目相关的文档和站点。
mvn site
:deploy: 将生成的站点部署到服务器。 - 更新依赖
mvn dependency:update
: 更新项目中所有依赖的版本。 - 帮助
mvn help:effective-pom
: 显示项目的实际 POM,包括继承和聚合的效果。
mvn help:all-plugin-goals
: 列出所有可用的插件目标。
mvn help:system
: 显示系统环境变量。 - 设置属性
mvn -Dproperty=value command
: 设置 Maven 环境变量,如-DskipTests=true
可以跳过测试。
执行特定生命周期阶段
mvn lifecycle-phase
: 直接执行生命周期中的特定阶段,例如mvn process-resources
。 - 插件目标
mvn plugin:goal
: 直接执行某个插件的目标,如mvn compiler:compile
。
请注意,以上命令在实际使用时可能会根据项目的具体配置有所不同。要查看更详细的命令用法和选项,可以运行 mvn help:help 或 mvn --help。
二、如何编写maven打包脚本
maven 配置详解
setting.xml
Maven的settings.xml
文件是用于配置Maven行为的重要文件,它提供了对Maven默认行为的自定义。这个文件主要有两个位置:
- 全局配置:位于Maven安装目录的conf子目录下,影响所有使用该Maven安装的用户。
- 用户配置:位于用户主目录下的.m2目录中(在Windows上直接是
%USERPROFILE%\.m2\settings.xml
,Linux或Mac上是~/.m2/settings.xml
)。如果存在,它会覆盖全局配置中的相同设置。
主要配置元素
servers
: 包含了访问私有仓库所需的认证信息。
mirrors
: 镜像设置,用于替代官方仓库,加快下载速度。
profiles
: 配置文件,可以根据不同的环境(开发、测试、生产)激活不同的配置。
repositories
: 自定义仓库地址,除了Maven中央仓库外,可以添加额外的仓库。
pluginGroups
: 指定不需要前缀即可使用的插件组,方便插件的引用。
localRepository
: 指定本地仓库的位置,默认在~/.m2/repository。
interactiveMode
: 控制Maven是否与用户进行交互。
offline
: 当设置为true时,Maven只使用本地仓库,不尝试连接远程仓库。
proxy
: 配置代理服务器信息,对于需要通过代理访问网络的情况非常有用。
profiles
: 根据不同的环境条件激活不同的配置集。
setting.xml 详细配置
<?xml version="1.0" encoding="UTF-8"?>
<settings
xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
<localRepository>/mnt/hgfs/repository</localRepository>
<pluginGroups></pluginGroups>
<proxies></proxies>
<servers></servers>
<!--
<mirrorOf>central</mirrorOf> 这里最好不要写成*号,否则你项目中的pom中配置repository不生效
-->
<mirrors>
<mirror>
<id>aliyunmaven</id>
<mirrorOf>*</mirrorOf>
<name>阿里云公共仓库</name>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>
<mirror>
<id>aliyunmaven</id>
<mirrorOf>*</mirrorOf>
<name>阿里云谷歌仓库</name>
<url>https://maven.aliyun.com/repository/google</url>
</mirror>
<mirror>
<id>aliyunmaven</id>
<mirrorOf>*</mirrorOf>
<name>阿里云阿帕奇仓库</name>
<url>https://maven.aliyun.com/repository/apache-snapshots</url>
</mirror>
<mirror>
<id>aliyunmaven</id>
<mirrorOf>*</mirrorOf>
<name>阿里云spring仓库</name>
<url>https://maven.aliyun.com/repository/spring</url>
</mirror>
<mirror>
<id>aliyunmaven</id>
<mirrorOf>*</mirrorOf>
<name>阿里云spring插件仓库</name>
<url>https://maven.aliyun.com/repository/spring-plugin</url>
</mirror>
</mirrors>
<profiles>
<profile>
<repositories>
<repository>
<id>nexus</id>
<name>local private nexus</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>nexus</id>
<name>local private nexus</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
</settings>
使用maven 打包springboot项目
maven 引入
在启动类所在module的pom中加入maven配置:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
使用package命令来打包
mvn clean package -s xxx.xml -Dmaven.test.skip=true
- -s 后面跟maven的setting配置
-Dmaven.test.skip=true
是跳过单元测试打包
idea打包
三、使用shell脚本自动发布
package.sh
负责拉取服务代码&打包代码&拷贝jar包到发布目录
#!/bin/bash
MAVEN_HOME=/docker/apache-maven-3.8.8/bin/
# 进入到项目目录中并拉取最新代码,前提是先使用 git config --global credential.helper store 保存凭证
cd /docker/service/projectName && git pull origin master
pwd
$MAVEN_HOME/mvn clean package -s /docker/service/setting.xml -Dmaven.test.skip=true
# 将打包文件拷贝出来用来发布应用
cd /docker/service && cp /docker/service/projectName/service-main/service-boot/target/service-1.0-SNAPSHOT.jar /docker/service
sh /docker/service/publish.sh
publish.sh
发布应用
#!/bin/bash
#设置环境变量
export JAVA_HOME=/usr/local/jdk1.8.0_181
export JRE_HOME=/$JAVA_HOME/jre
export CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin
#这里可替换为你自己的执行程序,其他代码无需更改
APP_NAME=/docker/service/service.jar
#使用说明,用来提示输入参数
usage() {
echo "Usage: sh restart.sh [start|stop|restart|status]"
exit 1
}
#检查程序是否在运行
#grep -v反选匹配 awk指定文件某一行
is_exist(){
pid=`ps -ef|grep $APP_NAME|grep -v grep|awk '{print $2}'`
#如果不存在返回1,存在返回0
if [ -z "${pid}" ]; then
return 1
else
return 0
fi
}
#启动方法
start(){
is_exist
if [ $? -eq 0 ]; then
echo "${APP_NAME} is already running. pid=${pid}"
else
nohup java -Dfile.encoding=utf-8 -jar -Xms128m -Xmx1024m ${APP_NAME} --spring.profiles.active=prod > /var/logs/service.log 2>&1 &
fi
}
#停止方法
stop(){
is_exist
if [ $? -eq "0" ]; then
kill -9 $pid
else
echo "${APP_NAME} is not running"
fi
}
#输出运行状态
status(){
is_exist
if [ $? -eq "0" ]; then
echo "${APP_NAME} is running. Pid is ${pid}"
else
echo "${APP_NAME} is NOT running."
fi
}
#重启
restart(){
stop
sleep 5
start
}
#根据输入参数,选择执行对应方法,不输入则执行使用说明
case "$1" in
"start")
start
;;
"stop")
stop
;;
"status")
status
;;
"restart")
restart
;;
*)
usage
;;
esac
四、使用maven不同环境配置加载不同的依赖
在项目开发中可能会产生这样的需求,开发环境依赖于 A 包,测试环境依赖 B 包,生产环境依赖于 C 包。按照我们传统的思维会每个环境注释掉相应的包,然后再打包,一次两次操作还好,操作多了之后这样会很麻烦。
Maven 不同环境引用依赖
Maven 配置
<profiles>
<!-- 测试环境 -->
<profile>
<id>dev</id>
<!-- 默认激活 dev 环境 -->
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<profiles.active>dev</profiles.active>
</properties>
<dependencies>
<!-- pay_provider -->
<dependency>
<groupId>com.allens.test</groupId>
<artifactId>allens-redis</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
</profile>
<!-- 生产环境 -->
<profile>
<id>prod</id>
<properties>
<profiles.active>prod</profiles.active>
</properties>
<dependencies>
<!-- pay_provider -->
<dependency>
<groupId>com.allens.test</groupId>
<artifactId>allens-redis</artifactId>
<version>2.0-SNAPSHOT</version>
</dependency>
</dependencies>
</profile>
</profiles>
切换不同环境
我们可以在idea的Maven窗口中选中需要的profile环境,然后在lifecircle 中 clean install即可。
当然我们也可以使用maven 命令进行打包指定不同环境
## 开发环境打包
mvn clean package -P dev
## 测试环境打包
mvn clean package -P test
## 生产环境打包
mvn clean package -P pr
最佳实践
① Springboot 热部署插件,在开发环境需要,在测试环境、预发环境、生产环境都是不需要的。
② OceanBase 不同版本适配的不同的操作系统,我们可以借助profile配置不同环境下配置不同的包来做到不同环境切换依赖。
Maven不同环境打包不同配置
和传统的部署方式不同,我们将配置文件放入到不同的目录,使用build>resource来在编译的时候,通过读取不同环境的profiles.active
属性来获取不同环境目录下的配置打包到classpath目录中。
传统的配置方式
传统配置方式会将配置文件放到resources底下,然后给配置文件命名 application-${env}.yml
来区分不同环境。在JVM参数中指定-Dspring.active.profiles=${env}
或者在idea中:
或者在 bootstrap.yml 或者application.yml中指定默认的配置:
spring:
profiles:
active: ${env}
所有环境的配置都会打包到jar包中。
maven通过编译打包确定环境配置。
只有需要的环境配置才会打包到jar包中。
maven 配置
<profiles>
<!-- 测试环境 -->
<profile>
<id>dev</id>
<!-- 默认激活 dev 环境 -->
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<profiles.active>dev</profiles.active>
<pay.dubbo.version>1.0.0-SNAPSHOT</pay.dubbo.version>
</properties>
<dependencies>
<!-- pay_provider -->
<dependency>
<groupId>com.allens.test</groupId>
<artifactId>common-utils</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
</profile>
<!-- 生产环境 -->
<profile>
<id>prod</id>
<properties>
<profiles.active>prod</profiles.active>
</properties>
<dependencies>
<!-- pay_provider -->
<dependency>
<groupId>com.allens.test</groupId>
<artifactId>common-utils</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</profile>
</profiles>
<build>
<!-- 指定maven编译资源文件位置 -->
<resources>
<!-- 编译 src/main/resources 中的资源文件 -->
<resource>
<directory>src/main/resources</directory>
</resource>
<!-- 根据不同的 mvn 命令参数编译 filters 目录中指定的配置文件 -->
<resource>
<directory>src/main/config/${profiles.active}</directory>
<targetPath>./</targetPath>
</resource>
</resources>
</build>
编译后的目录结构
五、如何加快maven打包速度
前言
众所周知,Maven和Gradle几乎包含了所有Java项目的构建。而目前绝大部分的Java项目都是使用Maven的方式,Maven对比Gradle的劣势很明显,就是太慢了!
但是现在,Maven也可以变得更快了!
1. maven-mvnd是什么?
maven-mvnd
是Apache Maven团队借鉴了Gradle和Takari的优点,衍生出来的更快的构建工具,maven的强化版!
maven-mvnd
在设计上,使用一个或多个守护进程来构建服务,以此来达到并行的目的!同时,maven-mvnd
内置了maven,因此我可以在maven 过渡到 maven-mvnd的过程中实现 无缝切换!不必再安装maven或进行复杂的配置更改。
官方仓库地址: https://github.com/apache/maven-mvnd
2. 使用步骤
-
从GitHub下载压缩包
访问仓库版本地址,https://github.com/apache/maven-mvnd/releases
如下所示:
点击对应开发环境的版本进行下载即可,笔者这边为window,下载 mvnd-0.7.1-windows-amd64.zip 版本 -
解压,配置环境变量
- 把下载的压缩包解压后,配置 其中bin 目录地址到系统 path 环境变量中,如何配置环境变量不在此详述
- 配置环境变量是为了在 cmd 的任意地址,可以识别到 bin 下的 mvnd 命令
- 配置完成,输入 mvnd -version 查看版本信息
mvnd -version
输出如下信息代表安装成功!
C:\WINDOWS\system32>mvnd -version mvnd native client 0.7.1-windows-amd64 (97c587c11383a67b5bd0ff8388bd94c694b91c1e) Terminal: org.jline.terminal.impl.jansi.win.JansiWinSysTerminal Apache Maven 3.8.3 (ff8e977a158738155dc465c6a97ffaf31982d739) Maven home: D:\Code\mvnd-0.7.1-windows-amd64\mvn Java version: 1.8.0_102, vendor: Oracle Corporation, runtime: D:\JAVA\jdk\jre Default locale: zh_CN, platform encoding: GBK OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"
-
如何使用
mvnd 与 maven 命令几乎没有任何不同,可以通过查看mvnd -help 查看
举个例子、如要打包安装,则把 mvn clean install 替换为 mvnd clean install 即可 -
配置使用原先已存在的 maven 的仓库!
可以修改 mvnd 解压目录下 conf 里的 mvnd.properties 文件,
拉到最后面,放开 maven.setting 注释,把值改成自己的maven仓库地址即可,如下:
maven.settings=D://maven//apache-maven-3.6.3//conf//settings.xml
注意!这里如果直接复制windows文件的路径,会是这样一个效果
D:\maven\apache-maven-3.6.3\conf\settings.xml
如果直接粘贴到 配置里会报错!
需要把 \ 转换成 // 到此配置已经完成 !
3. 打包速度对比
这里使用一个普通 Java 项目来实验对比,分别使用 maven 和 maven-mvnd 进行打包,
maven 打包命令:
mvn clean install -DskipTests
mvnd 打包命令:
mvnd clean install -DskipTests
结果如下,速度提升 3 倍 左右 !
速度提升没有网上传言的 8 倍那么夸张
当然,这可能和笔者的机器或项目有关,你们可以使用你们的项目另行验证!