为 Spring Web API 使用 Quarkus 扩展

Red Hat build of Quarkus 1.11

摘要

使用 Spring Web 的注解,在 Quarkus 应用程序中为 RESTful 服务创建端点

前言

作为应用程序开发人员,您可以使用 Spring Web 注解在 Quarkus 应用程序中定义 RESTful 服务。

对红帽文档提供反馈

我们非常感谢您对我们的技术内容提供反馈,并鼓励您告诉我们您的想法。如果您想添加评论,提供见解、纠正拼写错误甚至询问问题,您可以在文档中直接这样做。

注意

您必须有一个红帽帐户并登录到客户门户网站。

要从客户门户网站提交文档反馈,请执行以下操作:

  1. 选择 Multi-page HTML 格式。
  2. 点文档右上角的 反馈 按钮。
  3. 突出显示您要提供反馈的文本部分。
  4. 点高亮文本旁的添加反馈对话框。
  5. 在页面右侧的文本框中输入您的反馈,然后单击 Submit

每次提交反馈时,我们都会自动创建跟踪问题。打开在点 Submit 后显示的链接,并开始监视问题或添加更多注释。

感谢您的宝贵反馈。

使开源包含更多

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。我们从这四个术语开始:master、slave、黑名单和白名单。由于此项工作十分艰巨,这些更改将在即将推出的几个发行版本中逐步实施。有关更多详情,请参阅我们的首席技术官 Chris Wright 提供的消息

Quarkus 提供使用 Spring Web 中的注解的兼容性层,为您的应用程序定义 REST 端点。此功能由 quarkus-spring-web 扩展提供,作为使用默认 JAX-RS 注解来定义 REST 端点的替代选择。

重要

Quarkus 中的 Spring 兼容性层不会启动 Spring 应用程序上下文,或者在启动应用程序时执行 Spring 提供的任何基础架构类(如 org.springframework.beans.factory.config.BeanPostProcessor)。Quarkus 只能从 Spring 类和注解中读取元数据,并解析用户代码方法返回特定于 Spring 的类型和参数类型。但是,当您将作为 Spring Framework 一部分的任意库添加到 Quarkus 应用程序时,此类库将无法正常工作,因为 Quarkus 没有被设计为使用它们。

注意

您可以按照本指南创建示例,并将 Quarkus 扩展用于 Spring Web API,也可以下载并查看完成的示例。要查看已完成的 Quarkus Spring Web 示例,将其下载为 存档或 克隆 Quarkus 示例 Git 存储库。您可以在 spring-web-quickstart 目录中找到 Spring Web 示例。

第 1 章 先决条件

  • 已安装 OpenJDK 11,并且 JAVA_HOME 环境变量设置为与系统上安装 OpenJDK 的目录的路径匹配。
  • 已安装 Apache Maven 3.6.2 或更高版本。

第 2 章 创建 Spring Web 示例 Maven 项目

您可以创建新的 Quarkus 项目,自动生成 REST 控制器类,并使用 Quarkus Maven 插件通过单个命令添加 quarkus-spring-web 依赖项。您还可以更新 pom.xml 文件,并手动创建 REST 控制器类和 REST 控制器测试类。

流程

  • 使用本节中显示的以下方法之一来创建 Quarkus Spring Web 示例 Maven 项目:

    • 如果您没有 Maven 项目,您可以使用 Quarkus Maven 插件创建新的 Maven 项目。输入以下命令:

      • 创建 Maven 项目目录结构
      • 创建 org.acme.spring.web.GreetingController 类,该类为应用程序定义 REST 端点
      • 导入 quarkus-spring-web 扩展

        您必须将 & lt;project_name > 替换为包含项目文件的目录的名称。

        mvn io.quarkus:quarkus-maven-plugin:1.11.7.Final-redhat-00009:create \
            -DprojectGroupId=org.acme \
            -DprojectArtifactId=<project_name> \
            -DclassName="org.acme.spring.web.GreetingController" \
            -Dpath="/greeting" \
            -Dextensions="spring-web"
    • 如果您已经有一个 Quarkus Maven 项目,则必须使用命令行向其添加 quarkus-spring-web 扩展:
    1. 进入项目的根目录:

      cd <project_name>
    2. quarkus-spring-web 扩展添加到项目的 pom.xml 文件中:

      ./mvnw quarkus:add-extension -Dextensions="spring-web"

      使用这个命令,您可以在 pom.xml 文件中添加以下条目:

      pom.xml

      <dependency>
          <groupId>io.quarkus</groupId>
          <artifactId>quarkus-spring-web</artifactId>
      </dependency>

第 3 章 为 GreetingController 创建主类和测试类

在命令行中创建项目时,Quarkus Maven 插件会自动使用 Spring Web 注解生成 GreetingController 类文件,用于定义 REST 端点和包含 GreetingController 的单元测试的类文件。

流程

  1. 创建包含以下代码的 src/main/java/org/acme/spring/web/GreetingController.java 文件。

    src/main/java/org/acme/spring/web/GreetingController.java

    package org.acme.spring.web;
    
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    @RequestMapping("/greeting")
    public class GreetingController {
    
        @GetMapping
        public String hello() {
            return "Hello Spring";
        }
    }

  2. 创建包含以下代码的 src/test/java/org/acme/spring/web/GreetingControllerTest.java 文件。

    src/test/java/org/acme/spring/web/GreetingControllerTest.java

    package org.acme.spring.web;
    
    import io.quarkus.test.junit.QuarkusTest;
    import org.junit.jupiter.api.Test;
    
    import static io.restassured.RestAssured.given;
    import static org.hamcrest.CoreMatchers.is;
    
    @QuarkusTest
    public class GreetingControllerTest {
    
        @Test
        public void testHelloEndpoint() {
            given()
              .when().get("/greeting")
              .then()
                 .statusCode(200)
                 .body(is("Hello Spring"));
        }
    
    }

第 4 章 编译并启动 Spring Web 示例

使用 Quarkus Maven 插件编译并启动您的示例应用程序。您还可以编译并运行应用程序 作为原生可执行文件

流程

  1. 进入项目的根目录:

    cd <project_name>
  2. 使用 Quarkus Maven 插件在开发模式下运行应用程序:

    ./mvnw compile quarkus:dev
  3. 导航到 http://localhost:8080/greeting 您的浏览器显示以下信息:

    Hello Spring

第 5 章 配置 GreetingController 以返回 JSON 响应

设置 Spring Web 示例时自动生成的 GreetingController 是一个简单的端点,它将文本字符串返回为响应。在更复杂的应用程序中,您可能需要配置 REST 控制器,以 JSON 格式返回响应。以下示例演示了如何配置 Spring RestController 以返回 JSON 内容:

流程

  1. 展开 GreetingController 类,如示例所示。扩展类返回 JSON 格式的响应,其中包含问候和名称。请注意,您必须从 Spring Web 导入 PathVariable 注解类,以确保您的配置正常工作:

    src/main/java/org/acme/spring/web/GreetingController.java

    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    @RequestMapping("/greeting")
    public class GreetingController {
    
        @GetMapping
        public String hello() {
            return "hello";
        }
    
        @GetMapping("/{name}")
        public Greeting hello(@PathVariable(name = "name") String name) {
            return new Greeting("hello " + name);
        }
    
        public static class Greeting {
            private final String message;
    
            public Greeting(String message) {
                this.message = message;
            }
    
            public String getMessage(){
                return message;
            }
        }
    }

  1. 当您更改 REST 端点时,还必须更新包含 REST 端点的单元测试的类文件:

    src/test/java/org/acme/spring/web/GreetingControllerTest.java

    package org.acme.spring.web;
    
    import io.quarkus.test.junit.QuarkusTest;
    import org.junit.jupiter.api.Test;
    
    import static io.restassured.RestAssured.given;
    import static org.hamcrest.CoreMatchers.is;
    
    @QuarkusTest
    public class GreetingControllerTest {
    
        @Test
        public void testHelloEndpoint() {
            given()
              .when().get("/greeting/quarkus")
              .then()
                .statusCode(200)
                .body("message", is("hello quarkus"));
        }
    
    }

    请注意,当您在 Quarkus 中使用 Spring Web 兼容性层时,com.fasterxml:jackson.core 依赖项会自动添加到应用程序的 classpath 中,并配置。

第 6 章 在 Spring Web 示例中启用 OpenAPI 和 Swagger-UI 支持

您可以通过添加 quarkus-smallrye-openapi 扩展,为带有 Swagger-UI 的 REST 端点生成 OpenAPI 模式文档的支持。

流程

  1. 输入以下命令将 quarkus-smallrye-openapi 扩展添加为 Spring Web 示例的依赖项。添加扩展足以从 REST 端点生成基本 OpenAPI 模式文档:

    ./mvnw quarkus:add-extension -Dextensions="io.quarkus:quarkus-smallrye-openapi"

    输入命令会在 pom.xml 中添加以下依赖项:

    pom.xml

    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-smallrye-openapi</artifactId>
    </dependency>

  2. 输入以下命令从 /q/openapi 获取 schema 文档:

    curl http://localhost:8080/q/openapi

    您以 YAML 格式收到对生成的 OpenAPI 模式文档的响应:

    ---
    openapi: 3.0.3
    info:
      title: Generated API
      version: "1.0"
    paths:
      /greeting:
        get:
          responses:
            "200":
              description: OK
              content:
                text/plain:
                  schema:
                    type: string
      /greeting/{name}:
        get:
          parameters:
          - name: name
            in: path
            required: true
            schema:
              type: string
          responses:
            "200":
              description: OK
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Greeting'
    components:
      schemas:
        Greeting:
          type: object
          properties:
            message:
              type: string

第 7 章 在 REST 控制器代码中添加 MicroProfile OpenAPI 注解

您可以在剩余的控制器代码中添加 MicroProfile OpenAPI 注解,以便为其他端点生成更详细的 OpenAPI 模式。

流程

  1. GreetingController 的类级别添加 @OpenApiDefinition 注释。包括注解中的示例中显示的数据:

    @OpenAPIDefinition(
        info = @Info(
            title="Greeting API",
            version = "1.0.1",
            contact = @Contact(
                name = "Greeting API Support",
                url = "http://exampleurl.com/contact",
                email = "techsupport@example.com"),
            license = @License(
                name = "Apache 2.0",
                url = "https://www.apache.org/licenses/LICENSE-2.0.html"))
    )
  2. 使用 @Tag 注释注解您的端点定义。为每个端点提供名称和描述:

    @Tag(name = "Hello", description = "Just say hello")
    @GetMapping(produces=MediaType.TEXT_PLAIN_VALUE)
    public String hello() {
        return "hello";
    }
    
    @GetMapping(value = "/{name}", produces=MediaType.APPLICATION_JSON_VALUE)
    @Tag(name = "Hello to someone", description = "Just say hello to someone")
    public Greeting hello(@PathVariable(name = "name") String name) {
        return new Greeting("hello " + name);
    }

    您在注解中提供的数据会出现在生成的 OpenAPI 模式中:

    openapi: 3.0.3
    info:
      title: Greeting API
      contact:
        name: Greeting API Support
        url: http://exampleurl.com/contact
        email: techsupport@example.com
      license:
        name: Apache 2.0
        url: https://www.apache.org/licenses/LICENSE-2.0.html
      version: 1.0.1
    tags:
    - name: Hello
        description: Just say hello
    - name: Hello to someone
        description: Just say hello to someone
    paths:
      /greeting:
        get:
          tags:
          - Hello
          responses:
            '200':
              description: OK
              content:
                text/plain:
                  schema:
                    type: string
      /greeting/{name}:
        get:
          tags:
          - Hello to someone
          parameters:
          - name: name
            in: path
            required: true
            schema:
              type: string
          responses:
            '200':
              description: OK
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Greeting'
    
    components:
      schemas:
        Greeting:
          type: object
          properties:
            message:
              type: string

第 8 章 Quarkus 支持的 Spring Web 注解概述

Quarkus 中的 Spring 兼容性层支持 Spring Web 提供的有限功能子集。具体来说,Quarkus 只支持 Spring Web 中的 REST 相关注解,如 @RestController,但不支持 @Controller

Quarkus 支持 Spring Web 中的以下注解:

  • @RestController
  • @RequestMapping
  • @GetMapping
  • @PostMapping
  • @PutMapping
  • @DeleteMapping
  • @PatchMapping
  • @RequestParam
  • @RequestHeader
  • @MatrixVariable
  • @PathVariable
  • @CookieValue
  • @RequestBody
  • @ResponseStatus
  • @ExceptionHandler [1]
  • @RestControllerAdvice [2]


[1] 只能用 @RestControllerAdvice 类,而不能基于每个控制器使用。
[2] Quarkus 仅支持 @ExceptionHandler 功能。

第 9 章 Spring Web 注解及其 JAX-RS 概述

下表显示了 Spring Web 注释如何转换为 JAX-RS 注释。

表 9.1. Spring Web 注解及其 JAX-RS 等效项

SpringJAX-RS备注

@RestController

 

JAX-RS 中没有等效的。使用 @Path suffices 注解类。

@RequestMapping(path="/api")

@Path("/api")

 

@RequestMapping(consumes="application/json")

@consumes ("application/json")

 

@RequestMapping(produces="application/json")

@Produces("application/json")

 

@RequestParam

@QueryParam

 

@PathVariable

@PathParam

 

@RequestBody

 

JAX-RS 中没有等效的。与请求正文对应的方法参数会在 JAX-RS 中处理,而无需任何注释。

@RestControllerAdvice

 

JAX-RS 中没有等效的。

@ResponseStatus

 

JAX-RS 中没有等效的。

@ExceptionHandler

 

JAX-RS 中没有等效的注解。例外是通过实施 javax.ws.rs.ext.ExceptionMapper 来处理的。

第 10 章 Quarkus 支持的控制器方法参数类型

除了可以使用上表中的适当 Spring Web 注解注解的方法参数外,还支持 javax.servlet.http.HttpServletRequestjavax.servlet.http.HttpServletResponse。但是,为了正常工作,用户需要添加 quarkus-undertow 依赖项。

第 11 章 Controller 方法返回 Quarkus 支持的类型

当在 Quarkus 上使用 Spring Web 时,支持以下方法返回类型:

  • 原语类型
  • 字符串(以字面形式使用)。Quarkus 不支持 Spring MVC 视图
  • 使用 JSON 序列化的 POJO 类
  • org.springframework.http.ResponseEntity

第 12 章 Quarkus 支持的异常处理程序方法参数类型

Spring Web API 的 Quarkus 扩展支持以下异常处理程序方法参数类型。(列出类型的顺序是任意的,不反映应使用单个参数类型的首选项顺序):

  • 一个 exception 参数:声明为常规 例外 或更具体的异常。如果注解本身没有使用 value () 指定异常类型,这也充当映射提示。
  • 请求或响应对象(或两者)(通常来自 Servlet API)。您可以选择任何特定的请求或响应类型,如 ServletRequestHttpServletRequest。您必须将 quarkus-undertow 依赖项添加到项目以使用 Servlet API。

Quarkus 不支持 Spring ExceptionHandler Java API 文档中的 其他参数类型

第 13 章 异常处理器方法返回 Quarkus 支持的类型

在 Quarkus 中使用 Spring Web 时,支持以下方法返回类型:

  • org.springframework.http.ResponseEntity
  • java.util.Map

Quarkus 不支持 Spring ExceptionHandler Java API 文档中的 其他返回类型。

第 14 章 其他资源

更新于 2023-05-16

法律通告

Copyright © 2023 Red Hat, Inc.
The text of and illustrations in this document are licensed by Red Hat under a Creative Commons Attribution–Share Alike 3.0 Unported license ("CC-BY-SA"). An explanation of CC-BY-SA is available at http://creativecommons.org/licenses/by-sa/3.0/. In accordance with CC-BY-SA, if you distribute this document or an adaptation of it, you must provide the URL for the original version.
Red Hat, as the licensor of this document, waives the right to enforce, and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent permitted by applicable law.
Red Hat, Red Hat Enterprise Linux, the Shadowman logo, the Red Hat logo, JBoss, OpenShift, Fedora, the Infinity logo, and RHCE are trademarks of Red Hat, Inc., registered in the United States and other countries.
Linux® is the registered trademark of Linus Torvalds in the United States and other countries.
Java® is a registered trademark of Oracle and/or its affiliates.
XFS® is a trademark of Silicon Graphics International Corp. or its subsidiaries in the United States and/or other countries.
MySQL® is a registered trademark of MySQL AB in the United States, the European Union and other countries.
Node.js® is an official trademark of Joyent. Red Hat is not formally related to or endorsed by the official Joyent Node.js open source or commercial project.
The OpenStack® Word Mark and OpenStack logo are either registered trademarks/service marks or trademarks/service marks of the OpenStack Foundation, in the United States and other countries and are used with the OpenStack Foundation's permission. We are not affiliated with, endorsed or sponsored by the OpenStack Foundation, or the OpenStack community.
All other trademarks are the property of their respective owners.