練習 - 建立 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.7.3:create \
-DplatformVersion=3.7.3 \
-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。 它也會產生具有所有必要相依性的 pom.xml 檔案 (Hibernate、RESTEasy、Jackson、PostgreSQL 和 Docker):
<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 伺服器中儲存及擷取資料。 它也使用 搭配 Panache 的 Hibernate ORM (繼承自 io.quarkus.hibernate.orm.panache.PanacheEntity
),以簡化持續性層。
您會使用 JPA 實體 (@Entity
) 直接將 Java Todo
物件對應到 PostgreSQL Todo
資料表。 TodoResource
REST 端點會接著建立新的 Todo
實體類別並加以保存。 這個類別是在 Todo
資料表上對應的網域模型。 該資料表由 JPA 自動建立。
擴充 PanacheEntity
可提供您許多適用於您的類型的泛型建立、讀取、更新和刪除 (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
,讓它可以使用 HTTP 發佈 REST 介面來儲存和擷取資料。 開啟 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 資料庫 (這是因為 pom.xml 檔案中宣告的 PostgreSQL 相依性 quarkus-jdbc-postgresql
)、下載 PostgreSQL Docker 映射,並使用資料庫啟動容器。 它接著會自動在資料庫中建立 Todo
資料表。
請確定 Docker 已在本機電腦上執行,並使用此命令執行 [待辦事項] 應用程式:
cd todo
./mvnw quarkus:dev # On Mac or Linux
mvnw.cmd quarkus:dev # On Windows
Quarkus 應用程式應該會啟動並連線到您的資料庫。 您應該會看見下列輸出:
[io.qua.dat.dep.dev.DevServicesDatasourceProcessor] Dev Services for the default datasource (postgresql) started.
[io.qua.hib.orm.dep.HibernateOrmProcessor] Setting quarkus.hibernate-orm.database.generation=drop-and-create to initialize Dev Services managed database
__ ____ __ _____ ___ __ ____ ______
--/ __ \/ / / / _ | / _ \/ //_/ / / / __/
-/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
[org.hib.eng.jdb.spi.SqlExceptionHelper] (JPA Startup Thread) SQL Warning Code: 0, SQLState: 00000
[org.hib.eng.jdb.spi.SqlExceptionHelper] (JPA Startup Thread) table "todo" does not exist, skipping
[org.hib.eng.jdb.spi.SqlExceptionHelper] (JPA Startup Thread) SQL Warning Code: 0, SQLState: 00000
[org.hib.eng.jdb.spi.SqlExceptionHelper] (JPA Startup Thread) sequence "hibernate_sequence" does not exist, skipping
[io.quarkus] (Quarkus Main Thread) todo 1.0.0-SNAPSHOT on JVM (powered by Quarkus) started in 4.381s. Listening on: http://localhost:8080
[io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
[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 [r] to resume testing, [o] Toggle test output, [:] for the terminal, [h] for more options>
您可使用 cURL 以測試應用程式。
在不同的終端機中,使用下列命令在資料庫中建立新的待辦事項項目。 您應該會在 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":"2022-12-30T15:17:20.280203Z"}
透過使用下列 cURL 命令建立第二個待辦事項:
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] ------------------------------------------------------------------------