Quarkus 中文参考指南
学习如何创建 Hello World Quarkus 应用程序。本指南介绍:
-
Bootstrapping an application
-
创建 Jakarta REST 端口
-
Injecting beans
-
Functional tests
-
Packaging of the application
Prerequisites
如要完成本指南,您需要:
-
Roughly 15 minutes
-
An IDE
-
安装了 JDK 17+,已正确配置
JAVA_HOME
-
Apache Maven ${proposed-maven-version}
-
如果你想使用 Quarkus CLI, 则可以选择使用
-
如果你想构建一个本机可执行文件(或如果你使用本机容器构建,则使用 Docker),则可以选择安装 Mandrel 或 GraalVM 以及 configured appropriately
Verify Maven is using the Java you expect
如果你安装了多个 JDK,则不确定 Maven 是否会选择预期的 Java,你可能会得到意外的结果。你可以通过运行 `mvn --version`验证 Maven 使用哪个 JDK。 |
Solution
我们建议你按照 Bootstrapping the project以下的说明逐步创建该应用程序。
但是,你可以直接转到已完成的示例。
下载 $${quickstarts-base-url}/archive/main.zip[归档] 或克隆 git 存储库:
git clone {quickstarts-clone-url}
解决方案位于 getting-started
directory。
Bootstrapping the project
创建新 Quarkus 项目的最简单方法是打开一个终端并运行以下命令:
quarkus create app {create-app-group-id}:{create-app-artifact-id} \
--no-code
cd {create-app-artifact-id}
要创建一个 Gradle 项目,添加 --gradle
或 --gradle-kotlin-dsl
选项。
有关如何安装和使用 Quarkus CLI 的详细信息,请参见 Quarkus CLI 指南。
mvn {quarkus-platform-groupid}:quarkus-maven-plugin:{quarkus-version}:create \
-DprojectGroupId={create-app-group-id} \
-DprojectArtifactId={create-app-artifact-id} \
-DnoCode
cd {create-app-artifact-id}
要创建一个 Gradle 项目,添加 -DbuildTool=gradle
或 -DbuildTool=gradle-kotlin-dsl
选项。
适用于 Windows 用户:
-
如果使用 cmd,(不要使用反斜杠
\
,并将所有内容放在同一行上) -
如果使用 Powershell,将
-D
参数用双引号引起来,例如"-DprojectArtifactId={create-app-artifact-id}"
它在 `./getting-started`中生成以下内容:
-
the Maven structure
-
公开于 `/hello`上的 `org.acme.GreetingResource`资源
-
an associated unit test
-
启动应用程序后可以在 `http://localhost:8080`访问的登录页面
-
在 `src/main/docker`中针对 `native`和 `jvm`模式的 `Dockerfile`文件示例
-
the application configuration file
一旦生成,查看 pom.xml
。你会发现 Quarkus BOM 的导入,允许你省略 Quarkus 不同依赖的版本。此外,你可以看到 quarkus-maven-plugin
,它负责应用程序的封装,并且也会提供开发模式。
<dependencyManagement>
<dependencies>
<dependency>
<groupId>${quarkus.platform.group-id}</groupId>
<artifactId>${quarkus.platform.artifact-id}</artifactId>
<version>${quarkus.platform.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>${quarkus.platform.group-id}</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>
</plugins>
</build>
在 Gradle 项目中,你会发现类似的设置:
-
the Quarkus Gradle plugin
-
用于 Quarkus BOM 的 `enforcedPlatform`指令
如果我们关注依赖部分,你会看到允许开发 REST 应用程序的扩展:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest</artifactId>
</dependency>
implementation("io.quarkus:quarkus-rest")
The Jakarta REST resources
在项目创建过程中,已经创建了 `src/main/java/org/acme/GreetingResource.java`文件,内容如下:
package org.acme;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
@Path("/hello")
public class GreetingResource {
@GET
@Produces(MediaType.TEXT_PLAIN)
public String hello() {
return "Hello from Quarkus REST";
}
}
这是一个非常简单的 REST 端点,对 "/hello" 上的请求返回 "Hello from Quarkus REST"。
Differences with vanilla Jakarta REST
使用 Quarkus 时,不需要创建 |
Running the application
现在,我们可以运行应用程序了:
quarkus dev
./mvnw quarkus:dev
./gradlew --console=plain quarkusDev
[INFO] --------------------< org.acme:getting-started >---------------------
[INFO] Building getting-started 1.0.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ getting-started ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory <path>/getting-started/src/main/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ getting-started ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 2 source files to <path>/getting-started/target/classes
[INFO]
[INFO] --- quarkus-maven-plugin:<version>:dev (default-cli) @ getting-started ---
Listening for transport dt_socket at address: 5005
2019-02-28 17:05:22,347 INFO [io.qua.dep.QuarkusAugmentor] (main) Beginning quarkus augmentation
2019-02-28 17:05:22,635 INFO [io.qua.dep.QuarkusAugmentor] (main) Quarkus augmentation completed in 288ms
2019-02-28 17:05:22,770 INFO [io.quarkus] (main) Quarkus started in 0.668s. Listening on: http://localhost:8080
2019-02-28 17:05:22,771 INFO [io.quarkus] (main) Installed features: [cdi, rest]
一旦启动,你可以请求提供的端点:
$ curl -w "\n" http://localhost:8080/hello
Hello from Quarkus REST
按 `CTRL+C`停止应用程序,或者保持其运行并享受闪电般的热重新加载。
Automatically add newline with
curl -w "\n" 我们在本例中使用 `curl -w "\n"`是为了避免你的终端打印一个 '%' 或把结果和下一个命令提示放在同一行。 |
Using injection
Quarkus 中的依赖注入基于 ArC,ArC 是一种基于 CDI 的依赖注入解决方案,专为 Quarkus 的架构定制。如果你不熟悉 CDI,我们建议你阅读 Introduction to CDI指南。
Quarkus 仅实现了 CDI 特性的一部分,并附有非标准特性和特定 API,你可以在 Contexts and Dependency Injection guide中了解更多关于它的信息。
ArC 作为 quarkus-rest
的依赖项附带提供,所以你已经手边有它了。
让我们修改应用程序并添加一个伴随 Bean。使用以下内容创建 `src/main/java/org/acme/GreetingService.java`文件:
package org.acme;
import jakarta.enterprise.context.ApplicationScoped;
@ApplicationScoped
public class GreetingService {
public String greeting(String name) {
return "hello " + name;
}
}
编辑 `GreetingResource`类以注入 `GreetingService`并使用它创建一个新端点:
package org.acme;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
@Path("/hello")
public class GreetingResource {
@Inject
GreetingService service;
@GET
@Produces(MediaType.TEXT_PLAIN)
@Path("/greeting/{name}")
public String greeting(String name) {
return service.greeting(name);
}
@GET
@Produces(MediaType.TEXT_PLAIN)
public String hello() {
return "Hello from Quarkus REST";
}
}
如果你停止了应用程序(记住你不需要这样做,更改将由我们的实时重新加载特性自动部署),请使用以下命令重新启动应用程序:
quarkus dev
./mvnw quarkus:dev
./gradlew --console=plain quarkusDev
然后检查端点是否如预期的那样返回 hello quarkus
:
$ curl -w "\n" http://localhost:8080/hello/greeting/quarkus
hello quarkus
Development Mode
`quarkus:dev`在开发模式下运行 Quarkus。这使能了具有后台编译的实时重新加载,这意味着当你修改 Java 文件和/或资源文件并在浏览器中刷新时,这些更改将自动生效。这对资源文件(如配置属性文件)也适用。刷新浏览器将触发对工作区的扫描,并且如果检测到任何更改,Java 文件将重新编译,应用程序将重新部署;然后通过重新部署的应用程序来处理你的请求。如果编译或部署有任何问题,错误页面将通知你。
这还会在端口 5005`上侦听调试器。如果你希望在运行之前等待调试器附加,可以在命令行上传递 `-Dsuspend
。如果你根本不需要调试器,可以`-Ddebug=false`。
Testing
好的,到目前为止一切顺利,但是万一进行一些测试岂不是更好?
在生成的构建文件中,你可以看到 2 个测试依赖:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
testImplementation("io.quarkus:quarkus-junit5")
testImplementation("io.rest-assured:rest-assured")
Quarkus 支持 JUnit 5 测试。
因此,对于 Maven,必须设置 Surefire Maven Plugin 的版本,因为默认版本不支持 JUnit 5:
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire-plugin.version}</version>
<configuration>
<systemPropertyVariables>
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
<maven.home>${maven.home}</maven.home>
</systemPropertyVariables>
</configuration>
</plugin>
我们还设置了 java.util.logging
系统属性,以确保测试将使用正确的日志管理器和 maven.home
,以确保应用 ${maven.home}/conf/settings.xml
的自定义配置(如果有)。
生成的项目包含一个简单的测试。编辑 src/test/java/org/acme/GreetingResourceTest.java
以匹配以下内容:
package org.acme;
import io.quarkus.test.junit.QuarkusTest;
import org.junit.jupiter.api.Test;
import java.util.UUID;
import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.is;
@QuarkusTest
public class GreetingResourceTest {
@Test (1)
public void testHelloEndpoint() {
given()
.when().get("/hello")
.then()
.statusCode(200) (2)
.body(is("Hello from Quarkus REST"));
}
@Test
public void testGreetingEndpoint() {
String uuid = UUID.randomUUID().toString();
given()
.pathParam("name", uuid)
.when().get("/hello/greeting/{name}")
.then()
.statusCode(200)
.body(is("hello " + uuid));
}
}
1 | 通过使用 QuarkusTest 运行程序,您可以指示 JUnit 在测试之前启动应用程序。 |
2 | 检查 HTTP 响应状态代码和内容 |
这些测试使用 RestAssured,但请随意使用您最喜欢的库。
您可以使用 Maven 运行它们:
./mvnw test
您还可以直接从 IDE 运行测试(请确保您先停止该应用程序)。
默认情况下,测试将在端口 8081
上运行,以避免与正在运行的应用程序冲突。我们会自动配置 RestAssured 使用此端口。如果您想使用不同的客户端,则应使用 @TestHTTPResource`注释将被测试应用程序的 URL 直接注入测试类的字段中。此字段可以是 `String
、URL
或 URI
类型。还可以为此注释提供测试路径的值。例如,如果我想测试映射到 /myservlet
的 Servlet,我会将其添加到我的测试中:
@TestHTTPResource("/myservlet")
URL testUrl;
测试端口可以通过 quarkus.http.test-port
配置属性进行控制。Quarkus 还会创建一个系统属性,称为 test.url
,该属性被设置为在无法使用注入的情况下的基本测试 URL。
Working with multi-module project or external modules
Quarkus 在构建时大量使用 Jandex,以发现各种类或注释。一个直接可以识别的应用程序就是 CDI Bean 发现。因此,如果此构建时发现未正确设置,则大多数 Quarkus 扩展将无法正常工作。
此索引在为其配置 Quarkus 的项目上默认创建,得益于我们的 Maven 和 Gradle 插件。
如果您计划使用外部模块(例如,用于所有域对象的外部库),则需要通过添加 Jandex 插件(如果您能修改)或通过 quarkus.index-dependency
了解这些模块索引过程属性在您的 application.properties
中(在无法修改模块的情况下有用)。
请务必阅读 CDI 指南的 Bean Discovery 部分以获取更多信息。
Packaging and run the application
应用程序使用以下内容打包:
quarkus build
./mvnw install
./gradlew build
它在 /target
中生成多个输出:
-
getting-started-1.0.0-SNAPSHOT.jar
- 仅包含项目的类和资源,这是 Maven 构建产生的常规工件 - 它是 not 可运行 jar; -
包含
quarkus-run.jar
jar 文件的quarkus-app
目录——是一个可执行 jar。请注意,它不是一个 über-jar,因为依赖项已复制到quarkus-app/lib/
的子目录中。
你可以使用以下命令运行应用程序: java -jar target/quarkus-app/quarkus-run.jar
如果你想在某个地方(通常在容器中)部署你的应用程序,则需要部署整个 |
在运行应用程序之前,请不要忘记停止热重载模式(点击 |
Configuring the banner
默认情况下,当 Quarkus 应用程序启动(在常规或开发模式下)时,它将显示一个 ASCII 艺术标语。可以通过设置 application.properties
中的 quarkus.banner.enabled=false
,设置 -Dquarkus.banner.enabled=false
Java 系统属性,或设置 QUARKUS_BANNER_ENABLED
环境变量为 false
来禁用标语。此外,用户可以通过将标语文件放在 src/main/resources
中并在 application.properties
中配置 quarkus.banner.path=name-of-file
来提供一个自定义标语。
Non Application endpoints
这些非应用程序端点通常可以在 /q
前缀下访问,如以下所示:
-
/q/health
-
/q/metrics
-
/q/openapi
-
/q/info
但是,用户还可以选择将可能存在安全风险的一个端点暴露在不同的 TCP 端口下,方法是使用一个专门的 management interface。
What’s next?
本指南涵盖了使用 Quarkus 创建应用程序的过程。然而,还有更多。我们建议通过创建 your second Quarkus application、并使用 dev 服务和持久性来继续此旅程。你可以了解如何创建一个本机可执行文件并使用 building a native executable guide 将它打包到容器中。如果你对反应感兴趣,我们推荐 getting started with reactive guide,在这里你可以了解如何使用 Quarkus 实现响应式应用程序。
此外,tooling guide 文档解释了如何:
-
使用一条命令行来搭建一个项目
-
启用 development mode (热重载)
-
在你最喜欢的 IDE 中导入项目
-
and more