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 8 ,spring-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.xml 中 spring-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)实现服务托管和自动重启。

相关推荐
明月_清风5 小时前
Muse 登顶 App Store 第一,SDK 直接开源:AI Agent 开始进入下一个阶段
人工智能·后端
leikooo5 小时前
用餐厅和盘子理解栈和堆
java·数据结构·链表·rust
Ivanqhz6 小时前
激活函数在 Transformer 中的作用及各种变体简述
java·linux·数据库·人工智能·深度学习
沙漠之主6 小时前
C++编程教学设计资料:从入门到实战的完整课程方案
java·前端·c++
FPGA小徐7 小时前
PA1 基础设施(2)深度解析:NEMU 中 ITRACE、MTRACE、FTRACE、IRINGBUF、ETRACE、DIFFTEST 全解析
java·服务器·网络
YOLO数据集集合7 小时前
EvoAgent:面向PR研发治理的自进化Multi-Agent Harness系统
java·开发语言·目标检测·agent·自进化
hsfxuebao7 小时前
Loop Engineering 保姆级教程 + 项目实战
人工智能·后端
知行EDI7 小时前
知行之桥 MaBang 端口使用指南——Create Order 订单创建篇
java·服务器·数据库
笑鸿的学习笔记7 小时前
C++笔记之大块顺序写
java·c++·笔记
打工仔折腾 AI8 小时前
从 Demo 到生产级 Agent:8 个关键设计机制与 Python 实现拆解
java·jvm·人工智能·后端·python·langchain·ai agent 实战