Openapi Swaggerui
本指南介绍 Quarkus 应用程序如何通过 OpenAPI 标准暴露其 API 描述,以及如何通过用户友好的 Swagger UI 来测试它。
成果
我们建议您按照下面章节指示,一步一步创建应用程序。 但是你也可以直接跳到已完成的示例。
克隆 Git 仓库: git clone https://github.com/quarkusio/quarkus-quickstarts.git
, 或下载 压缩包
解决方案在 openapi-swaggerui-quickstart
目录.
创建 Maven 项目
首先,我们需要一个新项目。 通过以下命令创建一个新项目:
mvn io.quarkus:quarkus-maven-plugin:1.3.1.Final:create \
-DprojectGroupId=org.acme \
-DprojectArtifactId=openapi-swaggerui-quickstart \
-DclassName="org.acme.openapi.swaggerui.FruitResource" \
-Dpath="/fruits" \
-Dextensions="resteasy-jsonb"
cd openapi-swaggerui-quickstart
此命令生成一个带有 /fruits
REST 接口的 Maven 项目。
暴露一个 REST 资源
我们将创建一个 Fruit
bean 和一个 FruitResouce
REST 资源
(如果您想详细了解如何通过 Quarkus 创建 REST API,请随时查看 编写 JSON REST 服务指南)。
package org.acme.openapi.swaggerui;
public class Fruit {
public String name;
public String description;
public Fruit() {
}
public Fruit(String name, String description) {
this.name = name;
this.description = description;
}
}
package org.acme.openapi.swaggerui;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.DELETE;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.Consumes;
import javax.ws.rs.core.MediaType;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Set;
@Path("/fruits")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
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"));
}
@GET
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;
}
}
当我们修改API时,我们还需要更新测试:
package org.acme.openapi.swaggerui;
import io.quarkus.test.junit.QuarkusTest;
import org.junit.jupiter.api.Test;
import javax.ws.rs.core.MediaType;
import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.Matchers.containsInAnyOrder;
@QuarkusTest
public class FruitResourceTest {
@Test
public void testList() {
given()
.when().get("/fruits")
.then()
.statusCode(200)
.body("$.size()", is(2),
"name", containsInAnyOrder("Apple", "Pineapple"),
"description", containsInAnyOrder("Winter fruit", "Tropical fruit"));
}
@Test
public void testAdd() {
given()
.body("{\"name\": \"Pear\", \"description\": \"Winter fruit\"}")
.header("Content-Type", MediaType.APPLICATION_JSON)
.when()
.post("/fruits")
.then()
.statusCode(200)
.body("$.size()", is(3),
"name", containsInAnyOrder("Apple", "Pineapple", "Pear"),
"description", containsInAnyOrder("Winter fruit", "Tropical fruit", "Winter fruit"));
given()
.body("{\"name\": \"Pear\", \"description\": \"Winter fruit\"}")
.header("Content-Type", MediaType.APPLICATION_JSON)
.when()
.delete("/fruits")
.then()
.statusCode(200)
.body("$.size()", is(2),
"name", containsInAnyOrder("Apple", "Pineapple"),
"description", containsInAnyOrder("Winter fruit", "Tropical fruit"));
}
}
暴露 OpenAPI 规范
Quarkus 提议使用与 Eclipse MicroProfile OpenAPI
标准兼容的 smallrye-openapi
extension 来生成你 API 的 OpenAPI v3 规范.
您只需要将 openapi
扩展添加到您的 Quarkus 应用程序:
./mvnw quarkus:add-extension -Dextensions="openapi"
现在,准备运行我们的应用程序:
./mvnw compile quarkus:dev
一旦应用程序启动,您可以访问网址 /openapi
:
$ curl http://localhost:8080/openapi
openapi: 3.0.1
info:
title: Generated API
version: "1.0"
paths:
/fruits:
get:
responses:
200:
description: OK
content:
application/json: {}
post:
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Fruit'
responses:
200:
description: OK
content:
application/json: {}
delete:
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Fruit'
responses:
200:
description: OK
content:
application/json: {}
components:
schemas:
Fruit:
properties:
description:
type: string
name:
type: string
如果不喜欢默认的网址
|
按 CTRL+C
停掉应用程序。
提供的应用程序级别 OpenAPI 注解
有一些 MicroProfile OpenAPI 注解描述了全局的 API 信息,例如:
-
API 标题
-
API 描述
-
版本
-
联系信息
-
许可协议
所有这些信息(以及更多信息) 都可以在 Java 代码中 JAX-RS Application
类上使用合适的 OpenAPI 注解来指定。 因为 Quarkus 中 JAX-RS Application
类不是必备的,您很可能需要创建一个。 它可以只是一个简单 extends javax.ws.rs.core.Application
的空类。 然后此空类就可以用各种 OpenAPI 注解,如 @OpenAPIDefinition
。 例如:
@OpenAPIDefinition(
tags = {
@Tag(name="widget", description="Widget operations."),
@Tag(name="gasket", description="Operations related to gaskets")
},
info = @Info(
title="Example API",
version = "1.0.1",
contact = @Contact(
name = "Example API Support",
url = "http://exampleurl.com/contact",
email = "techsupport@example.com"),
license = @License(
name = "Apache 2.0",
url = "http://www.apache.org/licenses/LICENSE-2.0.html"))
)
public class ExampleApiApplication extends Application {
}
从静态文件加载 OpenAPI 规范
相对通过扫描注解动态创建 OpenAPI 规范,Quarkus 也支持静态的 OpenAPI 规范文档。
静态文件必须是符合 OpenAPI 标准 的有效文档。
符合 OpenAPI 标准的 OpenAPI 文档本身就是一个有效的 JSON 对象,可以以 yaml
或 json
格式表示。
要使用它,我们将把 OpenAPI 文档放在 META-INF/openapi.yaml
对应 /fruits
接口 。
如果你喜欢 Quarkus 也支持其它 OpenAPI document paths 路径。
openapi: 3.0.1
info:
title: Static OpenAPI document of fruits resource
description: Fruit resources Open API documentation
version: "1.0"
servers:
- url: http://localhost:8080/openapi
description: Optional dev mode server description
paths:
/fruits:
get:
responses:
200:
description: OK - fruits list
content:
application/json: {}
post:
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Fruit'
responses:
200:
description: new fruit resource created
content:
application/json: {}
delete:
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Fruit'
responses:
200:
description: OK - fruit resource deleted
content:
application/json: {}
components:
schemas:
Fruit:
properties:
description:
type: string
name:
type: string
默认情况下,请求 /openapi
时会返回融合了静态文件和根据应用程序接口代码生成的 OpenAPI 文档。
但我们可以修改 application.properties
中的 mp.openapi.scan.disabl=true
来改为仅使用静态 OpenAPI 文档。
现在, /openapi
接口将只使用静态的 OpenAPI 文档,而不是动态生成一个。
关于 OpenAPI 文档路径
Quarkus 支持各种路径来存储您的 OpenAPI 文档。 我们建议你将其放在`META-INF/openapi.yml`下。 替代路径:
在开发过程中支持静态OpenAPI 文档的实时重新加载。 修改 OpenAPI 文档就会被 Quarkus 采用。 |
使用 Swagger UI 进行开发
构建 API 时,开发者想要快速测试它们。 Swagger UI 是一个很好的工具 可以与您的 API 直观交互。 界面是根据您的 OpenAPI 规范自动生成的。
Quarkus smallrye-openapi
extension 伴有一个 swagger-ui
extension 来嵌入了一个配置正确的 Swagger UI 页面。
默认情况下,Swagger UI 仅在 Quarkus 在开发或测试模式下启动时有效。 如果你也想要在生产中提供它,你可以在你的
这是一个构建阶段属性,它不能在应用程序生成后在运行时更改。 |
默认情况下,Swagger UI 可以通过 /swagger-ui
访问。
您可以通过设置 application.properties
中的 quarkus.swagger-ui.path
属性来调整此路径:
quarkus.swagger-ui.path=/my-custom-path
不允许使用`/`值,因为它会阻止应用程序任何其他服务。 |
现在,准备运行我们的应用程序:
./mvnw compile quarkus:dev
您可以在应用程序日志中检查 Swagger UI 路径:
00:00:00,000 INFO [io.qua.swa.run.SwaggerUiServletExtension] Swagger UI available at /swagger-ui
一旦您的应用程序启动,您可以访问 http://localhost:8080/swagger-ui 探索下你的 API。
您可以可视化您的 API 的操作和规范。
您可以与 API 交互以快速测试。
按 CTRL+C
停掉应用程序。
配置参考
OpenAPI
Configuration property fixed at build time - All other configuration properties are overridable at runtime
Type |
Default |
|
---|---|---|
The path at which to register the OpenAPI Servlet. |
string |
|
Swagger UI
Configuration property fixed at build time - All other configuration properties are overridable at runtime
Type |
Default |
|
---|---|---|
The path where Swagger UI is available.
The value |
string |
|
If this should be included every time. By default this is only included when the application is running in dev mode. |
boolean |
|
If Swagger UI should be enabled. By default, Swagger UI is enabled. |
boolean |
|