Appearance
Spring Boot Maven Plugin 打包可执行归档文件详解 📦
概述
Spring Boot Maven Plugin 的核心功能之一就是创建可执行的归档文件(JAR 或 WAR),这些文件包含了应用程序的所有依赖,可以通过 java -jar
命令直接运行。这个功能解决了传统 Java 应用部署时需要单独管理依赖的痛点。
IMPORTANT
可执行归档文件是 Spring Boot 应用部署的核心特性,它将应用程序及其所有依赖打包成一个独立的文件,极大简化了部署过程。
为什么需要可执行归档文件? 🤔
在传统的 Java 应用开发中,我们面临以下痛点:
bash
# 需要手动管理 classpath
java -cp "lib/*:app.jar" com.example.Application
# 部署时需要确保所有依赖都在正确位置
├── app.jar
├── lib/
│ ├── spring-core-5.3.21.jar
│ ├── spring-boot-2.7.0.jar
│ └── ... (数十个依赖文件)
bash
# 一个命令搞定
java -jar my-app.jar
# 部署时只需要一个文件
└── my-app.jar (包含所有依赖)
基本配置与使用
1. 基础配置
xml
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
TIP
如果你使用 spring-boot-starter-parent
,上述配置已经预配置好了,你只需要添加插件定义即可。
2. 执行打包
bash
# 正确的执行方式
mvn package spring-boot:repackage
# 或者直接使用(如果使用了 starter-parent)
mvn package
WARNING
repackage
目标不能单独在命令行使用,它需要操作 package
阶段生成的源 JAR 文件。
可执行归档文件的内部结构 🏗️
让我们通过一个实际的 Kotlin Spring Boot 项目来理解可执行 JAR 的结构:
kotlin
package com.example.demo
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
@SpringBootApplication
class DemoApplication
fun main(args: Array<String>) {
runApplication<DemoApplication>(*args)
}
kotlin
package com.example.demo.controller
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RestController
@RestController
class HelloController {
@GetMapping("/hello")
fun hello(): String {
return "Hello from Spring Boot!"
}
}
打包后的 JAR 文件结构:
my-app.jar
├── META-INF/
│ └── MANIFEST.MF # 包含 Main-Class 和 Start-Class
├── BOOT-INF/
│ ├── classes/ # 应用程序类文件
│ │ └── com/example/demo/
│ │ ├── DemoApplication.class
│ │ └── controller/
│ │ └── HelloController.class
│ ├── lib/ # 所有依赖 JAR 文件
│ │ ├── spring-boot-3.2.0.jar
│ │ ├── spring-core-6.1.0.jar
│ │ └── ... (其他依赖)
│ └── layers.idx # 分层信息(可选)
└── org/springframework/boot/loader/ # Spring Boot 加载器
分层 JAR/WAR 🎯
分层归档是 Spring Boot 的一个重要特性,特别适用于 Docker 镜像构建场景。
默认分层策略
NOTE
分层的顺序很重要:变化频率低的层应该放在前面,这样在 Docker 构建时可以更好地利用缓存。
自定义分层配置
点击查看完整的分层配置示例
xml
<!-- pom.xml 中的配置 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<layers>
<enabled>true</enabled>
<configuration>${project.basedir}/src/layers.xml</configuration>
</layers>
</configuration>
</plugin>
xml
<!-- src/layers.xml -->
<layers xmlns="http://www.springframework.org/schema/boot/layers"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/boot/layers
https://www.springframework.org/schema/boot/layers/layers-3.5.xsd">
<application>
<into layer="spring-boot-loader">
<include>org/springframework/boot/loader/**</include>
</into>
<into layer="application" />
</application>
<dependencies>
<into layer="application">
<includeModuleDependencies />
</into>
<into layer="snapshot-dependencies">
<include>*:*:*SNAPSHOT</include>
</into>
<into layer="company-dependencies">
<include>com.example:*</include>
</into>
<into layer="dependencies" />
</dependencies>
<layerOrder>
<layer>dependencies</layer>
<layer>spring-boot-loader</layer>
<layer>snapshot-dependencies</layer>
<layer>company-dependencies</layer>
<layer>application</layer>
</layerOrder>
</layers>
实际应用场景示例 💼
场景 1:微服务架构中的服务模块
kotlin
// 用户服务
@SpringBootApplication
class UserServiceApplication
@RestController
class UserController {
@GetMapping("/users/{id}")
fun getUser(@PathVariable id: Long): User {
// 业务逻辑
return userService.findById(id)
}
}
xml
<!-- 配置为可执行 JAR -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.example.user.UserServiceApplication</mainClass>
</configuration>
</plugin>
场景 2:作为依赖模块的库项目
当你的模块需要被其他项目依赖时,应该使用自定义分类器:
xml
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<classifier>exec</classifier>
</configuration>
</execution>
</executions>
</plugin>
这样会生成两个文件:
my-library-1.0.jar
- 普通 JAR,可作为依赖使用my-library-1.0-exec.jar
- 可执行 JAR
场景 3:排除特定依赖
在某些情况下,你可能需要排除一些不必要的依赖:
xml
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
常见配置选项详解 ⚙️
1. 布局类型 (Layout)
布局类型 | 描述 | 适用场景 |
---|---|---|
JAR | 标准可执行 JAR 布局 | 大多数 Spring Boot 应用 |
WAR | 可执行 WAR 布局 | 需要部署到 Servlet 容器的应用 |
ZIP | 使用 PropertiesLauncher | 需要外部配置的应用 |
NONE | 仅打包依赖,不包含启动器 | 特殊用途的库项目 |
2. 重要参数说明
核心参数
mainClass
: 指定主类,如果不指定会自动查找包含main
方法的类classifier
: 为重新打包的归档文件添加分类器excludeDevtools
: 默认为true
,排除开发工具executable
: 创建完全可执行的 JAR(适用于 Unix 系统)
最佳实践建议 🌟
1. 项目结构建议
kotlin
src/
├── main/
│ ├── kotlin/
│ │ └── com/example/
│ │ ├── Application.kt # 主启动类
│ │ ├── config/ # 配置类
│ │ ├── controller/ # 控制器
│ │ ├── service/ # 服务层
│ │ └── repository/ # 数据访问层
│ └── resources/
│ ├── application.yml # 应用配置
│ └── static/ # 静态资源
└── test/
2. 配置模板
xml
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<!-- 基础配置 -->
<mainClass>${start.class}</mainClass>
<!-- 分层配置 -->
<layers>
<enabled>true</enabled>
</layers>
<!-- 排除开发依赖 -->
<excludeDevtools>true</excludeDevtools>
<excludeDockerCompose>true</excludeDockerCompose>
<!-- 自定义排除 -->
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
常见问题与解决方案 🔧
问题 1: 找不到主类
bash
# 错误信息
no main manifest attribute, in my-app.jar
解决方案:
xml
<configuration>
<mainClass>com.example.Application</mainClass>
</configuration>
问题 2: 依赖冲突
bash
# 错误信息
java.lang.NoSuchMethodError: ...
解决方案:
xml
<configuration>
<excludes>
<exclude>
<groupId>conflicting.group</groupId>
<artifactId>conflicting-artifact</artifactId>
</exclude>
</excludes>
</configuration>
总结 📝
Spring Boot Maven Plugin 的 repackage
功能是现代 Java 应用部署的核心工具:
✅ 优势:
- 简化部署流程,一个文件包含所有依赖
- 支持分层架构,优化 Docker 镜像构建
- 灵活的配置选项,适应不同场景需求
- 自动处理类路径和启动逻辑
✅ 适用场景:
- 微服务架构的独立服务
- 容器化部署的应用
- 需要简化部署的企业应用
- 云原生应用开发
通过合理配置 Spring Boot Maven Plugin,你可以轻松创建高效、可维护的可执行归档文件,大大简化应用的构建和部署过程。 🚀