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 插件配置

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 8spring-boot-maven-plugin 必须锁定版本为 2.1.18.RELEASE ,否则会报 class file version 61.0 错误(高版本插件编译的 class 与 JDK 8 不兼容)。


四、Assembly 打包配置

创建 src/assembly/package.xml

xml 复制代码
<assembly
    xmlns="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

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

bash 复制代码
#!/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 打包

bash 复制代码
mvn clean package

执行后在 target/ 目录下生成 your-app-release.tar.gz

6.2 部署

bash 复制代码
# 1. 解压
tar -xzf your-app-release.tar.gz

# 2. 修改配置
vim your-app/conf/application.yml

# 3. 启动
cd your-app/bin

# Linux
sh startup.sh

# Windows
startup.cmd

部署只需三步:解压 → 改配置 → 启动


七、迭代更新

后续升级只需替换 一个 JAR 文件,流程如下:

  1. 本地改完代码,执行 mvn clean package
  2. 将新的 your-app.jar 上传到服务器
  3. 替换 lib/ 下的旧 JAR
  4. 重启服务

配置、依赖、启动脚本全部不用动,真正实现热迭代。


八、常见问题

8.1 端口被占用

bash 复制代码
# Windows:查看端口占用
netstat -ano | findstr :8080

# Windows:杀掉进程
taskkill /pid 进程ID /f
bash 复制代码
# Linux:查看端口占用
lsof -i :8080

# Linux:杀掉进程
kill -9 进程ID

8.2 找不到主类

检查 pom.xmlspring-boot-maven-plugin<mainClass> 配置是否正确,需指向带 @SpringBootApplication 注解的主类。

8.3 JAR 中没有主清单属性

确保 spring-boot-maven-plugin 配置了 <goal>repackage</goal>,只有 repackage 才会生成 MANIFEST.MF 中的 Main-Class

8.4 class 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)实现服务托管和自动重启。

相关推荐
jay神7 小时前
基于微信小程序课外创新实践学分认定系统
java·spring boot·小程序·vue·毕业设计
Gauss松鼠会7 小时前
GaussDB(DWS) GUC参数修改、查看
java·数据库·sql·数据库开发·gaussdb
Qhappy7 小时前
AI逆向实战:从零还原某航空App的AES加密
javascript·后端
tonydf7 小时前
Nginx爆新的RCE漏洞!别担心,平滑升级即可。
后端·nginx
AIFQuant7 小时前
Java 对接全球股票实时报价:高可用架构与异常处理
java·开发语言·websocket·金融·架构·股票api
未若君雅裁7 小时前
Spring Bean 作用域、线程安全与生命周期
java·安全·spring
奋斗的小乌龟7 小时前
langchain4j笔记-智能体系统01
java·笔记
Java编程爱好者7 小时前
JVM GC调优实战:从线上频繁Full GC到RT降低80%的全过程
后端
wh_xia_jun7 小时前
用pom 的test 配置 与 jacoco
java·ide·intellij-idea