添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
quarkus create app org.acme:rest-json-quickstart \
    --extension='resteasy-reactive-jackson' \
    --no-code
cd rest-json-quickstart

创建Grade项目,请添加 --gradle 或者 --gradle-kotlin-dsl 参数。

For more information about how to install and use the Quarkus CLI, see the Quarkus CLI guide.

mvn io.quarkus.platform:quarkus-maven-plugin:3.6.4:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=rest-json-quickstart \
    -Dextensions='resteasy-reactive-jackson' \
    -DnoCode
cd rest-json-quickstart

创建Grade项目,请添加 -DbuildTool=gradle 或者 -DbuildTool=gradle-kotlin-dsl 参数。

This command generates a new project importing the RESTEasy Reactive/Jakarta REST and Jackson extensions, and in particular adds the following dependency:

pom.xml
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-resteasy-reactive-jackson</artifactId>
</dependency>
build.gradle
implementation("io.quarkus:quarkus-resteasy-reactive-jackson")
quarkus create app org.acme:rest-json-quickstart \
    --extension='resteasy-reactive-jsonb' \
    --no-code
cd rest-json-quickstart

创建Grade项目,请添加 --gradle 或者 --gradle-kotlin-dsl 参数。

For more information about how to install and use the Quarkus CLI, see the Quarkus CLI guide.

mvn io.quarkus.platform:quarkus-maven-plugin:3.6.4:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=rest-json-quickstart \
    -Dextensions='resteasy-reactive-jsonb' \
    -DnoCode
cd rest-json-quickstart

创建Grade项目,请添加 -DbuildTool=gradle 或者 -DbuildTool=gradle-kotlin-dsl 参数。

This command generates a new project importing the RESTEasy Reactive/Jakarta REST and JSON-B extensions, and in particular adds the following dependency:

pom.xml
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-resteasy-reactive-jsonb</artifactId>
</dependency>
build.gradle
implementation("io.quarkus:quarkus-resteasy-reactive-jsonb")
public Fruit(String name, String description) { this.name = name; this.description = description;

这是非常的简单。需要注意的重要一点是, JSON 序列化层需要具有默认构造函数。

现在,创建 org.acme.rest.json.FruitResource 类,如下所示。

package org.acme.rest.json;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Set;
import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
@Path("/fruits")
public class FruitResource {
    private Set<Fruit> fruits = Collections.newSetFromMap(Collections.synchronizedMap(new LinkedHashMap<>()));
    public FruitResource() {
        fruits.add(new Fruit("Apple", "Winter fruit"));
        fruits.add(new Fruit("Pineapple", "Tropical fruit"));
    public Set<Fruit> list() {
        return fruits;
    @POST
    public Set<Fruit> add(Fruit fruit) {
        fruits.add(fruit);
        return fruits;
    @DELETE
    public Set<Fruit> delete(Fruit fruit) {
        fruits.removeIf(existingFruit -> existingFruit.name.contentEquals(fruit.name));
        return fruits;

The implementation is pretty straightforward, and you just need to define your endpoints using the Jakarta REST annotations.

Fruit 对象将被 JSON-BJackson 自动序列化/反序列化,这取决于你在初始化项目时选择的扩展。

Jackson

在Quarkus中,通过CDI获得的默认Jackson ObjectMapper (并由Quarkus扩展使用)被配置为忽略未知属性(通过禁用 DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES 功能)。

You can restore the default behavior of Jackson by setting quarkus.jackson.fail-on-unknown-properties=true in your application.properties or on a per-class basis via @JsonIgnoreProperties(ignoreUnknown = false).

此外, ObjectMapper 被配置为ISO-8601的日期和时间格式(通过禁用 SerializationFeature.WRITE_DATES_AS_TIMESTAMPS 功能)。

Jackson的默认行为可以通过在你的 application.properties 中设置 quarkus.jackson.write-dates-as-timestamps=true 来设置。如果你想改变单个字段的默认行为,你可以使用 @JsonFormat 注解。

另外,Quarkus使得通过CDI beans来配置各种Jackson设置变得非常容易。最简单的(也是建议的)方法是定义一个类型为 io.quarkus.jackson.ObjectMapperCustomizer 的CDI Bean,在其中可以使用任何Jackson配置。

需要注册自定义模块的示例如下所示:

import com.fasterxml.jackson.databind.ObjectMapper;
import io.quarkus.jackson.ObjectMapperCustomizer;
import jakarta.inject.Singleton;
@Singleton
public class RegisterCustomModuleCustomizer implements ObjectMapperCustomizer {
    public void customize(ObjectMapper mapper) {
        mapper.registerModule(new CustomModule());

如果用户选择的话,他们甚至可以提供自己的 ObjectMapper bean。如果这样做,在产生 ObjectMapper 的CDI生产者中,手动注入和应用所有 io.quarkus.jackson.ObjectMapperCustomizer Bean是非常重要的。如果不这样做,就会阻止各种扩展所提供的Jackson特定的自定义功能被应用。

import com.fasterxml.jackson.databind.ObjectMapper;
import io.quarkus.arc.All;
import io.quarkus.jackson.ObjectMapperCustomizer;
import java.util.List;
import jakarta.inject.Singleton;
public class CustomObjectMapper {
    // Replaces the CDI producer for ObjectMapper built into Quarkus
    @Singleton
    @Produces
    ObjectMapper objectMapper(@All List<ObjectMapperCustomizer> customizers) {
        ObjectMapper mapper = myObjectMapper(); // Custom `ObjectMapper`
        // Apply all ObjectMapperCustomizer beans (incl. Quarkus)
        for (ObjectMapperCustomizer customizer : customizers) {
            customizer.customize(mapper);
        return mapper;
Mixin support

Quarkus automates the registration of Jackson’s Mixin support, via the io.quarkus.jackson.JacksonMixin annotation. This annotation can be placed on classes that are meant to be used as Jackson mixins while the classes they are meant to customize are defined as the value of the annotation.

import io.quarkus.jsonb.JsonbConfigCustomizer;
import jakarta.inject.Singleton;
import jakarta.json.bind.JsonbConfig;
import jakarta.json.bind.serializer.JsonbSerializer;
@Singleton
public class FooSerializerRegistrationCustomizer implements JsonbConfigCustomizer {
    public void customize(JsonbConfig config) {
        config.withSerializers(new FooSerializer());

A more advanced option would be to directly provide a bean of jakarta.json.bind.JsonbConfig (with a Dependent scope) or in the extreme case to provide a bean of type jakarta.json.bind.Jsonb (with a Singleton scope). If the latter approach is leveraged it is very important to manually inject and apply all io.quarkus.jsonb.JsonbConfigCustomizer beans in the CDI producer that produces jakarta.json.bind.Jsonb. Failure to do so will prevent JSON-B specific customizations provided by various extensions from being applied.

import io.quarkus.jsonb.JsonbConfigCustomizer;
import jakarta.enterprise.context.Dependent;
import jakarta.enterprise.inject.Instance;
import jakarta.json.bind.JsonbConfig;
public class CustomJsonbConfig {
    // Replaces the CDI producer for JsonbConfig built into Quarkus
    @Dependent
    JsonbConfig jsonConfig(Instance<JsonbConfigCustomizer> customizers) {
        JsonbConfig config = myJsonbConfig(); // Custom `JsonbConfig`
        // Apply all JsonbConfigCustomizer beans (incl. Quarkus)
        for (JsonbConfigCustomizer customizer : customizers) {
            customizer.customize(config);
        return config;

Now let’s add a simple web page to interact with our FruitResource. Quarkus automatically serves static resources located under the META-INF/resources directory. In the src/main/resources/META-INF/resources directory, add a fruits.html file with the content from this fruits.html file in it.

现在你可以与你的REST服务进行交互:

当使用GraalVM的本地可执行文件时,需要注册所有将与反射一起使用的类。好消息是,Quarkus在大多数时候都会为你做这项工作。到目前为止,我们还没有注册任何类,甚至没有注册 Fruit ,并且一切正常。

当Quarkus能够从REST方法中推断出序列化的类型时,它会发挥一些作用。当你有以下的REST方法时,Quarkus确定 Fruit 将被序列化:

public List<Fruit> list() { // ...

Quarkus通过在构建时分析REST方法自动为你执行此操,这就是为什么我们在本指南的第一部分不需要任何反射注册。

Another common pattern in the Jakarta REST world is to use the Response object. Response comes with some nice perks:

public Legume(String name, String description) { this.name = name; this.description = description;

现在让我们创建一个 LegumeResource REST服务,它只有一个返回legumes类列表的方法。

该方法返回一个 Response ,而不是一个 Legume 列表。

package org.acme.rest.json;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.core.Response;
@Path("/legumes")
public class LegumeResource {
    private Set<Legume> legumes = Collections.synchronizedSet(new LinkedHashSet<>());
    public LegumeResource() {
        legumes.add(new Legume("Carrot", "Root vegetable, usually orange"));
        legumes.add(new Legume("Zucchini", "Summer squash"));
    public Response list() {
        return Response.ok(legumes).build();

现在让我们添加一个简单的网页来显示我们的legumes列表。在 src/main/resources/META-INF/resources 目录中,添加一个 legumes.html 文件,其中包含这个https://github.com/quarkusio/quarkus-quickstarts/blob/main/rest-json-quickstart/src/main/resources/META-INF/resources/legumes.html[legumes.html] 文件的内容。

Open a browser to http://localhost:8080/legumes.html, and you will see our list of legumes.

有趣的部分是在将应用程序作为本机可执行文件运行时开始的:

As mentioned above, the issue is that Quarkus was not able to determine the Legume class will require some reflection by analyzing the REST endpoints. The JSON serialization library tries to get the list of fields of Legume and gets an empty list, so it does not serialize the fields' data.