使用Swagger和OpenAPI使RESTAPI文档变轻松

云平台

  Swagger和OpenAPI规范使我们能够轻松,无缝地设计和开发REST API。这些规范允许描述整个REST API的结构,以便机器可以读取和模拟它们。本文提供了有关这些概念的全面指南,并提供了所有主要Swagger组件的端到端示例。 (原文作者:Somnath Musib) https : //www.pexels.com/photo/low-angle-shot-of-high-rise-building-2096578/ Ø在过去的几年中,REST风格的Web服务引起了相当大的,并成为Web服务生态系统中的事实上的标准。它不仅隔开了它的复杂对象SOAP,而且已经成为API设计和开发中的默认选择。 API本质上是合同。API发布者及其使用者都必须遵守该合同,以进行有效的交流。与大多数其他合同一样,为了以预期的方式工作,API应该记录其各个方面。它提供的端点,端点的操作,操作可理解的签名以及针对请求返回的响应等方面?此外,为了适应不断变化的需求,API随着时间的推移而发展。在这种情况下,对API进行良好的文档编制不是一种选择,而是其产品所不可或缺的一部分,以确保获得更好的客户体验。 但是,我们如何记录我们的API?我们如何定义应作为文档齐全的API一部分的一组组件?此外,我们一直在更新我们的服务产品,因此需要维护这些API的多个版本。那我们如何版本API文档呢?一个可能具有数百个端点的API。我们甚至如何编写所有这些端点及其操作的文档?手动吗?决不。我们甚至如何确保消费者可以理解我们的API文档?有没有办法标准化API文档及其生成过程? 本文试图为上述问题提供答案。我们将讨论OpenAPI和围绕OpenAPI的工具-Swagger,该工具可帮助我们提供我们的API文档以及基于这些API的进一步开发。 什么是OpenAPI规范? OpenAPI规范(以前称为Swagger规范https://en.wikipedia.org/wiki/OpenAPI_Specification)是REST API的API描述格式。兼容OpenAPI规范的文件使我们能够描述完整的REST API。它通常以YAML(https://en.wikipedia.org/wiki/YAML)或JSON(https://en.wikipedia.org/wiki/JSON)文件格式编写。 该文件让我们:- 描述所有可用的API端点(例如/users, /users/{id})端点中的操作,例如GET /users,POST /user每个操作的输入和输出参数认证机制联系信息,API许可,使用条款和其他信息Swagger是什么? Swagger是围绕OpenAPI规范构建的一组开源工具,可以帮助我们设计,构建,记录和使用REST API。API描述其自身结构的能力是Swagger中所有出色功能的根源。请注意,Swagger不仅可以帮助我们设计和记录REST API,还可以让我们构建(服务器根节点)和消费端(其余客户端)之间的REST API。 Swagger的主要工具包括: Swagger Editor (http://editor.swagger.io/)-基于浏览器的编辑器,可以在其中编写OpenAPI规范Swagger UI(https://swagger.io/swagger-ui/) —将O​penAPI规范呈现为交互式API文档Swagger Codegen(https://github.com/swagger-api/swagger-codegen) —根据OpenAPI规范生成服务器根和客户端库我们将在本文中详细讨论上述三个工具。 以下是Swagger编辑器中的示例OpenAPI文档:- 图片提供:https : //swagger.io/docs/specification/basic-structure/ Swagger使用 现在既然我们已经了解了OpenAPI和Swagger是什么,那么让我们看看它们的实际作用。作为本文的一部分,我们将开发一个REST应用程序。然后,我们将使用Swagger UI呈现我们的API文档。然后,我们通过Swagger编辑器访问API文档(以JSON格式提供)。最后,我们将使用Swagger Codegen CLI生成服务器和客户端存根,以演示如何使用OpenAPI文档来模拟REST Web服务。 我们在建什么? 我们将构建一个Spring Boot应用程序,向我们提供管理献血者的功能。它允许我们创建,更新,删除和查看捐助者信息。 有关如何在开发环境中设置应用程序的逐步指南,请参考此链接(https://medium.com/codefountain/design-a-rest-api-with-spring-boot-and-mysql-a5572d94ccc7)。可以从此Github(https://github.com/musibs/swagger-medium-demo)存储库下载完整的源代码。 以下是步骤摘要: 使用JPA,H2和Web依赖关系创建一个新的Spring引导应用程序创建模型(model),服务(service)和控制器(controllers)运行该应用程序,然后尝试访问各种端点及其操作以下是应用程序pom文件: <?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.1.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>io.codefountain.swagger</groupId> <artifactId>swagger-medium-demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>swagger-medium-demo</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <depencies> <depency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </depency> <depency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </depency> <depency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </depency> <depency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </depency> <depency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </depency> <depency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </depency> <depency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </depency> </depencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build></project>pom.xml文件(https://gist.github.com/musibs/01d1fead61717823bdbdef1fe18a00e1/raw/76ad9a91233cda1a2b4ea51f26281e7414dd3b52/pom.xml) 我们从io.springfox添加了以下两个附加依赖项,以启用Swagger 2和Swagger UI:- <依赖> < groupId > io.springfox </ groupId > < artifactId > springfox-swagger2 </ artifactId > <版本> 2.9.2 </ version > </依赖> <依赖关系> < groupId > io.springfox </ groupId > < artifactId > springfox-swagger-ui </ artifactId > <版本> 2.9.2 </版本> </依赖>Swagger 的配置 现在该项目已启动并正在运行,我们可以访问我们的REST端点,让我们添加swagger配置:- package io.codefountain.swagger.configs;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import springfox.documentation.builders.ApiInfoBuilder;import springfox.documentation.builders.PathSelectors;import springfox.documentation.builders.RequestHandlerSelectors;import springfox.documentation.service.ApiInfo;import springfox.documentation.service.Contact;import springfox.documentation.spi.DocumentationType;import springfox.documentation.spring.web.plugins.Docket;import springfox.documentation.swagger2.annotations.EnableSwagger2;@Configuration@EnableSwagger2public class SwaggerConfiguration { @Bean public Docket api(){ return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.basePackage("io.codefountain.swagger")) .paths(PathSelectors.any()) .build().apiInfo(apiEndPointInfo()); } public ApiInfo apiEndPointInfo(){ return new ApiInfoBuilder().title("Spring Boot Rest API") .description("Donor Management API") .contact(new Contact("Somnath Musib", "medium.com/codefountain", "codefountain@gmail.com")) .license("Apache 2.0") .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html") .version("0.0.1-SNAPSHOT") .build(); }}Swagger 的配置(https://gist.github.com/musibs/38638a5f220628c54de6e3d6e27074ed/raw/652382db977773cc6b23df9ee6638945c50c170d/SwaggerConfiguration.java) 这是带有Swagger文档信息的Spring配置。我们添加了有关REST API的元数据信息,例如API名称,作者,网站,许可证等。我们还指示Swagger只为io.codefountain.swagger包中的组件生成文档。 访问Swagger UI 由于已启用Swagger,因此让我们查看Swagger完成的API端点的文档。这是通过以下链接中的Swagger UI呈现的: hhttp://localhost:8080//swagger-ui.html#/donor-controller Swagger默认文档 Swagger汇集了以下信息:- 文档元数据(metadata)(API名称,许可证(license),网站(website),联系人(contact)等)具有默认信息的所有REST端点都可以从代码中推断出这些信息。请注意,端点描述是方法名称这些是默认信息。现在,让我们用醒目的注释来显式地记录API的文档,以提供详细的描述以及有关端点和操作的信息。 记录Rest 控制器 如上所述,我们现在将明确记录REST控制器。Swagger提供了几个注释,以添加它在生成文档时提取的文档元数据。 对于每个REST端点及其关联的操作,我们都提供了ApiOperation及其各种响应以及ApiResponses批注。 package io.codefountain.swagger.controllers;import io.codefountain.swagger.exceptions.DonorAlreadyExistsException;import io.codefountain.swagger.exceptions.DonorNotFoundException;import io.codefountain.swagger.exceptions.GenericApiException;import io.codefountain.swagger.model.Donor;import io.codefountain.swagger.repository.DonorRepository;import io.swagger.annotations.Api;import io.swagger.annotations.ApiOperation;import io.swagger.annotations.ApiResponse;import io.swagger.annotations.ApiResponses;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.http.HttpStatus;import org.springframework.http.ResponseEntity;import org.springframework.web.bind.annotation.*;import javax.validation.ConstraintViolationException;import java.util.Optional;@RestController@RequestMapping("/api/donors")@Api(produces = "application/json", value = "Operations pertaining to manager blood donors in the application")public class DonorController { @Autowired private DonorRepository donorRepository; @PostMapping @ApiOperation(value = "Create a new donor", response = ResponseEntity.class) @ApiResponses(value = { @ApiResponse(code = 200, message = "Successfully created a new donor"), @ApiResponse(code = 401, message = "You are not authorized to view the resource"), @ApiResponse(code = 403, message = "Accessing the resource you were trying to reach is forbidden"), @ApiResponse(code = 404, message = "The resource you were trying to reach is not found"), @ApiResponse(code = 500, message = "Application failed to process the request") } ) public ResponseEntity<Donor> createDonor(@RequestBody Donor donor){ try{ Donor savedDonor = donorRepository.save(donor); return new ResponseEntity<Donor>(savedDonor, HttpStatus.OK); } catch(Exception e){ if( e instanceof ConstraintViolationException){ throw new DonorAlreadyExistsException(e.getMessage()); } throw new GenericApiException(e.getMessage()); } } @GetMapping @ApiOperation(value = "View all donors", response = Iterable.class) @ApiResponses(value = { @ApiResponse(code = 200, message = "Successfully retrieved all donors"), @ApiResponse(code = 401, message = "You are not authorized to view the resource"), @ApiResponse(code = 403, message = "Accessing the resource you were trying to reach is forbidden"), @ApiResponse(code = 404, message = "The resource you were trying to reach is not found"), @ApiResponse(code = 500, message = "Application failed to process the request") } ) public Iterable<Donor> getDonors(){ return donorRepository.findAll(); } @GetMapping("/{id}") @ApiOperation(value = "Retrieve specific donor with the supplied donor id", response = ResponseEntity.class) @ApiResponses(value = { @ApiResponse(code = 200, message = "Successfully retrieved the donor with the supplied id"), @ApiResponse(code = 401, message = "You are not authorized to view the resource"), @ApiResponse(code = 403, message = "Accessing the resource you were trying to reach is forbidden"), @ApiResponse(code = 404, message = "The resource you were trying to reach is not found"), @ApiResponse(code = 500, message = "Application failed to process the request") } ) public ResponseEntity<Donor> getDonor(@PathVariable("id") Long id){ Optional donor = donorRepository.findById(id); if(!donor.isPresent()){ return new ResponseEntity<Donor>(HttpStatus.NOT_FOUND); } return new ResponseEntity<Donor>((Donor) donor.get(), HttpStatus.OK); } @PutMapping @ApiOperation(value = "Update a donor information", response = ResponseEntity.class) @ApiResponses(value = { @ApiResponse(code = 200, message = "Successfully updated donor information"), @ApiResponse(code = 401, message = "You are not authorized to view the resource"), @ApiResponse(code = 403, message = "Accessing the resource you were trying to reach is forbidden"), @ApiResponse(code = 404, message = "The resource you were trying to reach is not found"), @ApiResponse(code = 500, message = "Application failed to process the request") } ) public ResponseEntity<Donor> UpdateDonor(@RequestBody Donor donor){ try{ Optional findDonor = donorRepository.findById(donor.getDonorId()); if(!findDonor.isPresent()){ throw new DonorNotFoundException("Donor with id "+donor.getDonorId()+" is not present"); } Donor savedDonor = donorRepository.save(donor); return new ResponseEntity<Donor>(savedDonor, HttpStatus.OK); } catch(Exception e){ e.printStackTrace(); return new ResponseEntity<Donor>(HttpStatus.INTERNAL_SERVER_ERROR); } } @DeleteMapping("/{id}") @ApiOperation(value = "Deletes specific donor with the supplied donor id") @ApiResponses(value = { @ApiResponse(code = 200, message = "Successfully deletes the specific donor"), @ApiResponse(code = 401, message = "You are not authorized to view the resource"), @ApiResponse(code = 403, message = "Accessing the resource you were trying to reach is forbidden"), @ApiResponse(code = 404, message = "The resource you were trying to reach is not found"), @ApiResponse(code = 500, message = "Application failed to process the request") } ) public void delete(@PathVariable("id") Long id){ donorRepository.deleteById(id); }}带有明确文档的REST控制器(https://gist.github.com/musibs/fd22dce69cd6fd3d0952ac91882ef374/raw/ed95a56dba7a3af8dc550361a1abc19c4a5dae5d/DonorController.java) 重新启动应用程序并访问相同的URL: 更新了Swagger文档 这次,Swagger提取了通过注释提供的信息。不仅如此,它现在还添加了带有HTTP响应代码的显式响应信息: 带有HTTP响应代码的API文档 访问Swagger编辑器 到目前为止,我们已经在本地访问了API文档。Swagger还会遵循OpenAPI规范以JSON文件格式生成文档。我们可以与使用者共享此JSON文件,他们可以读取端点信息,生成客户端和服务器存根。 可以通过以下URL访问我们的REST API文档:- http://localhost:8080/v2/api-docs { "swagger": "2.0", "info": { "description": "Donor Management API", "version": "0.0.1-SNAPSHOT", "title": "Spring Boot Rest API", "contact": { "name": "Somnath Musib", "url": "medium.com/codefountain", "email": "codefountain@gmail.com" }, "license": { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.html" } }, "host": "localhost:8080", "basePath": "/", "tags": [ { "name": "donor-controller", "description": "Donor Controller" } ], "paths": { "/api/donors": { "get": { "tags": [ "donor-controller" ], "summary": "View all donors", "operationId": "getDonorsUsingGET", "produces": [ "*/*" ], "responses": { "200": { "description": "Successfully retrieved all donors", "schema": { "$ref": "#/definitions/Iterable" } }, "401": { "description": "You are not authorized to view the resource" }, "403": { "description": "Accessing the resource you were trying to reach is forbidden" }, "404": { "description": "The resource you were trying to reach is not found" }, "500": { "description": "Application failed to process the request" } }, "deprecated": false }, "post": { "tags": [ "donor-controller" ], "summary": "Create a new donor", "operationId": "createDonorUsingPOST", "consumes": [ "application/json" ], "produces": [ "*/*" ], "parameters": [ { "in": "body", "name": "donor", "description": "donor", "required": true, "schema": { "$ref": "#/definitions/Donor" } } ], "responses": { "200": { "description": "Successfully created a new donor", "schema": { "$ref": "#/definitions/ResponseEntity" } }, "201": { "description": "Created" }, "401": { "description": "You are not authorized to view the resource" }, "403": { "description": "Accessing the resource you were trying to reach is forbidden" }, "404": { "description": "The resource you were trying to reach is not found" }, "500": { "description": "Application failed to process the request" } }, "deprecated": false }, "put": { "tags": [ "donor-controller" ], "summary": "Update a donor information", "operationId": "UpdateDonorUsingPUT", "consumes": [ "application/json" ], "produces": [ "*/*" ], "parameters": [ { "in": "body", "name": "donor", "description": "donor", "required": true, "schema": { "$ref": "#/definitions/Donor" } } ], "responses": { "200": { "description": "Successfully updated donor information", "schema": { "$ref": "#/definitions/ResponseEntity" } }, "201": { "description": "Created" }, "401": { "description": "You are not authorized to view the resource" }, "403": { "description": "Accessing the resource you were trying to reach is forbidden" }, "404": { "description": "The resource you were trying to reach is not found" }, "500": { "description": "Application failed to process the request" } }, "deprecated": false } }, "/api/donors/{id}": { "get": { "tags": [ "donor-controller" ], "summary": "Retrieve specific donor with the supplied donor id", "operationId": "getDonorUsingGET", "produces": [ "*/*" ], "parameters": [ { "name": "id", "in": "path", "description": "id", "required": true, "type": "integer", "format": "int64" } ], "responses": { "200": { "description": "Successfully retrieved the donor with the supplied id", "schema": { "$ref": "#/definitions/ResponseEntity" } }, "401": { "description": "You are not authorized to view the resource" }, "403": { "description": "Accessing the resource you were trying to reach is forbidden" }, "404": { "description": "The resource you were trying to reach is not found" }, "500": { "description": "Application failed to process the request" } }, "deprecated": false }, "delete": { "tags": [ "donor-controller" ], "summary": "Deletes specific donor with the supplied donor id", "operationId": "deleteUsingDELETE", "produces": [ "*/*" ], "parameters": [ { "name": "id", "in": "path", "description": "id", "required": true, "type": "integer", "format": "int64" } ], "responses": { "200": { "description": "Successfully deletes the specific donor" }, "204": { "description": "No Content" }, "401": { "description": "You are not authorized to view the resource" }, "403": { "description": "Accessing the resource you were trying to reach is forbidden" }, "404": { "description": "The resource you were trying to reach is not found" }, "500": { "description": "Application failed to process the request" } }, "deprecated": false } } }, "definitions": { "Donor": { "type": "object", "properties": { "bloodGroup": { "type": "string" }, "contactNo": { "type": "string" }, "dateOfBirth": { "type": "string", "format": "date" }, "donorId": { "type": "integer", "format": "int64" }, "emergencyContactNo": { "type": "string" }, "firstName": { "type": "string" }, "firstTimeDonor": { "type": "boolean" }, "lastName": { "type": "string" } }, "title": "Donor" }, "Iterable": { "type": "object", "title": "Iterable" }, "Iterable«Donor»": { "type": "object", "title": "Iterable«Donor»" }, "ResponseEntity": { "type": "object", "properties": { "body": { "type": "object" }, "statusCode": { "type": "string", "enum": [ "100 CONTINUE", "101 SWITCHING_PROTOCOLS", "102 PROCESSING", "103 CHECKPOINT", "200 OK", "201 CREATED", "202 ACCEPTED", "203 NON_AUTHORITATIVE_INFORMATION", "204 NO_CONTENT", "205 RESET_CONTENT", "206 PARTIAL_CONTENT", "207 MULTI_STATUS", "208 ALREADY_REPORTED", "226 IM_USED", "300 MULTIPLE_CHOICES", "301 MOVED_PERMANENTLY", "302 FOUND", "302 MOVED_TEMPORARILY", "303 SEE_OTHER", "304 NOT_MODIFIED", "305 USE_PROXY", "307 TEMPORARY_REDIRECT", "308 PERMANENT_REDIRECT", "400 BAD_REQUEST", "401 UNAUTHORIZED", "402 PAYMENT_REQUIRED", "403 FORBIDDEN", "404 NOT_FOUND", "405 METHOD_NOT_ALLOWED", "406 NOT_ACCEPTABLE", "407 PROXY_AUTHENTICATION_REQUIRED", "408 REQUEST_TIMEOUT", "409 CONFLICT", "410 GONE", "411 LENGTH_REQUIRED", "412 PRECONDITION_FAILED", "413 PAYLOAD_TOO_LARGE", "413 REQUEST_ENTITY_TOO_LARGE", "414 URI_TOO_LONG", "414 REQUEST_URI_TOO_LONG", "415 UNSUPPORTED_MEDIA_TYPE", "416 REQUESTED_RANGE_NOT_SATISFIABLE", "417 EXPECTATION_FAILED", "418 I_AM_A_TEAPOT", "419 INSUFFICIENT_SPACE_ON_RESOURCE", "420 METHOD_FAILURE", "421 DESTINATION_LOCKED", "422 UNPROCESSABLE_ENTITY", "423 LOCKED", "424 FAILED_DEPENCY", "425 TOO_EARLY", "426 UPGRADE_REQUIRED", "428 PRECONDITION_REQUIRED", "429 TOO_MANY_REQUESTS", "431 REQUEST_HEADER_FIELDS_TOO_LARGE", "451 UNAVAILABLE_FOR_LEGAL_REASONS", "500 INTERNAL_SERVER_ERROR", "501 NOT_IMPLEMENTED", "502 BAD_GATEWAY", "503 SERVICE_UNAVAILABLE", "504 GATEWAY_TIMEOUT", "505 HTTP_VERSION_NOT_SUPPORTED", "506 VARIANT_ALSO_NEGOTIATES", "507 INSUFFICIENT_STORAGE", "508 LOOP_DETECTED", "509 BANDWIDTH_LIMIT_EXCEEDED", "510 NOT_EXTED", "511 NETWORK_AUTHENTICATION_REQUIRED" ] }, "statusCodeValue": { "type": "integer", "format": "int32" } }, "title": "ResponseEntity" } }}api-docs.json(https://gist.github.com/musibs/caa48074703bd62489ba0dda428f4ba9/raw/3007a0b280a17b999ae520d778e0160ed5f5d879/api-docs.json) 该JSON文档符合OpenAPI规范,可以通过Swagger编辑器进行访问,如下所示: Swagger编辑器中的API文档 有权访问此文档的任何人都可以查看API端点和所有其他相关的元数据,例如模型结构,数据类型等。 Swagger Codegen存根 我们Swagger已经提供了两个漂亮的工具来管理文档生成和访问。第三个工具Swagger代码生成器使我们能够从提供的OpenAPI文档中生成服务器存根和客户端SDK。Swagger Codegen目前以下服务器(超过20种语言)和客户端SDK生成(超过40种语言): 图片提供:https : //swagger.io/tools/swagger-codegen/ Swagger Codegen可以通过命令行界面(codegen-cli)或Maven插件进行访问。在本文中,我们将使用Swagger代码生成CLI。要访问codegen CLI jar文件,您可以 从这里下载jar(https://search.maven.org/classic/remotecontent?filepath=io/swagger/swagger-codegen-cli/2.2.3/swagger-codegen-cli-2.2.3.jar)或者,如果您想要最新的更改,请浏览到Swagger Codegen Github存储库(https://github.com/swagger-api/swagger-codegen)并将其克隆到本地计算机。生成项目并浏览到swagger-codegen/modules/swagger-codegen-cli/target(https://github.com/swagger-api/swagger-codegen)文件夹生成Spring Boot服务器存根 我们将从OpenAPI文档中生成一个服务器存根。该存根可用于模拟和测试端点。当提供者可能已经共享了API文档但使用者没有访问提供者基础结构的权限时,这是一种常见情况。在这种情况下,模拟端点和操作以模拟API访问绝对至关重要。 在本节中,我们将生成服务器存根并实现GET映射/api/donors/{id} 要生成服务器根,请浏览至swagger codegen CLI jar文件的位置,然后运行以下命令: java -jar swagger-codegen-cli.jar generate-i C:\Somnath\Writing\Medium\docs\api-docs.json--api-package io.codefountain.swagger--model-package io.codefountain.swagger.client.model--invoker-package io.codefountain.swagger.client.invoker--group-id io.codefountain--artifact-id spring-swagger-codegen-api-client--artifact-version 0.0.1-SNAPSHOT-l spring-o C:\Somnath\Dev\Programming\Spring\donor-app-server--additional-properties dateLibrary=java8-localdatetime根生成命令 在上面的命令中,我们正在执行以下操作: 使用-i参数指定API规范的位置。根据您的环境位置更改此位置指定包结构。如果未提供此选项,则Swagger将使用默认的io.swagger包带-l选项的服务器根的类型最后,带有-o选项的spring boot项目的位置命令执行后,将生成带有所有端点根的spring boot项目。默认情况。

标签: 云平台