在 Spring Boot 微服务项目中,常见结构如下:
text
root
├─ service-auth
├─ service-gateway
├─ service-system
├─ service-xxx
└─ pom.xml(父工程)
每个模块都是一个 可独立启动的 Spring Boot 应用 ,在打包过程中,各自的包都在各模块的 target/ 下,统一部署需要手动逐个找到所有的jar包,比较繁琐且低效。希望能有一套更高效且不影响微服务独立性的方案。
二、推荐方案总览
- 父 POM 统一汇总
- 使用 Assembly 插件生成发布包
- 脚本统一收集
- 每个模块自己 copy
三、方案一:父工程统一聚合微服务 Jar(推荐)
核心思路
- 每个微服务 正常打 jar
- 父工程在
package阶段:- 自动收集所有子模块 jar
- 汇总到统一目录
3.1 统一输出目录定义
在 父 pom.xml 中定义:
xml
<properties>
<dist.dir>${project.build.directory}/dist</dist.dir>
</properties>
3.2 使用 maven-dependency-plugin 聚合
xml
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-all-modules</id>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<outputDirectory>${dist.dir}</outputDirectory>
<includeTypes>jar</includeTypes>
<stripVersion>true</stripVersion>
<overWriteReleases>true</overWriteReleases>
<overWriteSnapshots>true</overWriteSnapshots>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
配置说明
| 参数 | 作用 |
|---|---|
| outputDirectory | 汇总目录 |
| includeTypes | 只拷贝 jar |
| stripVersion | 去掉版本号,利于部署 |
| overWrite | 防止多次构建残留 |
3.3 示例
bash
mvn clean package -DskipTests
生成:
text
target/dist/
├─ analyzer-auth.jar
├─ analyzer-gateway.jar
├─ analyzer-modules-system.jar
├─ analyzer-special-xxx.jar
└─ ...
只需要关注 target/dist就可以
3.4 为什么可以在父工程统一收集 Jar?
Maven 构建顺序保证
text
父工程
├─ 子模块 A(jar)
├─ 子模块 B(jar)
└─ 子模块 C(jar)
当执行:
bash
mvn package
Maven 会:
- 先构建所有子模块
- 再执行父工程的
package阶段插件
因此在父工程package阶段:
- 所有子模块 jar 已经生成
- 父工程可以进行:
- copy
- 聚合
四、方案二:使用 Assembly 生成发布包
4.1 Assembly 描述文件(assembly.xml)
xml
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3">
<id>dist</id>
<formats>
<format>tar.gz</format>
</formats>
<baseDirectory>security-analyzer</baseDirectory>
<fileSets>
<fileSet>
<directory>${project.build.directory}/dist</directory>
<outputDirectory>/apps</outputDirectory>
</fileSet>
<fileSet>
<directory>script</directory>
<outputDirectory>/script</outputDirectory>
</fileSet>
</fileSets>
</assembly>
4.2 父 POM 绑定 Assembly 插件
xml
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
4.3 示例
text
target/security-analyzer-dist.tar.gz
解压后:
text
security-analyzer/
├─ apps/
│ ├─ auth.jar
│ ├─ gateway.jar
│ └─ system.jar
├─ script/ ## 配置的 fileSet
│ ├─ start.sh
│ └─ stop.sh
└─ README.md
五、方案三:统一收集
5.1 Jenkins Shell 示例
bash
mkdir -p dist
find . -path "*/target/*.jar" -name "*.jar" -exec cp {} dist/ \;
优缺点
| 优点 | 缺点 |
|---|---|
| 不改 pom | 构建逻辑不在代码 |
| 快速生效 | 可能导致本地与其他位置不一致 |
| 适合存量项目 | 可维护性较差 |
六、方案四:子模块自行 Copy 到公共目录(不推荐)
不推荐原因:
- 模块职责混乱
- 父工程失去发布控制权
- 模块被复用时易出问题
- 不符合微服务自治原则
子模块单独构建,或被其他项目复用时,配置立即失效或产生副作用。
6.1 方案四的核心思路
在子模块中:在 package 阶段,将自身 jar copy 到一个 公共目录
6.2 示例配置(maven-resources-plugin)
在 子模块 pom.xml 中:
xml
<build>
<plugins>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.3.1</version>
<executions>
<execution>
<id>copy-jar-to-dist</id>
<phase>package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.parent.basedir}/dist</outputDirectory>
<resources>
<resource>
<directory>${project.build.directory}</directory>
<includes>
<include>*.jar</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>