Spring Boot + JPackage:构建独立安装包

前言

从 JDK 14 开始,Java 官方引入了 JPackage 工具(在 JDK 16 正式成为标准功能),它能够将 Java 应用打包成特定平台的原生安装包,自带定制化的 JRE 运行环境。这意味着用户无需提前安装 Java 环境,双击安装包即可完成应用部署,极大地简化了交付流程。

本文将介绍如何使用 JPackage 工具将 Spring Boot 项目打包成 Windows、macOS 或 Linux 平台的原生安装包。

一、JPackage 简介

1.1 什么是 JPackage

JPackage 是 JDK 自带的打包工具,位于 $JAVA_HOME/bin 目录下。它的核心功能是:

生成平台原生安装包 :Windows 的 .exe/.msi、macOS 的 .dmg/.pkg、Linux 的 .deb/.rpm

自定义 JRE :使用 jlink 工具裁剪 JDK,仅打包应用所需的模块,大幅减小安装包体积

简化部署:用户无需预装 Java 环境,安装包自带运行时

1.2 JPackage 的优势

传统部署方式 JPackage 方式
需要预装 JRE/JDK 自带 JRE,无需额外安装
环境版本可能不匹配 绑定特定 JRE 版本,环境一致
手动编写启动脚本 自动生成启动器
跨平台需要多套脚本 一键生成各平台安装包

二、环境准备

2.1 JDK 版本要求

推荐使用 JDK 17 或更高版本(JPackage 在 JDK 16 才成为标准功能,JDK 17 是 LTS 版本)

确认 JPackage 可用:

bash 复制代码
jpackage --version

2.2 平台特定工具

根据目标操作系统,需要安装对应的打包工具:

Windows

WiX Toolset 3.11+ (用于生成 .msi 安装包)

下载地址:https://wixtoolset.org/

安装后将 bin 目录添加到系统环境变量 PATH

macOS

Xcode 命令行工具(用于生成 .dmg/.pkg

bash 复制代码
xcode-select --install
Linux

Debian/Ubuntu :安装 fakeroot

bash 复制代码
sudo apt-get install fakeroot

RedHat/CentOS :安装 rpm-build

bash 复制代码
sudo yum install rpm-build

三、Spring Boot 项目准备

3.1 示例项目结构

假设我们有一个标准的 Spring Boot 项目:

复制代码
my-springboot-app/
├── src/
│   └── main/
│       ├── java/
│       └── resources/
├── pom.xml
└── target/
    └── my-app-1.0.0.jar

3.2 构建可执行 JAR

首先使用 Maven 或 Gradle 构建项目:

bash 复制代码
# Maven
mvn clean package

# Gradle
gradle clean build

确保生成的 JAR 包是可执行的(Spring Boot 默认打包方式)。

四、使用 JPackage 打包

4.1 基础打包命令

以下是一个基础的 JPackage 命令示例(以 Windows 为例):

bash 复制代码
jpackage \
  --input target \
  --name MySpringBootApp \
  --main-jar my-app-1.0.0.jar \
  --main-class org.springframework.boot.loader.JarLauncher \
  --type msi \
  --app-version 1.0.0 \
  --vendor "我的公司" \
  --description "基于 Spring Boot 的企业级应用" \
  --icon src/main/resources/app-icon.ico \
  --win-dir-chooser \
  --win-menu \
  --win-shortcut
参数说明
参数 说明
--input 输入目录,包含 JAR 包和依赖
--name 应用名称
--main-jar 主 JAR 包文件名
--main-class 主类(Spring Boot 使用 JarLauncher
--type 安装包类型(msi/exe/dmg/pkg/deb/rpm
--app-version 应用版本号
--icon 应用图标(Windows 用 .ico,macOS 用 .icns
--win-dir-chooser 允许用户选择安装目录
--win-menu 创建开始菜单项
--win-shortcut 创建桌面快捷方式

4.2 自定义 JRE(使用 jlink)

为了减小安装包体积,可以使用 jlink 裁剪 JRE,仅包含必要的模块。

步骤 1:查找应用依赖的模块
bash 复制代码
jdeps --list-deps target/my-app-1.0.0.jar

输出示例:

复制代码
java.base
java.logging
java.sql
java.naming
java.desktop
...
bash 复制代码
jlink \
  --add-modules java.base,java.logging,java.sql,java.naming,java.desktop,java.xml,java.management \
  --output custom-jre \
  --strip-debug \
  --no-header-files \
  --no-man-pages \
  --compress=2
步骤 3:使用自定义 JRE 打包
bash 复制代码
jpackage \
  --input target \
  --name MySpringBootApp \
  --main-jar my-app-1.0.0.jar \
  --main-class org.springframework.boot.loader.JarLauncher \
  --type msi \
  --runtime-image custom-jre \
  --app-version 1.0.0 \
  --vendor "我的公司"

注意:Spring Boot 应用通常依赖较多模块,建议先不裁剪 JRE,确保功能正常后再优化。


五、不同平台的打包示例

5.1 Windows 平台(MSI)

bash 复制代码
jpackage \
  --input target \
  --name MyApp \
  --main-jar my-app-1.0.0.jar \
  --main-class org.springframework.boot.loader.JarLauncher \
  --type msi \
  --app-version 1.0.0 \
  --icon src/main/resources/app.ico \
  --win-dir-chooser \
  --win-menu \
  --win-shortcut \
  --win-menu-group "我的应用"

5.2 macOS 平台(DMG)

bash 复制代码
jpackage \
  --input target \
  --name MyApp \
  --main-jar my-app-1.0.0.jar \
  --main-class org.springframework.boot.loader.JarLauncher \
  --type dmg \
  --app-version 1.0.0 \
  --icon src/main/resources/app.icns \
  --mac-package-name "com.mycompany.myapp" \
  --mac-package-identifier "com.mycompany.myapp"

5.3 Linux 平台(DEB)

bash 复制代码
jpackage \
  --input target \
  --name myapp \
  --main-jar my-app-1.0.0.jar \
  --main-class org.springframework.boot.loader.JarLauncher \
  --type deb \
  --app-version 1.0.0 \
  --icon src/main/resources/app.png \
  --linux-shortcut \
  --linux-menu-group "Development"

六、集成到 Maven 构建流程

为了自动化打包流程,可以将 JPackage 命令集成到 Maven 的 pom.xml 中。

6.1 使用 exec-maven-plugin

pom.xml 中添加以下插件配置:

xml 复制代码
<build>
    <plugins>
        <!-- Spring Boot Maven 插件 -->
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>

        <!-- JPackage 打包插件 -->
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <version>3.1.0</version>
            <executions>
                <execution>
                    <id>jpackage</id>
                    <phase>package</phase>
                    <goals>
                        <goal>exec</goal>
                    </goals>
                    <configuration>
                        <executable>jpackage</executable>
                        <arguments>
                            <argument>--input</argument>
                            <argument>target</argument>
                            <argument>--name</argument>
                            <argument>MySpringBootApp</argument>
                            <argument>--main-jar</argument>
                            <argument>${project.build.finalName}.jar</argument>
                            <argument>--main-class</argument>
                            <argument>org.springframework.boot.loader.JarLauncher</argument>
                            <argument>--type</argument>
                            <argument>msi</argument>
                            <argument>--app-version</argument>
                            <argument>${project.version}</argument>
                            <argument>--vendor</argument>
                            <argument>我的公司</argument>
                            <argument>--win-dir-chooser</argument>
                            <argument>--win-menu</argument>
                            <argument>--win-shortcut</argument>
                        </arguments>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

6.2 执行构建

bash 复制代码
mvn clean package

构建完成后,安装包将生成在项目根目录下。

七、总结

JPackage 工具为 Java 应用的分发提供了强大的支持,从简单的命令行操作到集成到自动化构建流程,JPackage 都能很好地满足需求。

在实际项目中,建议根据应用特点选择合适的打包策略,平衡安装包体积、部署便利性和运行性能,为用户提供最佳的使用体验。

相关推荐
木辰風5 小时前
PLSQL自定义自动替换(AutoReplace)
java·数据库·sql
heartbeat..5 小时前
Redis 中的锁:核心实现、类型与最佳实践
java·数据库·redis·缓存·并发
5 小时前
java关于内部类
java·开发语言
好好沉淀5 小时前
Java 项目中的 .idea 与 target 文件夹
java·开发语言·intellij-idea
gusijin5 小时前
解决idea启动报错java: OutOfMemoryError: insufficient memory
java·ide·intellij-idea
To Be Clean Coder5 小时前
【Spring源码】createBean如何寻找构造器(二)——单参数构造器的场景
java·后端·spring
吨~吨~吨~5 小时前
解决 IntelliJ IDEA 运行时“命令行过长”问题:使用 JAR
java·ide·intellij-idea
你才是臭弟弟5 小时前
SpringBoot 集成MinIo(根据上传文件.后缀自动归类)
java·spring boot·后端
短剑重铸之日5 小时前
《设计模式》第二篇:单例模式
java·单例模式·设计模式·懒汉式·恶汉式
码农水水5 小时前
得物Java面试被问:消息队列的死信队列和重试机制
java·开发语言·jvm·数据结构·机器学习·面试·职场和发展