练习 - 创建 Quarkus 应用程序

已完成

在本单元中,你将创建一个基本的 Quarkus 应用程序。 使用 Maven 启动应用程序和所选集成开发环境(IDE)来编辑代码。 使用自己所选的终端来运行代码。 可以使用 Docker 启动本地 PostgreSQL 数据库,以便在本地运行和测试应用程序。

使用 Maven 生成 Quarkus 应用程序

可通过多种方式生成 Quarkus 项目结构。 可以使用 Quarkus Web 界面、IDE 插件或 Quarkus Maven 插件。 让我们使用 Maven 插件生成项目结构。

使用多个依赖项生成应用程序:

  • 用于公开 REST 终结点的 resteasy 依赖项
  • 用于序列化和反序列化 JSON 的 jackson 依赖项
  • 用于与数据库交互的 hibernate 依赖项
  • 连接到 PostgreSQL 数据库所需的postgresql依赖项
  • 用于生成 Docker 映像的 docker 依赖项

无需指定 Azure 依赖项,因为首先在本地运行应用程序,然后将其容器化版本部署到 Azure 容器应用。

在命令提示符下,创建待办事项应用程序:

mvn -U io.quarkus:quarkus-maven-plugin:3.19.0:create \
    -DplatformVersion=3.18.4 \
    -DprojectGroupId=com.example.demo \
    -DprojectArtifactId=todo \
    -DclassName="com.example.demo.TodoResource" \
    -Dpath="/api/todos" \
    -DjavaVersion=17 \
    -Dextensions="resteasy-jackson, hibernate-orm-panache, jdbc-postgresql, docker"

此命令将创建新的 Quarkus 项目。 它生成 Maven 目录结构(源代码src/main/java 和测试 src/test/java)。 它创建一些 Java 类、一些测试和一些 Dockerfiles。 它还会生成具有所有所需依赖项(Hibernate、RESTEasy、Jackson、PostgreSQL 和 Docker)的 pom.xml 文件:

  <dependencies>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-hibernate-orm-panache</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-resteasy-jackson</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-jdbc-postgresql</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-container-image-docker</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-arc</artifactId>
    </dependency>
    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-hibernate-orm</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-resteasy</artifactId>
    </dependency>
    <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>
  </dependencies>

注释

pom.xml 文件中的所有依赖项都在 Quarkus BOM(材料清单)io.quarkus.platform:quarkus-bom中定义。

编写应用程序代码

接下来,将生成的 MyEntity.java 类重命名为 Todo.java(与 TodoResource.java 文件位于同一文件夹中)。 将现有代码替换为以下 Java 代码。 它使用 Java 持久性 API(jakarta.persistence.* 包)从 PostgreSQL 服务器存储和检索数据。 它还使用 Hibernate ORM 和 Panache(继承自 io.quarkus.hibernate.orm.panache.PanacheEntity)来简化持久层。

使用 JPA 实体(@Entity)将 Java Todo 对象直接映射到 PostgreSQL Todo 表。 然后,TodoResource REST 终结点创建一个新的 Todo 实体类并保留它。 此类是映射到 Todo 表上的域模型。 表由 JPA 自动创建。

通过扩展 PanacheEntity,可以获得一些针对你的类型的通用 create、read、update 和 delete (CRUD) 方法。 因此,只需在一行 Java 代码中保存和删除 Todo 对象即可。

将以下代码添加到 Todo 实体:

package com.example.demo;

import io.quarkus.hibernate.orm.panache.PanacheEntity;

import jakarta.persistence.Entity;
import java.time.Instant;

@Entity
public class Todo extends PanacheEntity {

    public String description;

    public String details;

    public boolean done;

    public Instant createdAt = Instant.now();

    @Override
    public String toString() {
        return "Todo{" +
                "id=" + id + '\'' +
                ", description='" + description + '\'' +
                ", details='" + details + '\'' +
                ", done=" + done +
                ", createdAt=" + createdAt +
                '}';
    }
}

若要管理该类,请更新 TodoResource,以便它可以发布 REST 接口以使用 HTTP 存储和检索数据。 打开 TodoResource 类,并将代码替换为以下内容:

package com.example.demo;

import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.UriBuilder;
import jakarta.ws.rs.core.UriInfo;
import org.jboss.logging.Logger;

import java.util.List;

@Path("/api/todos")
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
public class TodoResource {

    @Inject
    Logger logger;

    @Inject
    UriInfo uriInfo;

    @POST
    @Transactional
    public Response createTodo(Todo todo) {
        logger.info("Creating todo: " + todo);
        Todo.persist(todo);
        UriBuilder uriBuilder = uriInfo.getAbsolutePathBuilder().path(todo.id.toString());
        return Response.created(uriBuilder.build()).entity(todo).build();
    }

    @GET
    public List<Todo> getTodos() {
        logger.info("Getting all todos");
        return Todo.listAll();
    }
}

运行应用程序

在开发模式下运行应用程序时,Docker 需要运行。 这是因为 Quarkus 检测到您需要 PostgreSQL 数据库(由于在 quarkus-jdbc-postgresql 文件中声明了 PostgreSQL 依赖项 ),然后下载 PostgreSQL Docker 映像,并启动带有数据库的容器。 然后,它会自动在数据库中创建 Todo 表。

确保 Docker 在你的计算机上本地运行,并使用以下命令运行待办事项应用程序:

cd todo
./mvnw quarkus:dev    # On Mac or Linux
mvnw.cmd quarkus:dev  # On Windows

Quarkus 应用程序应启动并连接到数据库。 应会看到以下输出:

2025-02-28 08:38:33,418 INFO  [io.qua.dat.dep.dev.DevServicesDatasourceProcessor] (build-28) Dev Services for default datasource (postgresql) started - container ID is ce37977203b0
2025-02-28 08:38:33,421 INFO  [io.qua.hib.orm.dep.dev.HibernateOrmDevServicesProcessor] (build-6) Setting quarkus.hibernate-orm.database.generation=drop-and-create to initialize Dev Services managed database
__  ____  __  _____   ___  __ ____  ______ 
 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/ 
 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \   
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/   
2025-02-28 08:38:35,278 INFO  [io.quarkus] (Quarkus Main Thread) todo 1.0.0-SNAPSHOT on JVM (powered by Quarkus 3.18.4) started in 5.367s. Listening on: http://localhost:8080

2025-02-28 08:38:35,280 INFO  [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
2025-02-28 08:38:35,280 INFO  [io.quarkus] (Quarkus Main Thread) Installed features: [agroal, cdi, hibernate-orm, hibernate-orm-panache, jdbc-postgresql, narayana-jta, resteasy, resteasy-jackson, smallrye-context-propagation, vertx]

--
Tests paused
Press [e] to edit command line args (currently ''), [r] to resume testing, [o] Toggle test output, [:] for the terminal, [h] for more options>

若要测试应用程序,可使用 cURL。

在单独的终端中,使用以下命令在数据库中创建新的 to-do 项。 应该会在 Quarkus 控制台中看到日志:

curl --header "Content-Type: application/json" \
    --request POST \
    --data '{"description":"Take Quarkus MS Learn","details":"Take the MS Learn on deploying Quarkus to Azure Container Apps","done": "true"}' \
    http://127.0.0.1:8080/api/todos

此命令应返回创建的项(标识符):

{"id":1,"description":"Take Quarkus MS Learn","details":"Take the MS Learn on deploying Quarkus to Azure Container Apps","done":true,"createdAt":"2025-02-26T07:27:30.093447Z"}

使用以下 cURL 命令创建第二个 to-do:

curl --header "Content-Type: application/json" \
    --request POST \
    --data '{"description":"Take Azure Container Apps MS Learn","details":"Take the ACA Learn module","done": "false"}' \
    http://127.0.0.1:8080/api/todos

接下来,使用新的 cURL 请求检索数据:

curl http://127.0.0.1:8080/api/todos

此命令返回待办事项列表,包括您创建的事项:

[ 
  {"id":1,"description":"Take Quarkus MS Learn","details":"Take the MS Learn on deploying Quarkus to Azure Container Apps","done":true},
  {"id":2,"description":"Take Azure Container Apps MS Learn","details":"Take the ACA Learn module","done":false}
]

测试应用程序

若要测试应用程序,可以使用现有的 TodoResourceTest 类。 它需要测试 REST 终结点。 为了测试终结点,它使用 RESTAssured。 将 TodoResourceTest 类中的代码替换为以下代码:

package com.example.demo;

import io.quarkus.test.junit.QuarkusTest;
import static io.restassured.RestAssured.given;
import static jakarta.ws.rs.core.HttpHeaders.CONTENT_TYPE;
import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
import org.junit.jupiter.api.Test;

@QuarkusTest
class TodoResourceTest {

    @Test
    void shouldGetAllTodos() {
        given()
                .when().get("/api/todos")
                .then()
                .statusCode(200);
    }

    @Test
    void shouldCreateATodo() {
        Todo todo = new Todo();
        todo.description = "Take Quarkus MS Learn";
        todo.details = "Take the MS Learn on deploying Quarkus to Azure Container Apps";
        todo.done = true;

        given().body(todo)
                .header(CONTENT_TYPE, APPLICATION_JSON)
                .when().post("/api/todos")
                .then()
                .statusCode(201);
    }
}

测试应用程序时,Docker Desktop 需要运行,因为 Quarkus 检测到它需要 PostgreSQL 数据库进行测试。 使用以下命令测试应用程序:

./mvnw clean test    # On Mac or Linux
mvnw.cmd clean test  # On Windows

应会看到如下所示的输出:

[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.example.demo.TodoResourceTest
[INFO] 
[INFO] Results:
[INFO] 
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
[INFO] 
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------