最近好几个团队从 Spring Boot 往 Quarkus 迁移,迁移过程中很少有人会在 Spring Boot 这边为 Maven 插件发愁,但换到 Quarkus 后问题全冒出来了:为什么 mvn package 打出来的东西在 target/quarkus-app,而不是一个干净的 jar?为什么 mvn quarkus:add-extension 非得让插件去改 pom?为什么 JVM 构建好好的,加个 -Pnative 就各种"反射找不到"?这些问题的答案其实都指向同一个东西——quarkus-maven-plugin 不是 Spring Boot 那种"顺便帮你打个可执行 jar"的辅助工具,它从项目创建、开发模式、代码生成、测试、打包到容器镜像构建,贯穿了整个生命周期。这篇文章就以 RESTful 服务项目和微服务项目为例,把插件的完整用法、目标命令和参数配置从头到尾捋一遍。
1. 先弄清插件的定位:它不是打包工具,是 Quarkus 的装配产线
1.1 为什么 Quarkus 敢把 "supersonic subatomic Java" 当口号
Quarkus 的核心思想是在构建期完成大部分本该在运行时做的工作。Spring Boot 项目启动时,组件扫描、反射元数据收集、配置绑定都由 Spring 容器在 JVM 里现做,启动慢、内存占用高;Quarkus 则把这些动作尽量前移到 Maven 构建阶段,编译时扫描类路径、生成字节码、把依赖注入关系静态化,甚至能在构建期直接把可选的 JVM 特征裁剪掉。
这套机制的执行载体就是 quarkus-maven-plugin。你以为你是用 Maven 打了个包,实际上你是在构建期触发了一次"装配",Quarkus 应用启动时要做的事早在打包那一刻就被安排好了。说得直白一点:Spring Boot 的插件更像"打包助手",而 Quarkus 的插件是应用的一部分。
理解了这一点,下面所有怪现象就都顺了:为什么原生镜像需要额外元数据?因为 GraalVM 在构建期需要知道哪些类会被反射调用,这些 reflect-config.json、resource-config.json 由插件的代码生成环节配合扩展生成;为什么不能随便往 pom 里塞一个没注册的依赖?因为插件如果不认识这个扩展,构建期就没人帮你做对应的元数据加工,服务起来行为自然不对。
1.2 插件提供的核心 goal 清单
quarkus-maven-plugin 暴露了一系列 Maven goal,下面这张表基本覆盖了日常使用频率最高的场景:
| 命令示例 | 对应 goal | 作用 |
|---|---|---|
mvn quarkus:create |
create |
创建新的 Quarkus 项目骨架 |
mvn quarkus:dev |
dev |
启动开发模式,支持热重载 |
mvn quarkus:add-extension |
add-extension |
向当前项目添加扩展 |
mvn quarkus:list-extensions |
list-extensions |
列出当前项目已装或可装的扩展 |
mvn quarkus:build |
build |
生产构建,默认绑定在 package 阶段 |
mvn quarkus:update |
update |
升级 Quarkus 平台版本 |
mvn quarkus:generate-code |
generate-code |
根据 proto/avro 等 schema 生成代码 |
quarkus:build 默认绑定到 Maven 的 package 阶段,所以你在生成的项目里直接执行 mvn clean package 就会触发它。generate-code 默认绑定在 generate-sources 阶段,像 gRPC 的 .proto 文件翻译成 Java 类,就是这一步干的。
1.3 项目 pom 里为什么要有那三行 executions
用 quarkus:create 生成的项目,pom 里会有这么一段:
xml复制<plugin>
<groupId>io.quarkus.platform</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<version>${quarkus.platform.version}</version>
<extensions>true</extensions>
<executions>
<execution>
<goals>
<goal>build</goal>
<goal>generate-code</goal>
<goal>generate-code-tests</goal>
</goals>
</execution>
</executions>
</plugin>
<extensions>true</extensions> 很容易被忽略,但非常关键。它让插件有机会向 Maven 注册自己的构建扩展,否则部分代码生成和资源处理逻辑就不会生效。如果你把这个配置删了,很多项目表面上还能 mvn package
