第 54 章 使用 Swagger 支持扩展 JAX-RS 端点
摘要
CXF Swagger2Feature (org.apache.cxf.jaxrs.swagger.Swagger2Feature
)允许您通过扩展具有简单配置的 JAX-RS 服务端点来生成 Swagger 2.0 文档。
Swagger2Feature 在 Spring Boot 和 Karaf 实现中受到支持。
54.1. Swagger2Feature 选项
您可以在 Swagger2Feature 中使用以下选项:
名称 | 描述 | 默认 |
---|---|---|
|
上下文根路径+(请参阅 | null |
| 您的联系信息+ | |
| description+ | "应用程序" |
| 安全过滤器+ | null |
| 主机和端口信息+ | null |
|
扫描所有资源时排除特定路径(请参阅 | null |
| 许可证+ | "Apache 2.0 许可证" |
| 许可证 URL+ | |
|
当生成 | false |
| 以逗号分隔的软件包名称列表,其中资源必须扫描+ | 在端点中配置的服务类列表 |
| 作为过滤器运行该功能 | false |
| 生成 swagger 文档+ | true |
|
扫描包括非注解 JAX-RS 资源的所有资源(请参阅 | false |
| 协议方案+ | null |
| Swagger UI 配置 | null |
| 服务 URL+ 条款. | null |
| 标题+ | "sample REST Application" |
|
防止 Swagger 缓存 | false |
| 版本+ | "1.0.0" |
+ 选项在 Swagger 的 BeanConfig 中定义
++ 选项在 Swagger 的 ReaderConfig 中定义
=== Karaf 实施
这部分论述了如何使用在 JAR 文件中定义 REST 服务的 Swagger2Feature,并部署到 Karaf 容器上的 Fuse。
==== Quickstart 示例
您可以从 Fuse Software Downloads 页面下载
Red Hat Fuse Quickstarts。
Quickstart zip 文件包含快速入门的 /cxf/rest/
目录,它演示了如何使用 CXF 创建 RESTful (JAX-RS) Web 服务,以及如何启用 Swagger 并注解 JAX-RS 端点。
==== 启用 Swagger
启用 Swagger 包括:
通过将 CXF 类(
org.apache.cxf.jaxrs.swagger.Swagger.Swagger2Feature )添加到 <
> 定义,修改定义 CXF 服务的 XML 文件。jaxrs
:server例如,请参阅 55.4 示例 XML 文件示例。
在 REST 资源类中:
为服务所需的每个注解导入 Swagger API 注解:
import io.swagger.annotations.*
其中 * =
Api
,ApiOperation
,ApiResponse
, ApiResponse ,ApiResponses
等等。详情请参阅
https://github.com/swagger-api/swagger-core/wiki/Annotations
。例如,请参阅 55.5 示例资源类。
-
将 Swagger 注释添加到 JAX-RS 注释(
@PATH
、@PUT
、@POST
、@GET
、@Produces
、@Consumes
、@DELETE
、@PathParam
等等)。
例如,请参阅 55.5 示例资源类。
55.4 示例 XML 文件示例
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxrs="http://cxf.apache.org/blueprint/jaxrs" xmlns:cxf="http://cxf.apache.org/blueprint/core" xsi:schemaLocation=" http://www.osgi.org/xmlns/blueprint/v1.0.0 https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd http://cxf.apache.org/blueprint/jaxrs http://cxf.apache.org/schemas/blueprint/jaxrs.xsd http://cxf.apache.org/blueprint/core http://cxf.apache.org/schemas/blueprint/core.xsd"> <jaxrs:server id="customerService" address="/crm"> <jaxrs:serviceBeans> <ref component-id="customerSvc"/> </jaxrs:serviceBeans> <jaxrs:providers> <bean class="com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider"/> </jaxrs:providers> <jaxrs:features> <bean class="org.apache.cxf.jaxrs.swagger.Swagger2Feature"> <property name="title" value="Fuse:CXF:Quickstarts - Customer Service" /> <property name="description" value="Sample REST-based Customer Service" /> <property name="version" value="${project.version}" /> </bean> </jaxrs:features> </jaxrs:server> <cxf:bus> <cxf:features> <cxf:logging /> </cxf:features> <cxf:properties> <entry key="skip.default.json.provider.registration" value="true" /> </cxf:properties> </cxf:bus> <bean id="customerSvc" class="org.jboss.fuse.quickstarts.cxf.rest.CustomerService"/> </blueprint>
55.5 示例资源类
. . . import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.Context; import javax.ws.rs.core.Response; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import io.swagger.annotations.ApiResponse; import io.swagger.annotations.ApiResponses; . . . @Path("/customerservice/") @Api(value = "/customerservice", description = "Operations about customerservice") public class CustomerService { private static final Logger LOG = LoggerFactory.getLogger(CustomerService.class); private MessageContext jaxrsContext; private long currentId = 123; private Map<Long, Customer> customers = new HashMap<>(); private Map<Long, Order> orders = new HashMap<>(); public CustomerService() { init(); } @GET @Path("/customers/{id}/") @Produces("application/xml") @ApiOperation(value = "Find Customer by ID", notes = "More notes about this method", response = Customer.class) @ApiResponses(value = { @ApiResponse(code = 500, message = "Invalid ID supplied"), @ApiResponse(code = 204, message = "Customer not found") }) public Customer getCustomer(@ApiParam(value = "ID of Customer to fetch", required = true) @PathParam("id") String id) { LOG.info("Invoking getCustomer, Customer id is: {}", id); long idNumber = Long.parseLong(id); return customers.get(idNumber); } @PUT @Path("/customers/") @Consumes({ "application/xml", "application/json" }) @ApiOperation(value = "Update an existing Customer") @ApiResponses(value = { @ApiResponse(code = 500, message = "Invalid ID supplied"), @ApiResponse(code = 204, message = "Customer not found") }) public Response updateCustomer(@ApiParam(value = "Customer object that needs to be updated", required = true) Customer customer) { LOG.info("Invoking updateCustomer, Customer name is: {}", customer.getName()); Customer c = customers.get(customer.getId()); Response r; if (c != null) { customers.put(customer.getId(), customer); r = Response.ok().build(); } else { r = Response.notModified().build(); } return r; } @POST @Path("/customers/") @Consumes({ "application/xml", "application/json" }) @ApiOperation(value = "Add a new Customer") @ApiResponses(value = { @ApiResponse(code = 500, message = "Invalid ID supplied"), }) public Response addCustomer(@ApiParam(value = "Customer object that needs to be updated", required = true) Customer customer) { LOG.info("Invoking addCustomer, Customer name is: {}", customer.getName()); customer.setId(++currentId); customers.put(customer.getId(), customer); if (jaxrsContext.getHttpHeaders().getMediaType().getSubtype().equals("json")) { return Response.ok().type("application/json").entity(customer).build(); } else { return Response.ok().type("application/xml").entity(customer).build(); } } @DELETE @Path("/customers/{id}/") @ApiOperation(value = "Delete Customer") @ApiResponses(value = { @ApiResponse(code = 500, message = "Invalid ID supplied"), @ApiResponse(code = 204, message = "Customer not found") }) public Response deleteCustomer(@ApiParam(value = "ID of Customer to delete", required = true) @PathParam("id") String id) { LOG.info("Invoking deleteCustomer, Customer id is: {}", id); long idNumber = Long.parseLong(id); Customer c = customers.get(idNumber); Response r; if (c != null) { r = Response.ok().build(); customers.remove(idNumber); } else { r = Response.notModified().build(); } return r; } . . . }
=== Spring Boot 实施
这部分论述了如何在 Spring Boot 中使用 Swagger2Feature。
==== Quickstart 示例
Quickstart 示例(https://github.com/fabric8-quickstarts/spring-boot-cxf-jaxrs
)演示了如何在 Spring Boot 中使用 Apache CXF。Quickstart 使用 Spring Boot 配置一个应用程序,这些应用程序包括启用了 Swagger 的 CXF JAX-RS 端点。
==== 启用 Swagger
启用 Swagger 包括:
在 REST 应用程序中:
导入 Swagger2Feature:
import org.apache.cxf.jaxrs.swagger.Swagger2Feature;
在 CXF 端点中添加 Swagger2Feature:
endpoint.setFeatures(Arrays.asList(new Swagger2Feature()));
例如,请参阅 55.1 示例 REST 应用程序。
在 Java 实施文件中,为服务所需的每个注解导入 Swagger API 注解:
import io.swagger.annotations.*
其中 * =
Api
,ApiOperation
,ApiResponse
, ApiResponse ,ApiResponses
等等。详情请查看
https://github.com/swagger-api/swagger-core/wiki/Annotations
。例如,请参阅 55.2 示例 Java 实施文件。
在 Java 文件中,将 Swagger 注释添加到 JAX-RS 注释(
@PATH
、@PUT
、@POST
、@GET
、@Produces
、@Consumes
、@DELETE
、@PathParam
等等)。例如,请参阅 55.3 示例 Java 文件。
55.1 示例 REST 应用程序
package io.fabric8.quickstarts.cxf.jaxrs; import java.util.Arrays; import org.apache.cxf.Bus; import org.apache.cxf.endpoint.Server; import org.apache.cxf.jaxrs.JAXRSServerFactoryBean; import org.apache.cxf.jaxrs.swagger.Swagger2Feature; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; @SpringBootApplication public class SampleRestApplication { @Autowired private Bus bus; public static void main(String[] args) { SpringApplication.run(SampleRestApplication.class, args); } @Bean public Server rsServer() { // setup CXF-RS JAXRSServerFactoryBean endpoint = new JAXRSServerFactoryBean(); endpoint.setBus(bus); endpoint.setServiceBeans(Arrays.<Object>asList(new HelloServiceImpl())); endpoint.setAddress("/"); endpoint.setFeatures(Arrays.asList(new Swagger2Feature())); return endpoint.create(); } }
55.2 示例 Java 实施文件
import io.swagger.annotations.Api; @Api("/sayHello") public class HelloServiceImpl implements HelloService { public String welcome() { return "Welcome to the CXF RS Spring Boot application, append /{name} to call the hello service"; } public String sayHello(String a) { return "Hello " + a + ", Welcome to CXF RS Spring Boot World!!!"; } }
55.3 示例 Java 文件
package io.fabric8.quickstarts.cxf.jaxrs; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import org.springframework.stereotype.Service; @Path("/sayHello") @Service public interface HelloService { @GET @Path("") @Produces(MediaType.TEXT_PLAIN) String welcome(); @GET @Path("/{a}") @Produces(MediaType.TEXT_PLAIN) String sayHello(@PathParam("a") String a); }