Documenting a Spring REST API Using OpenAPI 3.0
1.概述
文档是构建REST API的重要组成部分。 在本教程中,我们将看一下SpringDoc,它是一个基于OpenAPI 3规范简化了Spring Boot 1.x和2.x应用程序的API文档的生成和维护的工具。
进一步阅读:
使用Swagger生成Spring Boot REST Client
使用Spring REST API设置Swagger 2
Spring Cloud合约简介
2.设置springdoc-openapi
为了让springdoc-openapi自动为我们的API生成OpenAPI 3规范文档,我们只需将springdoc-openapi-ui依赖项添加到我们的pom.xml中:
1 2 3 4 5 | <dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-ui</artifactId> <version>1.2.32</version> </dependency> |
然后,当我们运行应用程序时,默认情况下,OpenAPI描述将在路径/ v3 / api-docs中可用-例如:
1 | http://localhost:8080/v3/api-docs/ |
要使用定制路径,我们可以在application.properties文件中指出:
1 | springdoc.api-docs.path=/api-docs |
现在,我们可以在以下位置访问文档:
1 | http://localhost:8080/api-docs/ |
默认情况下,OpenAPI定义为JSON格式。 对于yaml格式,我们可以在以下位置获取定义:
1 | http://localhost:8080/api-docs.yaml |
3.使用Swagger UI设置springdoc-openapi
除了自己生成OpenAPI 3规范外,我们还可以将springdoc-openapi与Swagger UI集成在一起,以便我们可以与我们的API规范进行交互并行使端点。
3.1。 Maven依赖
使用Swagger UI设置springdoc-openapi所要做的就是将依赖项springdoc-openapi-ui添加到项目的pom.xml中:
1 2 3 4 5 | <dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-ui</artifactId> <version>1.2.32</version> </dependency> |
现在,我们可以在以下位置访问API文档:
1 | http://localhost:8080/swagger-ui.html |
3.2。 支持swagger-ui属性
Springdoc-openapi还支持swagger-ui属性。 这些可以用作Spring Boot属性,带有前缀springdoc.swagger-ui。
例如,让我们自定义API文档的路径。 我们可以通过修改application.properties使其包括:
1 | springdoc.swagger-ui.path=/swagger-ui-custom.html |
因此,现在我们的API文档将在http:// localhost:8080 / swagger-ui-custom.html上提供。
再举一个例子,要按API方法的HTTP方法顺序对它们进行排序,我们可以添加:
1 | springdoc.swagger-ui.operationsSorter=method |
3.3。 样本API
<
假设我们的应用程序具有一个用于管理图书的控制器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | @RestController @RequestMapping("/api/book") public class BookController { @Autowired private BookRepository repository; @GetMapping("/{id}") public Book findById(@PathVariable long id) { return repository.findById(id) .orElseThrow(() -> new BookNotFoundException()); } @GetMapping("/") public Collection<Book> findBooks() { return repository.getBooks(); } @PutMapping("/{id}") @ResponseStatus(HttpStatus.OK) public Book updateBook( @PathVariable("id") final String id, @RequestBody final Book book) { return book; } } |
然后,当我们运行应用程序时,可以在以下位置查看文档:
1 | http://localhost:8080/swagger-ui-custom.html |
让我们深入到/ api / book端点,并查看其请求和响应的详细信息:
4.将springdoc-openapi与Spring WebFlux集成
通过添加springdoc-openapi-webflux-ui,我们可以将Springdoc-openapi和Swagger UI集成到Spring WebFlux项目中
1 2 3 4 5 | <dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-webflux-ui</artifactId> <version>1.2.32</version> </dependency> |
而且,像以前一样,可以在以下位置访问该文档:
1 | http://localhost:8080/swagger-ui.html |
为了自定义路径,在这里我们可以在application.properties中添加springdoc.swagger-ui.path属性。
5.公开分页信息
Spring Data JPA与Spring MVC无缝集成。 此类集成的一个示例是Pageable支持:
1 2 3 4 | @GetMapping("/filter") public Page<Book> filterBooks(Pageable pageable) { return repository.getBooks(pageable); } |
刚开始,我们可能希望SpringDoc在生成的文档中添加页面,大小和对查询参数进行排序。 但是,默认情况下,SpringDoc不满足此期望。 为了解锁此功能,我们应该添加springdoc-openapi-data-rest
1 2 3 4 5 | <dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-data-rest</artifactId> <version>1.2.32</version> </dependency> |
现在,它将预期的查询参数添加到文档中:
6.使用springdoc-openapi Maven插件
springdoc-openapi库提供了一个Maven插件springdoc-openapi-maven-plugin
springdoc-openapi-maven-plugin插件与spring-boot-maven插件一起使用。 Maven在集成测试阶段运行openapi插件。
让我们看看如何在pom.xml中配置插件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.1.8.RELEASE</version> <executions> <execution> <id>pre-integration-test</id> <goals> <goal>start</goal> </goals> </execution> <execution> <id>post-integration-test</id> <goals> <goal>stop</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-maven-plugin</artifactId> <version>0.2</version> <executions> <execution> <phase>integration-test</phase> <goals> <goal>generate</goal> </goals> </execution> </executions> </plugin> |
另外,我们可以配置插件以使用自定义值:
1 2 3 4 5 6 7 8 9 10 | <plugin> <executions> ......... </executions> <configuration> <apiDocsUrl>http://localhost:8080/v3/api-docs</apiDocsUrl> <outputFileName>openapi.json</outputFileName> <outputDir>${project.build.directory}</outputDir> </configuration> </plugin> |
让我们仔细看看我们可以为插件配置的参数:
apiDocsUrl –可以使用JSON格式访问文档的URL,默认为http:// localhost:8080 / v3 / api-docs
outputFileName –存储定义的文件的名称,默认为openapi.json
outputDir –文档存储目录的绝对路径–默认情况下,$ {project.build.directory}
7.使用JSR-303 Bean验证自动生成文档
当我们的模型包含JSR-303 bean验证批注(例如@ NotNull,@ NotBlank,@ Size,@ Min和@Max)时,springdoc-openapi库将使用它们来生成相应约束的其他模式文档。
让我们来看一个使用Book Bean的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
现在,为Book bean生成的文档提供了更多信息:
8.使用@ControllerAdvice和@ResponseStatus生成文档
在@RestControllerAdvice类中的方法上使用@ResponseStatus将自动生成响应代码的文档。 在此@RestControllerAdvice类中,这两种方法都用@ResponseStatus进行注释:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | @RestControllerAdvice public class GlobalControllerExceptionHandler { @ExceptionHandler(ConversionFailedException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public ResponseEntity<String> handleConnversion(RuntimeException ex) { return new ResponseEntity<>(ex.getMessage(), HttpStatus.BAD_REQUEST); } @ExceptionHandler(BookNotFoundException.class) @ResponseStatus(HttpStatus.NOT_FOUND) public ResponseEntity<String> handleBookNotFound(RuntimeException ex) { return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_FOUND); } } |
结果,我们现在可以看到响应代码400和404的文档:
9.使用@Operation和@ApiResponses生成文档
接下来,让我们看看如何使用几个特定于OpenAPI的注释向我们的API添加一些描述。
为此,我们将使用@Operation和@ApiResponses注释控制器的/ api / book / {id}端点:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | @Operation(summary ="Get a book by its id") @ApiResponses(value = { @ApiResponse(responseCode ="200", description ="Found the book", content = { @Content(mediaType ="application/json", schema = @Schema(implementation = Book.class)) }), @ApiResponse(responseCode ="400", description ="Invalid id supplied", content = @Content), @ApiResponse(responseCode ="404", description ="Book not found", content = @Content) }) @GetMapping("/{id}") public Book findById(@Parameter(description ="id of book to be searched") @PathVariable long id) { return repository.findById(id).orElseThrow(() -> new BookNotFoundException()); } |
效果如下:
如我们所见,添加到@Operation的文本位于API操作级别。 同样,添加到@ApiResponse容器批注中各种@ApiResponse元素的描述在此处也可见,这为我们的API响应增加了含义。
显然,我们没有得到以上响应400和404的任何模式。 因为我们为它们定义了一个空的@Content,所以仅显示它们的描述。
10. Kotlin支持
由于Spring Boot 2.x对Kotlin具有一流的支持,因此SpringDoc为Boot 2.x应用程序提供了开箱即用的JVM语言。
为了了解这一点,我们将在Kotlin中创建一个简单的Foo API。
初始设置后,我们将添加一个数据类和一个控制器。 我们将它们添加到Boot App的子包中,以便在运行时将FooController与早期的BookController一起使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | @Entity data class Foo( @Id val id: Long = 0, @NotBlank @Size(min = 0, max = 50) val name: String ="" ) @RestController @RequestMapping("/") class FooController() { val fooList: List = listOf(Foo(1,"one"), Foo(2,"two")) @Operation(summary ="Get all foos") @ApiResponses(value = [ ApiResponse(responseCode ="200", description ="Found Foos", content = [ (Content(mediaType ="application/json", array = ( ArraySchema(schema = Schema(implementation = Foo::class)))))]), ApiResponse(responseCode ="400", description ="Bad request", content = [Content()]), ApiResponse(responseCode ="404", description ="Did not find any Foos", content = [Content()])] ) @GetMapping("/foo") fun getAllFoos(): List = fooList } |
现在,当我们点击API文档URL时,我们还将看到Foo API:
为了增强对Kotlin类型的支持,我们可以添加以下依赖:
1 2 3 4 5 | <dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-kotlin</artifactId <version>1.3.9</version> </dependency> |
在那之后,我们的Foo模式将看起来更有用。 与添加JSR-303 Bean验证时类似:
11.结论
在本文中,我们学习了在项目中设置springdoc-openapi的过程。 然后,我们看到了如何将Springdoc-openapi与Swagger UI集成在一起。 我们还看到了如何使用Spring Webflux项目来做到这一点。
接下来,我们使用springdoc-openapi Maven插件为我们的API生成OpenAPI定义,并且我们了解了如何从Spring Data中公开分页和排序信息。 之后,我们研究了springdoc-openapi如何使用@ControllerAdvice类中的JSR 303 bean验证注释和@ResponseStatus注释自动生成文档。
然后,我们学习了如何使用一些特定于OpenAPI的注释向我们的API添加描述。 最后,我们窥视了OpenAPI对Kotlin的支持。
springdoc-openapi根据OpenAPI 3规范生成API文档。 此外,它还为我们处理Swagger UI配置,从而使API文档生成成为一个相当简单的任务。
与往常一样,该代码可在GitHub上获得。