Creating a tutorial

创建一项新教程,指导用户创建、运行和测试 Quarkus 应用,该应用使用来自假想扩展名的注释。

Prerequisites

  • Roughly 15 minutes

  • 一个编辑器或 IDE,使用插件或本机方式提供 AsciiDoc 的语法高亮和预览。

  • 你必须熟悉“Tutorial”の概要。

  • 准备就绪的“Quarkus style and content guidelines”作为语法需求和其他惯例的参考。

Decide on a title and file name

  1. 为教程确定一个标题。对于这个工作示例,我们将使用“Serve Http requests using the Acme extension”。

  2. 确定一个文件名。对于这个示例,我们将使用“acme-serve-http-requests-tutorial.adoc”:

    • acme-”将此指南与 acme 扩展的其他资源归为一组

    • serve-http-requests”是文档标题的派生词

    • -tutorial”将表示此文档为教程(可选)

    • .adoc”表示这是一个 AsciiDoc 文件

Copy the tutorial template

从 Quarkus 存储库复制“docs/src/main/diataxis/_templates/template-tutorial.adoc”到名为“acme-serve-http-requests-tutorial.adoc”的新文件中。

Update the document header

[id="acme-serve-http-requests-tutorial"] (1)
= Serve Http requests using the Acme extension (2)
:iokays-category: quarkus
:iokays-path: modules/ROOT/pages/_attributes.adoc
:keywords: Quarkus, 中文文档, 编程技术, AsciiDoc,  adoc,  _attributes-local.adoc,  包含文件,  本地属性,  文档生成,  格式化,  文本处理,  文档结构,  AsciiDoc教程
:description: 学习如何在AsciiDoc中使用`include::_attributes-local.adoc[]`来管理和引用本地属性。本指南详细解释了其作用、用法及最佳实践,助你高效生成结构化文档。

:iokays-category: quarkus
:iokays-path: modules/ROOT/pages/_attributes-local.adoc
:iokays-category: quarkus
:iokays-path: modules/ROOT/pages/doc-create-tutorial.adoc (3)
:categories: web (4)
:extension-status: experimental (5)
<1>  将文件名用作该部分的唯一 ID。
<1>  将标题添加为顶级标题。
<1>  包括其他属性以协助定义一致的格式并提供源代码可移植性。
<1>  指定 “`web`”类别,因为我们的假想扩展名可与 Http 请求配合使用。
<1>  我们的假想 “`acme`”扩展名是试验性的,因此我们在标题中包括了扩展名状态声明。
Document Preview

文件的预览应包含所选标题作为一页顶部的一个样式标题。

Add an abstract

我们希望让我们的教程的读者知道,在按照教程中的步骤操作之后,他们将取得怎样的成果。摘要应简洁,并应使用适当的动词(创建、构建、部署……)来设定预期。读者应能够确定他们是否希望参与内容。

Create an application that uses unique annotations from the experimental acme extension to define two endpoints:
a simple HTTP endpoint and an endpoint that emits server-sent events (SSE).
We will also use Quarkus dev mode for iterative development and testing.
Document Preview

文件的预览应包含摘要,作为紧跟标题后的一个段落。

Include extension status descriptive text

acme`扩展是试验性的,我们会包含提供扩展状态文本的 `{includes}/extension-status.adoc。它使用标题中定义的扩展状态属性。

Unresolved directive in doc-create-tutorial.adoc - include::{includes}/extension-status.adoc[]
Document Preview

现在,文档的预览应包括摘要下方的警告框,说明该插件是实验性技术,并描述了对实验性技术的稳定性和支持方面的预期。

Define Prerequisites

我们需要告诉用户完成本教程所需的资源。

任何描述开发活动的教程都应使用 {includes}/prerequisites.adoc 来确保在描述先决条件时使用一致的语言。声明 prerequisites- 属性可以自定义最终文本。

== Prerequisites

:prerequisites-time: 30 minutes (1)
:prerequisites-docker: (2)
:prerequisites-no-graalvm: (3)
include::{includes}/prerequisites.adoc[] (4)

The `curl` command line utility is also used to manually test the endpoint.
<1>  声明我们的假设教程大约需要 30 分钟才能完成。
<1>  声明我们的荒谬 acme 扩展也需要一个容器运行时。
<1>  为了简化本教程,我们将避免 GraalVM 和 Mandrel 先决条件。
<1>  包含提供描述先决条件的文本的通用文件。
Document Preview

第二层 Prerequistes 标题应紧跟在文档预览中的扩展状态框之后。它应该说明:

  • 本教程大约需要 30 分钟

  • 您需要一个 IDE、JDK(带版本)、maven(占位符为 maven 版本)、一个正在工作的容器运行时和(可选)Quarkus CLI。

Describe the steps for completing the tutorial

此过程有几部分。只需记住,每一步都应以一个可理解/可观察的结果结束:“输出应类似于这样……”

Define the first step

在指定第一步的头之前启用节号。

:sectnums: (1)
:sectnumlevels: 3
== Create a new project (2)

Create a new project with the following command: (3)

:create-app-artifact-id: acme-quickstart (4)
:create-app-extensions: acme (5)
include::{includes}/devtools/create-app.adoc[] (6)
<1>  Enable section numbering
<1>  为第一步创建一个第二层标题
<1>  Describe the step briefly
<1>  定义装配件 ID(Maven 或 Gradle)
<1>  列出此项目所需的扩展
<1>  使用通用文本描述如何创建项目
Document Preview

文档预览现在应包含一个名为 1. Create a new project 的新部分,其中包含使用 Quarkus CLI 和 maven 创建新项目的步骤。

Using a source file

在本教程中,我们将使用标签包含来自单独 Java 文件的代码。

将此看作一个有抱负的示例。通常会将来源直接包含在源代码块中。虽然包含来自 Java 文件的来源存在优势,但有关引用代码应实现的细节还待解决。欢迎提供帮助和建议!

让我们创建一个名为 acme-serve-http-requests-MyAcmeApplication.java 的文件。虽然这不是一个有效的 Java 文件名,但它确实与我们的教程来源紧密相连。我们将依靠 IDE 的神奇功能进行语法检查。

让我们向文件添加以下代码:

// tag::application[]
package org.acme;

import jakarta.enterprise.context.ApplicationScoped;

import org.acme.corp.Anvil;
import org.acme.corp.Toaster;

import io.smallrye.mutiny.Multi;

@ApplicationScoped (1)
public class MyAcmeApplication {

    @Anvil(optional = {"name"}) (2)
    public String hello(String name) {
        return String.format("Hello, %s!", (name == null ? "World" : name));
    }

    // tag::goodbye[]
    @Toaster (1)
    public Multi<String> longGoodbye(String name) {
        return Multi.createFrom().items("Goodbye", ",", "Sweet", "Planet", "!"); (2)
    }
    // end::goodbye[]
}
// end::application[]

在此代码示例中需要注意以下几点:

  • AsciiDoc 注释显示在某些行上,且其编号不是连续的。

  • AsciiDoc 内容区域由代码不同部分周围的注释中的标签对 (tag::end::) 定义。

Provide concise subsequent steps

现在让我们指导学习者使用虚构的 @Anvil 注解创建一个简单的端点。

Create a source code file

我们将从在文件中创建并添加端点的步骤开始。

== Hello, World! as an Acme REST service

Let's create a Http endpoint using the `@Anvil` annotation.

Create a new source file, `src/main/java/org/acme/MyAcmeApplication.java`, and define the `MyAcmeApplication` bean as follows:

[source,java]

Unresolved directive in doc-create-tutorial.adoc - include::{doc-examples}/acme-serve-http-requests-MyAcmeApplication.java[tags=*;!goodbye]

<1> Specify the CDI lifecycle of this bean.
An `@ApplicationScoped` bean has a single bean instance that is used for the application.
<2> The `@Anvil` annotation always implies a simple Http GET request with the uri derived from the method name, `/hello` in this case.
The `optional` value indicates that the `name` parameter is not required.

有关这些指令需要注意以下几点:

  • 我们正在包含来自源文件中的代码,同时使用 Asciidoc 标签区域从列表中排除 goodbye 方法。

  • 我们在 @ApplicationScoped 的含义周围添加了一些内容,而未详细说明备选 CDI 生命周期。

  • 我们描述了 @Anvil 在本教程所涵盖的特定情况下提供的内容。

在教程中提供解释时要小心。在教程中包含足够的信息,帮助用户确定他们接下来应该参考哪些其他资源 (howto, conceptreference)。

Document Preview

预览应包含一个新章节 2. Hello, World! as an Acme REST service,其中包含 src/main/java/org/acme/MyAcmeApplication.java 的内容,省略了 goodbye 方法。

Explore continuous development and test

现在是指导用户启动 Quarkus dev 模式的时候了。常见包括项对我们来说做了大部分工作:

== Dev Mode: Hello, World!

Let's run our application using Quarkus' iterative development mode:

Unresolved directive in doc-create-tutorial.adoc - include::{includes}/devtools/dev.adoc[]

Once the console output from dev mode indicates that things are ready, use `curl` to invoke the `hello` endpoint:

[source,shell]

$ curl -w "\n" http://localhost:8080/hello Hello, World!

Pass the name as a parameter:

[source,bash,subs=attributes+]

$ curl localhost:8080/hello -d '{"name": "bananas"}' Hello, bananas!

You can leave dev mode running throughout the rest of the tutorial for continuous feedback as you make changes to code.
Use `CTRL-C` to exit dev mode.

我们在此提供了一些信息:

  • 我们使用描述如何启动 dev 模式的常用文本。

  • 我们描述如何使用 curl 来测试我们定义的端点的输出。

Document Preview

预览应包括一个新章节,“3. Dev 模式:Hello, World!”该部分应包括使用 Quarkus dev 模式的三个方法(cli、maven 和 gradle)。它应包含包含 curl 控制台命令和输出的代码块以及退出 dev 模式的说明。

Adding tests

现在,让我们引导用户向其应用程序中添加测试:

== Testing: Hello, World!

Let's create a test to work with our `@Anvil` endpoint.

Create a new source file, `src/test/java/org/acme/MyAcmeApplicationTest.java`, and define `MyAcmeApplicationTest` as follows:

[source,java]

Unresolved directive in doc-create-tutorial.adoc - include::{doc-examples}/acme-serve-http-requests-MyAcmeApplicationTest.java[tags=*;!goodbye]

After saving, the dev console should detect the presence of tests, but it isn't running by default.
The bottom of the console screen will display a message indicating that running tests have been paused.

Press `r` to resume testing.
You should see the status change as tests are running, and it should finish with a message indicating that 1 test was run and that it was successful.

我们使用 Asciidoc 区域标记来从列表中排除一个方法(我们稍后会添加该方法)。

Document Preview

预览应包含一个新的部分 4. Testing: Hello, World!,其中包含 `src/main/java/org/acme/MyAcmeApplicationTest.java`的内容,但省略了 `testGoodbyeEndpoint`方法。

Add additional capabilities

让我们添加另一个步骤,以使用虚拟 `@Toaster`注释创建不同的端点,并为其提供相应测试。

== Goodbye, Sweet Planet! Server sent events with Acme

Let's add an endpoint that supports Server Sent Events using the `@Toaster` annotation:

[source,java]

Unresolved directive in doc-create-tutorial.adoc - include::{doc-examples}/acme-serve-http-requests-MyAcmeApplication.java[tag=goodbye]

<1> The `@Toaster` annotation indicates that this method emits Server-Sent Events.
<2> A `Multi` is an asynchronous publisher of multiple events provided by Mutiny, the event-driven reactive streams library used by Quarkus.

== Testing: Goodbye, Sweet Planet!

Let's create a test to work with our `@Toaster` endpoint.

Add the following method to `src/test/java/org/acme/MyAcmeApplicationTest.java`:

[source,java]

Unresolved directive in doc-create-tutorial.adoc - include::{doc-examples}/acme-serve-http-requests-MyAcmeApplicationTest.java[tag=goodbye]

After saving, the dev console should detect the presence of the additional test, and run both.
You should see a message that 2 tests were run, and both were successful.

几点注意:

  • 我们仅使用 AsciiDoc 区域标记来包含目标文件的一个区域。

  • 我们不详细解释概念:

    • 我们讨论了 `@Toaster`注释在此示例中的作用。

    • 我们以一种方式定义了 `Multi`一词,从而帮助用户找到与其他相关材料(如何、概念或参考)的路径。

Document preview

预览现在应包含两个新部分,5. Goodbye, Sweet Planet! Server sent events with Acme`和 `6. Testing: Goodbye, Sweet Planet!。 两个新的代码列表应重点关注之前遗漏的方法:goodbye`来自 `src/main/java/org/acme/MyAcmeApplication.java,以及 testGoodbyeEndpoint`来自 `src/main/java/org/acme/MyAcmeApplicationTest.java

Provide a Summary section

:sectnums!: (1)
== Summary

Congratulations! You have created a project that uses the acme extension to create fanciful endpoints using the `@Anvil` and `@Toaster` annotations. (2)
<1>  Turn off section numbering
<1>  祝贺用户出色完成任务!
Document preview

预览现在应包含一个未编号的 `Summary`部分。

Summary

恭喜!您已创建了一个教程,其中描述了如何创建使用不可理解的注释的应用程序,这些注释来自一个虚拟扩展。

将结果与完整的操作示例进行比较:

Unresolved directive in doc-create-tutorial.adoc - include::{doc-examples}/acme-serve-http-requests-tutorial.adoctxt[]