使用OpenAPI Generator實現Open API Server
- java
- OpenAPI
1.概述
顧名思義, OpenAPI Generator會根據OpenAPI規範生成代碼。它可以為客戶端庫,服務器存根,文檔和配置創建代碼。
它支持各種語言和框架。值得注意的是,它支持C ++,C#,Java,PHP,Python,Ruby,Scala –幾乎所有廣泛使用的工具。
在本教程中,我們將學習如何通過OpenAPI Generator的maven插件實現基於Spring的服務器存根。使用生成器的其他方式是通過其CLI或在線工具。
2. YAML文件
首先,我們需要一個指定API的YAML文件。我們將其作為生成器的輸入,以生成服務器存根。
這是我們的petstore.yml
的片段:
openapi: "3.0.0" paths: /pets: get: summary: List all pets operationId: listPets tags: - pets parameters: - name: limit in: query ... responses: ... post: summary: Create a pet operationId: createPets ... /pets/{petId}: get: summary: Info for a specific pet operationId: showPetById ... components: schemas: Pet: type: object required: - id - name properties: id: type: integer format: int64 name: type: string tag: type: string Error: type: object required: - code - message properties: code: type: integer format: int32 message: type: string
3. Maven依賴
3.1 OpenAPI Generator的插件
接下來,讓我們為生成器插件添加Maven依賴項:
<plugin> <groupId>org.openapitools</groupId> <artifactId>openapi-generator-maven-plugin</artifactId> <version>5.1.0</version> <executions> <execution> <goals> <goal>generate</goal> </goals> <configuration> <inputSpec> ${project.basedir}/src/main/resources/petstore.yml </inputSpec> <generatorName>spring</generatorName> <apiPackage>com.baeldung.openapi.api</apiPackage> <modelPackage>com.baeldung.openapi.model</modelPackage> <supportingFilesToGenerate> ApiUtil.java </supportingFilesToGenerate> <configOptions> <delegatePattern>true</delegatePattern> </configOptions> </configuration> </execution> </executions> </plugin>
如我們所見,我們傳入YAML文件作為inputSpec
。之後,由於需要基於Spring的服務器,因此將generatorName
用作spring
。
然後apiPackage
指定將在其中生成API的程序包名稱。接下來,我們在生成器放置數據模型的地方放置了modelPackage
將delegatePattern
設置為true
,我們要求創建一個可以實現為自定義@Service
類的接口。
重要的**是,無論您使用的是CLI,Maven / Gradle插件還是在線生成選項,OpenAPI Generator的選項**都相同。
3.2 Spring依賴
在生成Spring服務器時,我們還需要其依賴項( Spring Boot Starter Web和Spring Data JPA ),以便生成的代碼可以按預期進行編譯和運行:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.4.4</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-jpa</artifactId> <version>2.4.6</version> </dependency> </dependencies>
4.代碼生成
要生成服務器存根,我們只需要運行:
mvn clean install
結果,我們得到:
現在讓我們看一下代碼,從apiPackage
的內容開始。
首先,**我們獲得一個名為PetsApi
**的API接口,其中包含YAML規範中定義的所有請求映射。這是代碼段:
@javax.annotation.Generated(value = "org.openapitools.codegen.languages.SpringCodegen", date = "2021-03-22T23:26:32.308871+05:30[Asia/Kolkata]") @Validated @Api(value = "pets", description = "the pets API") public interface PetsApi { /** * GET /pets : List all pets * * @param limit How many items to return at one time (max 100) (optional) * @return A paged array of pets (status code 200) * or unexpected error (status code 200) */ @ApiOperation(value = "List all pets", nickname = "listPets", notes = "", response = Pet.class, responseContainer = "List", tags={ "pets", }) @ApiResponses(value = { @ApiResponse(code = 200, message = "A paged array of pets", response = Pet.class, responseContainer = "List"), @ApiResponse(code = 200, message = "unexpected error", response = Error.class) }) @GetMapping(value = "/pets", produces = { "application/json" }) default ResponseEntity<List> listPets(@ApiParam( value = "How many items to return at one time (max 100)") @Valid @RequestParam(value = "limit", required = false) Integer limit) { return getDelegate().listPets(limit); } // other generated methods }
其次,由於我們使用委託模式,因此OpenAPI還會為我們PetsApiDelegate
特別是,在此接口中聲明的方法返回的HTTP狀態默認為501未實現:
@javax.annotation.Generated(value = "org.openapitools.codegen.languages.SpringCodegen", date = "2021-03-22T23:26:32.308871+05:30[Asia/Kolkata]") public interface PetsApiDelegate { /** * GET /pets : List all pets * * @param limit How many items to return at one time (max 100) (optional) * @return A paged array of pets (status code 200) * or unexpected error (status code 200) * @see PetsApi#listPets */ default ResponseEntity<List<Pet>> listPets(Integer limit) { getRequest().ifPresent(request -> { for (MediaType mediaType: MediaType.parseMediaTypes(request.getHeader("Accept"))) { if (mediaType.isCompatibleWith(MediaType.valueOf("application/json"))) { String exampleString = "{ \"name\" : \"name\", \"id\" : 0, \"tag\" : \"tag\" }"; ApiUtil.setExampleResponse(request, "application/json", exampleString); break; } } }); return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); } // other generated method declarations }
在那之後,我們看到有一個PetsApiController
類,它簡單地連接了委託者:
@javax.annotation.Generated(value = "org.openapitools.codegen.languages.SpringCodegen", date = "2021-03-22T23:26:32.308871+05:30[Asia/Kolkata]") @Controller @RequestMapping("${openapi.swaggerPetstore.base-path:}") public class PetsApiController implements PetsApi { private final PetsApiDelegate delegate; public PetsApiController( @org.springframework.beans.factory.annotation.Autowired(required = false) PetsApiDelegate delegate) { this.delegate = Optional.ofNullable(delegate).orElse(new PetsApiDelegate() {}); } @Override public PetsApiDelegate getDelegate() { return delegate; } }
在modelPackage
,基於YAML輸入中定義schemas
,生成Error
和Pet
的數據模型POJO。
讓我們看看其中一個– Pet
:
@javax.annotation.Generated(value = "org.openapitools.codegen.languages.SpringCodegen", date = "2021-03-22T23:26:32.308871+05:30[Asia/Kolkata]") public class Pet { @JsonProperty("id") private Long id; @JsonProperty("name") private String name; @JsonProperty("tag") private String tag; // constructor @ApiModelProperty(required = true, value = "") @NotNull public Long getId() { return id; } // other getters and setters // equals, hashcode, and toString methods }
5.測試服務器
現在,要使服務器存根作為服務器發揮作用,所需要做的就是添加委託者接口的實現。
為了簡單起見,在這裡我們不會這樣做,而僅測試存根。此外,在此之前,我們需要一個Spring Application
:
@SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
5.1 使用curl
啟動應用程序後,我們只需運行以下命令:
curl -I http://localhost:8080/pets/
這是預期的結果:
HTTP/1.1 501 Content-Length: 0 Date: Fri, 26 Mar 2021 17:29:25 GMT Connection: close
5.2 整合測試
另外,我們可以為它編寫一個簡單的集成測試:
@RunWith(SpringRunner.class) @SpringBootTest @AutoConfigureMockMvc public class OpenApiPetsIntegrationTest { private static final String PETS_PATH = "/pets/"; @Autowired private MockMvc mockMvc; @Test public void whenReadAll_thenStatusIsNotImplemented() throws Exception { this.mockMvc.perform(get(PETS_PATH)).andExpect(status().isNotImplemented()); } @Test public void whenReadOne_thenStatusIsNotImplemented() throws Exception { this.mockMvc.perform(get(PETS_PATH + 1)).andExpect(status().isNotImplemented()); } }
六,結論
在本教程中,我們看到瞭如何使用OpenAPI生成器的maven插件根據YAML規範生成基於Spring的服務器存根。