Quarkus 中文参考指南

学习如何创建 Hello World Quarkus 应用程序。本指南介绍:

Learn how to create a Hello World Quarkus app. This guide covers:

  • Bootstrapping an application

  • Creating a Jakarta REST endpoint

  • Injecting beans

  • Functional tests

  • Packaging of the application

Prerequisites

Unresolved directive in getting-started.adoc - include::{includes}/prerequisites.adoc[]

Verify Maven is using the Java you expect

如果你安装了多个 JDK,则不确定 Maven 是否会选择预期的 Java,你可能会得到意外的结果。你可以通过运行 `mvn --version`验证 Maven 使用哪个 JDK。

If you have multiple JDK’s installed, it is not certain Maven will pick up the expected java and you could end up with unexpected results. You can verify which JDK Maven uses by running mvn --version.

Architecture

在本指南中,我们将创建一个直接服务的应用程序 `hello`端口。为了演示依赖注入,此端口使用了一个 `greeting`bean。

In this guide, we create a straightforward application serving a hello endpoint. To demonstrate dependency injection, this endpoint uses a greeting bean.

getting started architecture

本指南还介绍了端口测试。

This guide also covers the testing of the endpoint.

Solution

我们建议你按照 Bootstrapping the project以下的说明逐步创建该应用程序。

We recommend that you follow the instructions from bootstrapping-the-project and onwards to create the application step by step.

但是,你可以直接转到已完成的示例。

However, you can go right to the completed example.

下载 {quickstarts-archive-url}[归档] 或克隆 git 存储库:

Download an {quickstarts-archive-url}[archive] or clone the git repository:

git clone {quickstarts-clone-url}

解决方案位于 getting-started directory

The solution is located in the getting-started directory.

Bootstrapping the project

创建新 Quarkus 项目的最简单方法是打开一个终端并运行以下命令:

The easiest way to create a new Quarkus project is to open a terminal and run the following command:

Unresolved directive in getting-started.adoc - include::{includes}/devtools/create-app.adoc[]

它在 `./getting-started`中生成以下内容:

It generates the following in ./getting-started:

  • the Maven structure

  • an org.acme.GreetingResource resource exposed on /hello

  • an associated unit test

  • a landing page that is accessible on http://localhost:8080 after starting the application

  • example Dockerfile files for both native and jvm modes in src/main/docker

  • the application configuration file

一旦生成,查看 pom.xml。你会发现 Quarkus BOM 的导入,允许你省略 Quarkus 不同依赖的版本。此外,你可以看到 quarkus-maven-plugin,它负责应用程序的封装,并且也会提供开发模式。

Once generated, look at the pom.xml. You will find the import of the Quarkus BOM, allowing you to omit the version of the different Quarkus dependencies. In addition, you can see the quarkus-maven-plugin responsible of the packaging of the application and also providing the development mode.

<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 项目中,你会发现类似的设置:

In a Gradle project, you would find a similar setup:

  • the Quarkus Gradle plugin

  • an enforcedPlatform directive for the Quarkus BOM

如果我们关注依赖部分,你会看到允许开发 REST 应用程序的扩展:

If we focus on the dependencies section, you can see the extension allowing the development of REST applications:

pom.xml
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-rest</artifactId>
</dependency>
build.gradle
implementation("io.quarkus:quarkus-rest")

The Jakarta REST resources

在项目创建过程中,已经创建了 `src/main/java/org/acme/GreetingResource.java`文件,内容如下:

During the project creation, the src/main/java/org/acme/GreetingResource.java file has been created with the following content:

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"。

It’s a very simple REST endpoint, returning "Hello from Quarkus REST" to requests on "/hello".

Differences with vanilla Jakarta REST

使用 Quarkus 时,不需要创建 Application`类。这是受支持的,但不是必需的。此外,只创建资源的一个实例,而不是每个请求一个。你可以使用不同的 `*Scoped`注释(`ApplicationScoped、`RequestScoped`等)对其进行配置。

With Quarkus, there is no need to create an Application class. It’s supported, but not required. In addition, only one instance of the resource is created and not one per request. You can configure this using the different *Scoped annotations (ApplicationScoped, RequestScoped, etc).

Running the application

现在,我们可以运行应用程序了:

Now we are ready to run our application:

Unresolved directive in getting-started.adoc - include::{includes}/devtools/dev.adoc[]

[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]

一旦启动,你可以请求提供的端点:

Once started, you can request the provided endpoint:

$ curl -w "\n" http://localhost:8080/hello
Hello from Quarkus REST

按 `CTRL+C`停止应用程序,或者保持其运行并享受闪电般的热重新加载。

Hit CTRL+C to stop the application, or keep it running and enjoy the blazing fast hot-reload.

Automatically add newline with curl -w "\n"

我们在本例中使用 `curl -w "\n"`是为了避免你的终端打印一个 '%' 或把结果和下一个命令提示放在同一行。

We are using curl -w "\n" in this example to avoid your terminal printing a '%' or put both result and next command prompt on the same line.

Using injection

Quarkus 中的依赖注入基于 ArC,ArC 是一种基于 CDI 的依赖注入解决方案,专为 Quarkus 的架构定制。如果你不熟悉 CDI,我们建议你阅读 Introduction to CDI指南。

Dependency injection in Quarkus is based on ArC which is a CDI-based dependency injection solution tailored for Quarkus' architecture. If you’re new to CDI then we recommend you to read the Introduction to CDI guide.

Quarkus 仅实现了 CDI 特性的一部分,并附有非标准特性和特定 API,你可以在 Contexts and Dependency Injection guide中了解更多关于它的信息。

Quarkus only implements a subset of the CDI features and comes with non-standard features and specific APIS, you can learn more about it in the Contexts and Dependency Injection guide.

ArC 作为 quarkus-rest 的依赖项附带提供,所以你已经手边有它了。

ArC comes as a dependency of quarkus-rest so you already have it handy.

让我们修改应用程序并添加一个伴随 Bean。使用以下内容创建 `src/main/java/org/acme/GreetingService.java`文件:

Let’s modify the application and add a companion bean. Create the src/main/java/org/acme/GreetingService.java file with the following content:

package org.acme;

import jakarta.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class GreetingService {

    public String greeting(String name) {
        return "hello " + name;
    }

}

编辑 `GreetingResource`类以注入 `GreetingService`并使用它创建一个新端点:

Edit the GreetingResource class to inject the GreetingService and create a new endpoint using it:

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";
    }
}

如果你停止了应用程序(记住你不需要这样做,更改将由我们的实时重新加载特性自动部署),请使用以下命令重新启动应用程序:

If you stopped the application (keep in mind you don’t have to do it, changes will be automatically deployed by our live reload feature), restart the application with:

Unresolved directive in getting-started.adoc - include::{includes}/devtools/dev.adoc[]

然后检查端点是否如预期的那样返回 hello quarkus

Then check that the endpoint returns hello quarkus as expected:

$ curl -w "\n" http://localhost:8080/hello/greeting/quarkus
hello quarkus

Development Mode

`quarkus:dev`在开发模式下运行 Quarkus。这使能了具有后台编译的实时重新加载,这意味着当你修改 Java 文件和/或资源文件并在浏览器中刷新时,这些更改将自动生效。这对资源文件(如配置属性文件)也适用。刷新浏览器将触发对工作区的扫描,并且如果检测到任何更改,Java 文件将重新编译,应用程序将重新部署;然后通过重新部署的应用程序来处理你的请求。如果编译或部署有任何问题,错误页面将通知你。

quarkus:dev runs Quarkus in development mode. This enables live reload with background compilation, which means that when you modify your Java files and/or your resource files and refresh your browser, these changes will automatically take effect. This works too for resource files like the configuration property file. Refreshing the browser triggers a scan of the workspace, and if any changes are detected, the Java files are recompiled and the application is redeployed; your request is then serviced by the redeployed application. If there are any issues with compilation or deployment an error page will let you know.

这还会在端口 5005`上侦听调试器。如果你希望在运行之前等待调试器附加,可以在命令行上传递 `-Dsuspend。如果你根本不需要调试器,可以`-Ddebug=false`。

This will also listen for a debugger on port 5005. If you want to wait for the debugger to attach before running you can pass -Dsuspend on the command line. If you don’t want the debugger at all you can use -Ddebug=false.

Testing

好的,到目前为止一切顺利,但是万一进行一些测试岂不是更好?

All right, so far so good, but wouldn’t it be better with a few tests, just in case.

在生成的构建文件中,你可以看到 2 个测试依赖:

In the generated build file, you can see 2 test dependencies:

pom.xml
<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>
build.gradle
testImplementation("io.quarkus:quarkus-junit5")
testImplementation("io.rest-assured:rest-assured")

Quarkus 支持 JUnit 5 测试。

Quarkus supports JUnit 5 tests.

因此,对于 Maven,必须设置 Surefire Maven Plugin 的版本,因为默认版本不支持 JUnit 5:

Because of this, in the case of Maven, the version of the Surefire Maven Plugin must be set, as the default version does not support 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 的自定义配置(如果有)。

We also set the java.util.logging system property to make sure tests will use the correct log manager and maven.home to ensure that custom configuration from ${maven.home}/conf/settings.xml is applied (if any).

生成的项目包含一个简单的测试。编辑 src/test/java/org/acme/GreetingResourceTest.java 以匹配以下内容:

The generated project contains a simple test. Edit the src/test/java/org/acme/GreetingResourceTest.java to match the following content:

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 By using the QuarkusTest runner, you instruct JUnit to start the application before the tests.
2 Check the HTTP response status code and content

这些测试使用 RestAssured,但请随意使用您最喜欢的库。

These tests use RestAssured, but feel free to use your favorite library.

您可以使用 Maven 运行它们:

You can run these using Maven:

./mvnw test

您还可以直接从 IDE 运行测试(请确保您先停止该应用程序)。

You can also run the test from your IDE directly (be sure you stopped the application first).

默认情况下,测试将在端口 8081 上运行,以避免与正在运行的应用程序冲突。我们会自动配置 RestAssured 使用此端口。如果您想使用不同的客户端,则应使用 @TestHTTPResource`注释将被测试应用程序的 URL 直接注入测试类的字段中。此字段可以是 `StringURLURI 类型。还可以为此注释提供测试路径的值。例如,如果我想测试映射到 /myservlet 的 Servlet,我会将其添加到我的测试中:

By default, tests will run on port 8081 so as not to conflict with the running application. We automatically configure RestAssured to use this port. If you want to use a different client you should use the @TestHTTPResource annotation to directly inject the URL of the tested application into a field on the test class. This field can be of the type String, URL or URI. This annotation can also be given a value for the test path. For example, if I want to test a Servlet mapped to /myservlet I would just add the following to my test:

@TestHTTPResource("/myservlet")
URL testUrl;

测试端口可以通过 quarkus.http.test-port 配置属性进行控制。Quarkus 还会创建一个系统属性,称为 test.url,该属性被设置为在无法使用注入的情况下的基本测试 URL。

The test port can be controlled via the quarkus.http.test-port config property. Quarkus also creates a system property called test.url that is set to the base test URL for situations where you cannot use injection.

Working with multi-module project or external modules

Quarkus 在构建时大量使用 Jandex,以发现各种类或注释。一个直接可以识别的应用程序就是 CDI Bean 发现。因此,如果此构建时发现未正确设置,则大多数 Quarkus 扩展将无法正常工作。

Quarkus heavily utilizes Jandex at build time, to discover various classes or annotations. One immediately recognizable application of this, is CDI bean discovery. As a result, most of the Quarkus extensions will not work properly if this build time discovery isn’t properly setup.

此索引在为其配置 Quarkus 的项目上默认创建,得益于我们的 Maven 和 Gradle 插件。

This index is created by default on the project on which Quarkus is configured for, thanks to our Maven and Gradle plugins.

但是,在使用多模块项目时,请务必阅读 Working with multi-module projects 部分或 MavenGradle 指南。

However, when working with a multi-module project, be sure to read the Working with multi-module projects section of the Maven or Gradle guides.

如果您计划使用外部模块(例如,用于所有域对象的外部库),则需要通过添加 Jandex 插件(如果您能修改)或通过 quarkus.index-dependency 了解这些模块索引过程属性在您的 application.properties 中(在无法修改模块的情况下有用)。

If you plan to use external modules (for example, an external library for all your domain objects), you will need to make these modules known to the indexing process either by adding the Jandex plugin (if you can modify them) or via the quarkus.index-dependency property inside your application.properties (useful in cases where you can’t modify the module).

请务必阅读 CDI 指南的 Bean Discovery 部分以获取更多信息。

Be sure to read the Bean Discovery section of the CDI guide for more information.

Packaging and run the application

应用程序使用以下内容打包:

The application is packaged using:

Unresolved directive in getting-started.adoc - include::{includes}/devtools/build.adoc[]

它在 /target 中生成多个输出:

It produces several outputs in /target:

  • getting-started-1.0.0-SNAPSHOT.jar - containing just the classes and resources of the projects, it’s the regular artifact produced by the Maven build - it is not the runnable jar;

  • the quarkus-app directory which contains the quarkus-run.jar jar file - being an executable jar. Be aware that it’s not an über-jar as the dependencies are copied into subdirectories of quarkus-app/lib/.

你可以使用以下命令运行应用程序: java -jar target/quarkus-app/quarkus-run.jar

You can run the application using: java -jar target/quarkus-app/quarkus-run.jar

如果你想在某个地方(通常在容器中)部署你的应用程序,则需要部署整个 quarkus-app 目录。

If you want to deploy your application somewhere (typically in a container), you need to deploy the whole quarkus-app directory.

在运行应用程序之前,请不要忘记停止热重载模式(点击 CTRL+C),否则你将遇到端口冲突。

Before running the application, don’t forget to stop the hot reload mode (hit CTRL+C), or you will have a port conflict.

默认情况下,当 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 来提供一个自定义标语。

By default, when a Quarkus application starts (in regular or dev mode), it will display an ASCII art banner. The banner can be disabled by setting quarkus.banner.enabled=false in application.properties, by setting the -Dquarkus.banner.enabled=false Java System Property, or by setting the QUARKUS_BANNER_ENABLED environment variable to false. Furthermore, users can supply a custom banner by placing the banner file in src/main/resources and configuring quarkus.banner.path=name-of-file in application.properties.

Non Application endpoints

不同的 Quarkus 扩展为不同的类型的应用程序信息提供非应用程序端点。此类扩展的示例是 healthmetricsOpenAPI 和信息扩展。

Various Quarkus extensions contribute non-application endpoints that provide different kinds of information about the application. Examples of such extensions are the health, metrics, OpenAPI and info extensions.

这些非应用程序端点通常可以在 /q 前缀下访问,如以下所示:

These non application endpoints are normally accessible under the /q prefix like so:

  • /q/health

  • /q/metrics

  • /q/openapi

  • /q/info

但是,用户还可以选择将可能存在安全风险的一个端点暴露在不同的 TCP 端口下,方法是使用一个专门的 management interface

but users can also choose to expose one that might present a security risk under a different TCP port using a dedicated management interface.

Info endpoint

如果应用程序包含 quarkus-info 扩展,则 Quarkus 默认情况下将公开 /q/info 端点,该端点提供有关构建、java 版本、版本控制和操作系统的的信息。公开信息的详细级别是可配置的。

If the application contains the quarkus-info extension, then Quarkus will by default expose the /q/info endpoint which provides information about the build, java version, version control, and operating system. The level of detail of the exposed information is configurable.

实现 InfoContributor 的所有 CDI bean 都将被选中,并且它们的数据将附加到端点。

All CDI beans implementing the InfoContributor will be picked up and their data will be appended to the endpoint.

Configuration Reference

Unresolved directive in getting-started.adoc - include::{generated-dir}/config/quarkus-info.adoc[]

What’s next?

本指南涵盖了使用 Quarkus 创建应用程序的过程。然而,还有更多。我们建议通过创建 your second Quarkus application、并使用 dev 服务和持久性来继续此旅程。你可以了解如何创建一个本机可执行文件并使用 building a native executable guide 将它打包到容器中。如果你对反应感兴趣,我们推荐 getting started with reactive guide,在这里你可以了解如何使用 Quarkus 实现响应式应用程序。

This guide covered the creation of an application using Quarkus. However, there is much more. We recommend continuing the journey by creating your second Quarkus application, with dev services and persistence. You can learn about creating a native executable and packaging it in a container with the building a native executable guide. If you are interested in reactive, we recommend the getting started with reactive guide, where you can see how to implement reactive applications with Quarkus.

此外,tooling guide 文档解释了如何:

In addition, the tooling guide document explains how to:

  • scaffold a project in a single command line

  • enable the development mode (hot reload)

  • import the project in your favorite IDE

  • and more