MicroProfile OpenAPI 适用于所有人
MicroProfile OpenAPI 主要用于为 OpenAPI 添加到 JAX-RS 端点。 在这篇博文中,我们将探讨 SmallRye实现 如何通过一些额外的功能以及对更多Web框架的支持来扩展它,当在Quarkus中使用时。
使用Quarkus
示例代码可以在 此处 找到。您也可以使用 code.quarkus.io 初始化一个项目 - 只需确保包含SmallRye OpenAPI扩展。
JAX-RS
让我们从Quarkus中的一个基本JAX-RS示例开始。我们有一个Greeting
对象,其中有一个message
和一个to
字段,我们将为问候语创建GET
、POST
和DELETE
端点。
除了常规的Quarkus设置外,您还需要在pom.xml
中添加以下内容来创建一个JAX-RS端点
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-openapi</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-jsonb</artifactId>
</dependency>
在Quarkus中,您不需要Application
类,我们可以直接添加端点类
@Path("/jax-rs")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class JaxRsGreeting {
@GET
@Path("/hello")
public Greeting helloJaxRs() {
return new Greeting("Hello", "JAX-RS");
}
@POST
@Path("/hello")
public Greeting newHelloJaxRs(Greeting greeting) {
return greeting;
}
@DELETE
@Path("/hello/{message}")
public void deleteHelloJaxRs(@PathParam("message") String message) {
// Here do the delete...
}
}
到目前为止,我们还没有添加任何MicroProfile OpenAPI注解,但是因为我们添加了quarkus-smallrye-openapi
扩展,我们将在/openapi
下生成一个Schema文档
---
openapi: 3.0.3
info:
title: Generated API
version: "1.0"
paths:
/jax-rs/hello:
get:
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Greeting'
post:
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Greeting'
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Greeting'
/jax-rs/hello/{message}:
delete:
parameters:
- name: message
in: path
required: true
schema:
type: string
responses:
"204":
description: No Content
components:
schemas:
Greeting:
type: object
properties:
message:
type: string
to:
type: string
有关更多信息,请参阅 quarkus.io/guides/rest-json。
OpenAPI
您可以通过使用MicroProfile OpenAPI将更多信息添加到生成的Schema文档中。
使用配置添加头信息
我们在SmallRye中添加的一个功能是能够通过MicroProfile配置添加头信息,通常您会使用注解将这些信息添加到Application
类中。这在Quarkus中很有用,因为您不需要Application
类。因此,将以下内容添加到application.properties
将为您提供一些头信息
mp.openapi.extensions.smallrye.info.title=OpenAPI for Everyone
%dev.mp.openapi.extensions.smallrye.info.title=OpenAPI for Everyone (development)
%test.mp.openapi.extensions.smallrye.info.title=OpenAPI for Everyone (test)
mp.openapi.extensions.smallrye.info.version=1.0.0
mp.openapi.extensions.smallrye.info.description=Example on how to use OpenAPI everywhere
mp.openapi.extensions.smallrye.info.contact.email=phillip.kruger@redhat.com
mp.openapi.extensions.smallrye.info.contact.name=Phillip Kruger
mp.openapi.extensions.smallrye.info.contact.url=https://www.phillip-kruger.com
mp.openapi.extensions.smallrye.info.license.name=Apache 2.0
mp.openapi.extensions.smallrye.info.license.url=https://apache.ac.cn/licenses/LICENSE-2.0.html
现在查看/openapi
下生成的Schema文档的头信息
---
openapi: 3.0.3
info:
title: OpenAPI for Everyone (development)
description: Example on how to use OpenAPI everywhere
contact:
name: Phillip Kruger
url: https://www.phillip-kruger.com
email: phillip.kruger@redhat.com
license:
name: Apache 2.0
url: https://apache.ac.cn/licenses/LICENSE-2.0.html
version: 1.0.0
# Rest of the schema document...
为操作添加一些OpenAPI注解
您可以使用MicroProfile OpenAPI中的任何注解来进一步描述您的端点,例如Tag
注解
@Path("/jax-rs")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Tag(name = "JAX-RS Resource", description = "Basic Hello World using JAX-RS") (1)
public class JaxRsGreeting {
//...
}
1 | MicroProfile OpenAPI注解的示例用法。 |
自动生成operation id
一些使用Schema文档生成客户端存根的工具需要在Schema文档中有一个operationId
,该ID用于命名客户端存根方法。我们在SmallRye中添加了支持,可以使用方法名(METHOD
)、类名和方法名(CLASS_METHOD
)或包名、类名和方法名(PACKAGE_CLASS_METHOD
)来自动生成它。为此,请将以下内容添加到application.properties
mp.openapi.extensions.smallrye.operationIdStrategy=METHOD
您现在将在每个操作的Schema文档中看到operationId
---
openapi: 3.0.3
# Header omitted...
/jax-rs/hello:
get:
tags:
- JAX-RS Resource
operationId: helloJaxRs (1)
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Greeting'
post:
tags:
- JAX-RS Resource
operationId: newHelloJaxRs (1)
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Greeting'
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Greeting'
/jax-rs/hello/{message}:
delete:
tags:
- JAX-RS Resource
operationId: deleteHelloJaxRs (1)
parameters:
- name: message
in: path
required: true
schema:
type: string
responses:
"204":
description: No Content
1 | 自动生成的operationId |
更改OpenAPI版本
一些API网关可能需要特定版本的OpenAPI才能正常工作。SmallRye扩展生成的Schema文档将使用3.0.3
作为版本,但由于这些版本之间只有细微的差异,您可以将其更改为3.0.0
、3.0.1
或3.0.2
。您可以通过在application.properties
中添加以下内容来实现
mp.openapi.extensions.smallrye.openapi=3.0.2
现在生成的版本将是
---
openapi: 3.0.2
# Rest of the document...
有关更多信息,请参阅 quarkus.io/guides/openapi-swaggerui。
Spring Web
最近,SmallRye OpenAPI添加了对Spring Web的支持,这意味着,当您在Quarkus中使用Spring Web时,不仅可以看到默认的OpenAPI文档,还可以使用MicroProfile OpenAPI来进一步描述您的Spring Web端点。
让我们将一个Spring Rest Controller添加到我们当前的应用程序中。首先,在您的pom.xml
中添加这个
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-spring-web</artifactId>
</dependency>
现在您可以创建一个类似于我们到目前为止看到的JAX-RS的端点,但使用Spring Web
@RestController
@RequestMapping(value = "/spring", produces = MediaType.APPLICATION_JSON_VALUE)
@Tag(name = "Spring Resource", description = "Basic Hello World using Spring")
public class SpringGreeting {
@GetMapping("/hello")
public Greeting helloSpring() {
return new Greeting("Hello", "Spring");
}
@PostMapping("/hello")
public Greeting newHelloSpring(@RequestBody Greeting greeting) {
return greeting;
}
@DeleteMapping("/hello/{message}")
public void deleteHelloSpring(@PathVariable(name = "message") String message) {
// Here do the delete...
}
}
Spring注解将被扫描,并添加到您的Schema文档中
---
openapi: 3.0.3
# Header omitted...
/spring/hello:
get:
tags:
- Spring Resource
operationId: helloSpring
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Greeting'
post:
tags:
- Spring Resource
operationId: newHelloSpring
requestBody:
content:
'_/_':
schema:
$ref: '#/components/schemas/Greeting'
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Greeting'
/spring/hello/{message}:
delete:
tags:
- Spring Resource
operationId: deleteHelloSpring
parameters:
- name: message
in: path
required: true
schema:
type: string
responses:
"204":
description: No Content
有关更多信息,请参阅 quarkus.io/guides/spring-web。
Vert.x Reactive Routes
在Quarkus中,您还可以使用Reactive Routes构建Vert.x端点。与Spring Web类似,您的端点将在OpenAPI Schema中可用,并且可以使用MicroProfile OpenAPI进一步描述。要在Quarkus中添加Vert.x Reactive Route,您需要在pom.xml
中添加以下内容
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-vertx-web</artifactId>
</dependency>
现在您可以创建端点
@ApplicationScoped
@RouteBase(path = "/vertx", produces = "application/json")
@Tag(name = "Vert.x Resource", description = "Basic Hello World using Vert.x")
public class VertxGreeting {
@Route(path = "/hello", methods = HttpMethod.GET)
public Greeting helloVertX() {
return new Greeting("Hello", "Vert.x");
}
@Route(path = "/hello", methods = HttpMethod.POST)
public Greeting newHelloVertX(@Body Greeting greeting) {
return greeting;
}
@Route(path = "/hello/:message", methods = HttpMethod.DELETE)
public void deleteHelloVertX(@Param("message") String message) {
// Here do the delete...
}
}
现在您的Vert.x Routes在OpenAPI中可用了
---
openapi: 3.0.3
# Header omitted...
/vertx/hello:
get:
tags:
- Vert.x Resource
operationId: helloVertX
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Greeting'
post:
tags:
- Vert.x Resource
operationId: newHelloVertX
requestBody:
content:
'_/_':
schema:
$ref: '#/components/schemas/Greeting'
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Greeting'
/vertx/hello/{message}:
delete:
tags:
- Vert.x Resource
operationId: deleteHelloVertX
parameters:
- name: message
in: path
required: true
schema:
type: string
responses:
"204":
description: No Content
有关更多信息,请参阅 quarkus.io/guides/reactive-routes。
使用Panache生成的端点
在Quarkus中,您可以使用Panache生成JAX-RS端点。如果您的pom.xml
中包含quarkus-smallrye-openapi
扩展,这些生成的类也将被扫描并添加到OpenAPI Schema文档中。
有关更多信息,请参阅 quarkus.io/guides/rest-data-panache。
任何其他Web框架
您还可以通过在yaml
文件中提供Schema文档的该部分来将任何其他端点添加到您的文档中。例如,假设您有一个Servlet公开了一些方法,并且您想将它们添加到Schema文档中。Servlet只是一个例子,任何Web框架都可以在这里工作。
因此,我们首先在pom.xml
中添加此项以在Quarkus中添加Servlet支持
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-undertow</artifactId>
</dependency>
我们现在可以像这样创建一个Servlet端点示例
@WebServlet("/other/hello/*")
public class ServletGreeting extends HttpServlet {
private static final Jsonb JSONB = JsonbBuilder.create();
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
response.setContentType("application/json");
Greeting greeting = new Greeting("Hello", "Other");
PrintWriter out = response.getWriter();
out.print(JSONB.toJson(greeting));
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("application/json");
Greeting greeting = JSONB.fromJson(request.getInputStream(), Greeting.class);
PrintWriter out = response.getWriter();
out.print(JSONB.toJson(greeting));
}
@Override
protected void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// Here do the delete...
}
}
现在我们需要一个OpenAPI Schema文档来映射这些端点。您需要将其添加到src/main/resources/META-INF
中的一个名为openapi.yml
的文件中
---
openapi: 3.0.3
tags:
- name: Other Resource
description: Basic Hello World using Something else
paths:
/other/hello:
get:
tags:
- Other Resource
operationId: helloOther
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Greeting'
post:
tags:
- Other Resource
operationId: newHelloOther
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Greeting'
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Greeting'
/other/hello/{message}:
delete:
tags:
- Other Resource
operationId: deleteHelloOther
parameters:
- name: message
in: path
required: true
schema:
type: string
responses:
"204":
description: No Content
这将与其余的端点合并,以公开您文档中的所有路径。因此,最终您的/openapi
输出将如下所示
---
openapi: 3.0.2
info:
title: OpenAPI for Everyone (development)
description: Example on how to use OpenAPI everywhere
contact:
name: Phillip Kruger
url: https://www.phillip-kruger.com
email: phillip.kruger@redhat.com
license:
name: Apache 2.0
url: https://apache.ac.cn/licenses/LICENSE-2.0.html
version: 1.0.0
tags:
- name: Other Resource
description: Basic Hello World using Something else
- name: Spring Resource
description: Basic Hello World using Spring
- name: JAX-RS Resource
description: Basic Hello World using JAX-RS
- name: Vert.x Resource
description: Basic Hello World using Vert.x
paths:
/other/hello:
get:
tags:
- Other Resource
operationId: helloOther
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Greeting'
post:
tags:
- Other Resource
operationId: newHelloOther
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Greeting'
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Greeting'
/other/hello/{message}:
delete:
tags:
- Other Resource
operationId: deleteHelloOther
parameters:
- name: message
in: path
required: true
schema:
type: string
responses:
"204":
description: No Content
/jax-rs/hello:
get:
tags:
- JAX-RS Resource
operationId: helloJaxRs
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Greeting'
post:
tags:
- JAX-RS Resource
operationId: newHelloJaxRs
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Greeting'
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Greeting'
/jax-rs/hello/{message}:
delete:
tags:
- JAX-RS Resource
operationId: deleteHelloJaxRs
parameters:
- name: message
in: path
required: true
schema:
type: string
responses:
"204":
description: No Content
/spring/hello:
get:
tags:
- Spring Resource
operationId: helloSpring
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Greeting'
post:
tags:
- Spring Resource
operationId: newHelloSpring
requestBody:
content:
'_/_':
schema:
$ref: '#/components/schemas/Greeting'
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Greeting'
/spring/hello/{message}:
delete:
tags:
- Spring Resource
operationId: deleteHelloSpring
parameters:
- name: message
in: path
required: true
schema:
type: string
responses:
"204":
description: No Content
/vertx/hello:
get:
tags:
- Vert.x Resource
operationId: helloVertX
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Greeting'
post:
tags:
- Vert.x Resource
operationId: newHelloVertX
requestBody:
content:
'_/_':
schema:
$ref: '#/components/schemas/Greeting'
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Greeting'
/vertx/hello/{message}:
delete:
tags:
- Vert.x Resource
operationId: deleteHelloVertX
parameters:
- name: message
in: path
required: true
schema:
type: string
responses:
"204":
description: No Content
components:
schemas:
Greeting:
type: object
properties:
message:
type: string
to:
type: string
这包含来自JAX-RS、Spring Web、Vert.x Reactive Routes和Servlet的资源。
Swagger UI
在Quarkus中,Swagger UI是默认包含的,当您现在浏览到 localhost:8080/swagger-ui 时,您将看到包含所有端点的UI

总结
在这篇文章中,我们探讨了Quarkus如何扩展MicroProfile OpenAPI规范,以便更轻松地记录您的端点。我们还讨论了如何使用它来记录任何Web框架。
如果您发现任何问题或有任何建议,请前往 SmallRye OpenAPI 项目,我们将在那里进行讨论。