实际的工程开发中,我们经常接触到的部署场景至少存在本地,测试,生产三类。一般情况下三者之间有着或多或少的差异,诸如数据库链接地址,附件服务器存储路径等等。这种时候如果试图靠人工来进行相应的替换构建和部署,实在有违我们这个行业的初衷。
1. 概述
Maven提供了多种特性来帮助我们实现多环境下的打包构建。这次我们就以一个现实的场景为例,介绍一类完整的实现方式。
2. 场景介绍
场景如下:“产品需要被部署到多个地区,因此每次编译都要根据各个地方上不同的情况将诸如数据库配置,附件服务器位置配置等其它信息进行相应的替换,才能进行最终的测试和发包”。
3. 实现
3.1 项目目录结构
首先让我们看看目录结构:
│ pom.xml
└─src
├─main
├─test
└─_res
├─assembly
│ assembly.xml # 供 maven-assembly-plugin 使用
└─profiles
├─dev # 开发环境配置
├─product # 生产环境配置
│ │ application.yml # 存储有区域性配置的配置文件
│ │ db.properties # 存储有区域性配置的配置文件
│ │
│ └─_area # 区域特意信息
│ Beijin.properties
│ Xian.properties
│
└─test # 测试环境配置
3.2 pom.xml
文件
<properties>
<jdk>1.8</jdk>
<!-- 使用assembly生成的zip包存放的目录 -->
<build.assemblySavePath>C:/Users/LQ/Desktop/</build.assemblySavePath>
<!-- 区域名称 -->
<area.name></area.name>
</properties>
<profiles>
<profile>
<id>product</id> <!--指定ID-->
<build>
<resources>
<resource>
<directory>src\main\resources</directory>
<excludes>
<exclude>application.yml</exclude>
<exclude>db.properties</exclude>
</excludes>
</resource>
</resources>
<plugins>
<!-- Maven之打包时配置文件替换 : https://www.bbsmax.com/A/Ae5R97LmJQ/ -->
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<copy file="${basedir}/src/_res/profiles/product/db.properties"
tofile="${project.build.directory}/db.properties" filtering="true"
overwrite="true">
<filterset filtersfile="${basedir}/src/_res/profiles/product/_area/${area.name}.properties">
</filterset>
</copy>
<copy file="${basedir}/src/_res/profiles/product/application.yml"
tofile="${project.build.directory}/application.yml"
filtering="true" overwrite="true">
<filterset filtersfile="${basedir}/src/_res/profiles/product/_area/${area.name}.properties">
</filterset>
</copy>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
<!-- 打包自定义的格式包,这种情况就可以使用maven-assembly-plugin插件。 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<skip>false</skip>
<!-- 压缩包的名称 + 每个descriptor的id 就是最终的压缩包名称 -->
<finalName>${project.artifactId}-${area.name}</finalName>
<!-- 打包后的包名是否包含assembly的id名 -->
<appendAssemblyId>true</appendAssemblyId>
<!-- 压缩包最终的输出位置 -->
<outputDirectory>
${build.assemblySavePath}
</outputDirectory>
<!-- 引用的assembly配置文件,可以用多个,即可以同时打包多个格式的包; -->
<descriptors>
<descriptor>
src/_res/assembly/assembly.xml
</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<!-- this is used for inheritance merges -->
<id>make-assembly</id>
<!-- bind to the packaging phase -->
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
3.3 assembly.xml
文件
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<id>bin</id>
<formats>
<format>zip</format>
</formats>
<!-- 决定下面的 baseDirectory 节点是否生效 -->
<includeBaseDirectory>false</includeBaseDirectory>
<!-- 压缩包里的文件都会被baseDirectory所指示的文件夹所包裹;;;
即打开压缩包第一步看到的是一个文件夹, 文件夹里面才是 <files> 节点里配置的各个文件
. 表示不使用文件夹, <files>节点里配置的各个文件直接出现在压缩包之下
-->
<baseDirectory>xxx</baseDirectory>
<!-- 配置文件;;;定义 代码文件 中与 输出文件 的映射 -->
<files>
<file>
<!-- 相对目录 POM.xml所在目录 -->
<source>target/${artifactId}.jar</source>
<outputDirectory>.</outputDirectory>
<destName>${artifactId}.jar</destName>
</file>
</files>
<fileSets>
<fileSet>
<!-- ${project.build.directory}指代构建目录,缺省为target -->
<directory>${project.build.directory}</directory>
<outputDirectory>.</outputDirectory>
<includes>
<include>*.yml</include>
<include>*.properties</include>
</includes>
</fileSet>
</fileSets>
</assembly>
3.4 其它配置文件
# 1. application.yml
server:
port: @port@ # 没错, 这种格式在 maven-antrun-plugin 中是默认的占位符格式。
# 2. db.properties
@areaName@
# 3. Beijin.properties
areaName=Beijin
port=8090
# 4. Xian.properties
areaName=Xian
port=8091
4. Maven打包
# 注意这里的 "-Dxxx=yyy" 参数因为笔者习惯于在Powershell下执行, CMD下需要去掉这些""。
mvn clean package "-Dmaven.test.skip=true" -P product "-Dbuild.assemblySavePath=./" "-Darea.name=Xian"
5. Links
- 《Maven实战》 第十四章
- Office Site - maven-antrun-plugin