Spring Boot 项目标准化部署打包实战
Spring Boot 项目标准化部署打包实战
一、目标
将 Spring Boot 项目打包为开箱即用的生产环境部署包。用户解压后只需修改配置文件,运行启动脚本即可启动服务。
最终目录结构
your-app/ ├── bin/ │ ├── startup.sh # Linux 启动脚本 │ └── startup.cmd # Windows 启动脚本 ├── conf/ │ └── application.yml # 外部配置文件(解耦,方便运维修改) ├── lib/ │ ├── your-app.jar # 主程序 JAR │ └── *.jar # 依赖 JAR ├── logs/ # 日志目录(自动创建) └── LICENSE设计理念
- 配置与程序分离:
conf/application.yml独立于 JAR,运维人员无需接触代码 - 一键启动:封装好 JVM 参数和 classpath 的启动脚本,降低操作门槛
- 热迭代:后续升级只需替换
lib/your-app.jar,配置、依赖、脚本全不动
二、环境要求
| 组件 | 版本要求 |
|---|---|
| JDK | 8+ |
| Maven | 3.6+ |
| Spring Boot | 2.x |
三、Maven 配置
3.1 pom.xml 插件配置
<build><plugins><!-- 1. 依赖拷贝插件:将所有依赖 JAR 拷贝到 target/lib/ --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-dependency-plugin</artifactId><executions><execution><id>copy-dependencies</id><phase>package</phase><goals><goal>copy-dependencies</goal></goals><configuration><outputDirectory>${project.build.directory}/lib</outputDirectory></configuration></execution></executions></plugin><!-- 2. Spring Boot 打包插件:生成可执行 JAR --><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>2.1.18.RELEASE</version><configuration><mainClass>com.your.MainApplication</mainClass></configuration><executions><execution><goals><goal>repackage</goal></goals></execution></executions></plugin><!-- 3. Assembly 打包插件:按自定义结构打包为 tar.gz --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-assembly-plugin</artifactId><configuration><descriptors><descriptor>src/assembly/package.xml</descriptor></descriptors></configuration><executions><execution><id>make-assembly</id><phase>package</phase><goals><goal>single</goal></goals></execution></executions></plugin></plugins></build>重要提示:如果使用JDK 8,
spring-boot-maven-plugin必须锁定版本为2.1.18.RELEASE,否则会报class file version 61.0错误(高版本插件编译的 class 与 JDK 8 不兼容)。
四、Assembly 打包配置
创建src/assembly/package.xml:
<assemblyxmlns="http://maven.apache.org/ASSEMBLY/2.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd"><id>release</id><formats><format>tar.gz</format></formats><includeBaseDirectory>true</includeBaseDirectory><baseDirectory>your-app</baseDirectory><fileSets><!-- 启动脚本,权限 755 --><fileSet><directory>src/assembly/bin</directory><outputDirectory>bin</outputDirectory><fileMode>0755</fileMode></fileSet><!-- 配置文件 --><fileSet><directory>src/main/resources</directory><outputDirectory>conf</outputDirectory></fileSet></fileSets><!-- 依赖 JAR 全部打入 lib/ --><dependencySets><dependencySet><outputDirectory>lib</outputDirectory><includes><include>*:jar</include></includes></dependencySet></dependencySets></assembly>各节点说明:
| 节点 | 作用 |
|---|---|
<id>release</id> | 最终产物名后缀:your-app-release.tar.gz |
<format>tar.gz</format> | 打包格式,跨平台通用 |
<baseDirectory> | 解压后的根目录名 |
<fileMode>0755</fileMode> | Linux 下脚本可执行权限 |
五、启动脚本
5.1 Windows 启动脚本
src/assembly/bin/startup.cmd:
@echo off set DIR=%~dp0.. cd %DIR% if not exist "%DIR%\logs" mkdir "%DIR%\logs" set JAVA_OPTS=-Xms256m -Xmx1024m -Dfile.encoding=UTF-8 java %JAVA_OPTS% ^ -Dloader.path="%DIR%\lib" ^ -Dspring.config.location=file:"%DIR%\conf\application.yml" ^ -jar "%DIR%\lib\your-app.jar" ^ > "%DIR%\logs\app.log" 2>&1 echo Started. pause说明:
%~dp0是批处理脚本自身所在目录,%~dp0..回到项目根目录。^是 Windows 命令行续行符。
5.2 Linux 启动脚本
src/assembly/bin/startup.sh:
#!/bin/bash# 获取脚本所在目录的上级目录(即项目根目录)DIR="$(cd "$(dirname"$0")/.."&&pwd)" cd "$DIR" # 创建日志目录 mkdir -p logs # JVM 参数 JAVA_OPTS="-Xms256m-Xmx1024m-Dfile.encoding=UTF-8" # 后台启动,日志输出到 logs/app.log nohup java$JAVA_OPTS\ -Dloader.path="$DIR/lib" \ -Dspring.config.location=file:"$DIR/conf/application.yml" \ -jar "$DIR/lib/your-app.jar" \ > "$DIR/logs/app.log" 2>&1 & echo "Started. PID:$!"脚本解读:
| 配置项 | 说明 |
|---|---|
-Xms256m -Xmx1024m | 初始堆 256M,最大堆 1G(按实际调整) |
-Dloader.path | 指定依赖 JAR 加载路径,配合PropertiesLauncher使用 |
-Dspring.config.location | 指定外部配置文件路径,优先级高于 JAR 内的配置 |
nohup ... & | 后台运行,终端关闭不中断 |
$! | 最后启动的后台进程 PID |
六、打包与部署
6.1 打包
mvn clean package执行后在target/目录下生成your-app-release.tar.gz。
6.2 部署
# 1. 解压tar-xzfyour-app-release.tar.gz# 2. 修改配置vimyour-app/conf/application.yml# 3. 启动cdyour-app/bin# Linuxshstartup.sh# Windowsstartup.cmd部署只需三步:解压 → 改配置 → 启动。
七、迭代更新
后续升级只需替换一个 JAR 文件,流程如下:
- 本地改完代码,执行
mvn clean package - 将新的
your-app.jar上传到服务器 - 替换
lib/下的旧 JAR - 重启服务
配置、依赖、启动脚本全部不用动,真正实现热迭代。
八、常见问题
8.1 端口被占用
# Windows:查看端口占用netstat-ano|findstr :8080# Windows:杀掉进程taskkill /pid 进程ID /f# Linux:查看端口占用lsof-i:8080# Linux:杀掉进程kill-9进程ID8.2 找不到主类
检查pom.xml中spring-boot-maven-plugin的<mainClass>配置是否正确,需指向带@SpringBootApplication注解的主类。
8.3 JAR 中没有主清单属性
确保spring-boot-maven-plugin配置了<goal>repackage</goal>,只有repackage才会生成MANIFEST.MF中的Main-Class。
8.4class file version 61.0错误
原因:高版本 Spring Boot Maven Plugin(3.x)编译的 class 需要 JDK 17+,与 JDK 8 不兼容。
解决:JDK 8 环境下将spring-boot-maven-plugin版本降级到2.1.18.RELEASE。
8.5 配置文件找不到
启动参数中的路径建议使用绝对路径(%DIR%/$DIR),避免因工作目录不同导致相对路径解析失败。脚本中已通过DIR变量实现了此逻辑。
8.6 日志文件不输出
- 确认
logs/目录有写入权限 - 检查启动用户是否有当前目录的写权限
nohup输出会先写入nohup.out,确认重定向符号>正确
九、总结
通过Maven Assembly 插件 + 外部配置文件 + 启动脚本的组合,可以将 Spring Boot 项目打包为标准的生产环境部署包。
| 维度 | 收益 |
|---|---|
| 部署成本 | 解压 → 改配置 → 启动,三步完成 |
| 运维友好 | 配置外置,无需懂 Java 也能改配置、看日志 |
| 迭代效率 | 升级只换一个 JAR,秒级完成 |
| 跨平台 | Windows / Linux 均有对应启动脚本 |
| 标准化 | 统一的目录结构,不同项目一致,降低认知成本 |
延伸思考:在生产环境中,可以进一步加入
-XX:+HeapDumpOnOutOfMemoryError、GC 日志、JMX 监控等 JVM 参数,结合 Systemd(Linux)或 NSSM(Windows)实现服务托管和自动重启。
