当前位置: 首页 > news >正文

【JAVA WEB实用与优化技巧】Maven自动化构建与Maven 打包技巧

文章目录

  • 一、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 命令及其作用:

  1. 创建项目
    mvn archetype:create: 创建一个新的 Maven 项目,此命令已废弃,现在推荐使用 mvn archetype:generate。
  2. 初始化项目
    mvn archetype:generate: 生成一个新的 Maven 项目骨架,允许用户交互式地选择项目类型和属性。
  3. 编译
    mvn compile: 编译项目的源代码。
  4. 测试
    mvn test-compile: 编译项目的测试源代码。
    mvn test: 运行项目的测试,并生成测试报告。
  5. 打包
    mvn package: 编译、测试并打包项目(如 JAR、WAR 或 EAR 文件)。
  6. 验证
    mvn verify: 验证工件是否符合质量标准,通常会运行集成测试。
  7. 安装
    mvn install: 将构建好的工件安装到本地 Maven 仓库,供本地项目依赖。
  8. 部署
    mvn deploy: 将工件部署到远程仓库,供整个团队或公众使用。
  9. 清理
    mvn clean: 删除 target 目录及其所有内容,用于清理构建输出。
  10. 生成站点文档
    mvn site: 生成项目相关的文档和站点。
    mvn site:deploy: 将生成的站点部署到服务器。
  11. 更新依赖
    mvn dependency:update: 更新项目中所有依赖的版本。
  12. 帮助
    mvn help:effective-pom: 显示项目的实际 POM,包括继承和聚合的效果。
    mvn help:all-plugin-goals: 列出所有可用的插件目标。
    mvn help:system: 显示系统环境变量。
  13. 设置属性
    mvn -Dproperty=value command: 设置 Maven 环境变量,如 -DskipTests=true 可以跳过测试。
    执行特定生命周期阶段
    mvn lifecycle-phase: 直接执行生命周期中的特定阶段,例如 mvn process-resources
  14. 插件目标
    mvn plugin:goal: 直接执行某个插件的目标,如 mvn compiler:compile
    请注意,以上命令在实际使用时可能会根据项目的具体配置有所不同。要查看更详细的命令用法和选项,可以运行 mvn help:help 或 mvn --help。

二、如何编写maven打包脚本

maven 配置详解

setting.xml

Maven的settings.xml文件是用于配置Maven行为的重要文件,它提供了对Maven默认行为的自定义。这个文件主要有两个位置:

  1. 全局配置:位于Maven安装目录的conf子目录下,影响所有使用该Maven安装的用户。
  2. 用户配置:位于用户主目录下的.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. 使用步骤

  1. 从GitHub下载压缩包
    访问仓库版本地址,https://github.com/apache/maven-mvnd/releases
    如下所示:
    在这里插入图片描述
    点击对应开发环境的版本进行下载即可,笔者这边为window,下载 mvnd-0.7.1-windows-amd64.zip 版本

  2. 解压,配置环境变量

    • 把下载的压缩包解压后,配置 其中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"
    
  3. 如何使用
    mvnd 与 maven 命令几乎没有任何不同,可以通过查看mvnd -help 查看
    举个例子、如要打包安装,则把 mvn clean install 替换为 mvnd clean install 即可

  4. 配置使用原先已存在的 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 倍那么夸张
当然,这可能和笔者的机器或项目有关,你们可以使用你们的项目另行验证!
在这里插入图片描述

相关文章:

  • HackTheBox-Machines--Lazy
  • 大聪明教你学Java | 深入浅出聊 Stream.parallel()
  • 【面试题】JavaScript基础高频面试(上)
  • 在SpringBoot项目中实现切面执行链功能
  • 【SQL学习进阶】从入门到高级应用【三范式】
  • ChatGPT AI专题资料合集【65GB】
  • [补题记录]LeetCode 167.两数之和 II - 输入有序数组
  • 【自己动手】自制刷题系统(php+layui应用 社区工作者题库)
  • 24年护网工具,今年想参加护网的同学要会用
  • 深度学习训练时混合精度的作用
  • 如何使用AES128位进行视频解密
  • Leetcode:字符串转换整数 (atoi)
  • 软件开发整体介绍
  • Java中连接Mongodb进行操作
  • iOS Hittest 机制和实际应用之一 hittest方法
  • 【魅力网页的背后】:CSS基础魔法,从零打造视觉盛宴
  • ChatGPT-3
  • 【开源】新生报到网站 JAVA+Vue.js+SpringBoot+MySQL
  • 【原创】springboot+mysql员工管理系统
  • springboot基础及上传组件封装
  • 三星“七天机”质保期内屏幕漏液被要求自费维修,商家:系人为损坏
  • 秦洪看盘|交易型资金收缩,释放短线压力
  • 稳住外贸基本盘,这个中部大省出手了
  • 850亿元!2025年中央金融机构注资特别国债(一期)拟第一次续发行
  • 图忆|红场阅兵:俄罗斯30年来的卫国战争胜利日阅兵式
  • 迪拜金融市场CEO:2024年市场表现出色,超八成新投资者来自海外