1. Overview
1.概述
Documentation is an essential part of building REST APIs. In this tutorial, we’ll take a look at SpringDoc — a tool that simplifies the generation and maintenance of API docs based on the OpenAPI 3 specification for Spring Boot 1.x and 2.x applications.
文档是构建REST API的一个重要部分。在本教程中,我们将看看SpringDoc–一个简化了Spring Boot 1.x和2.x应用程序基于OpenAPI 3规范的API文档生成和维护的工具。
2. Setting up springdoc-openapi
2.设置springdoc-openapi
To have springdoc-openapi automatically generate the OpenAPI 3 specification docs for our API, we simply add the springdoc-openapi-ui dependency to our pom.xml:
为了让springdoc-openapi自动为我们的API生成OpenAPI 3规范文档,我们只需将springdoc-openapi-ui依赖关系加入我们的pom.xml。
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.6.4</version>
</dependency>
Then when we run our application, the OpenAPI descriptions will be available at the path /v3/api-docs by default:
然后当我们运行我们的应用程序时,OpenAPI描述将在路径/v3/api-docs中默认可用。
http://localhost:8080/v3/api-docs/
To use a custom path, we can indicate in the application.properties file:
要使用一个自定义的路径,我们可以在application.properties文件中说明。
springdoc.api-docs.path=/api-docs
Now we’ll be able to access the docs at:
现在,我们将能够在以下地点访问这些文件。
http://localhost:8080/api-docs/
The OpenAPI definitions are in JSON format by default. For yaml format, we can obtain the definitions at:
OpenAPI的定义默认为JSON格式。对于yaml格式,我们可以在以下网站获得定义。
http://localhost:8080/api-docs.yaml
3. Integration with Swagger UI
3.与Swagger UI的整合
Besides generating the OpenAPI 3 specification itself, we can integrate springdoc-openapi with Swagger UI so that we can interact with our API specification and exercise the endpoints.
除了生成OpenAPI 3规范本身,我们还可以将springdoc-openapi与Swagger UI集成,这样我们就可以与我们的API规范进行交互,并行使端点。
The springdoc-openapi dependency already includes Swagger UI, so we’re all set here.
springdoc-openapi依赖性已经包括了Swagger UI,所以我们在这里都准备好了。
We can simply access the API documentation at:
我们可以简单地访问API文档:。
http://localhost:8080/swagger-ui.html
3.1. Support for swagger-ui Properties
3.1.对swagger-ui属性的支持
Springdoc-openapi also supports swagger-ui properties. These can be used as Spring Boot properties, with the prefix springdoc.swagger-ui.
Springdoc-openapi还支持swagger-ui属性。这些可以作为Spring Boot属性使用,其前缀为springdoc.swagger-ui。
For example, let’s customize the path of our API documentation. We can do this by modifying our application.properties to include:
例如,让我们自定义我们的API文档的路径。我们可以通过修改我们的application.properties来做到这一点,包括。
springdoc.swagger-ui.path=/swagger-ui-custom.html
So now our API documentation will be available at http://localhost:8080/swagger-ui-custom.html.
因此,现在我们的API文档将在http://localhost:8080/swagger-ui-custom.html上提供。
As another example, to sort the API paths in order of their HTTP methods, we can add:
再比如,为了按照HTTP方法的顺序对API路径进行排序,我们可以添加。
springdoc.swagger-ui.operationsSorter=method
3.2. Sample API
3.2.示例API
Suppose our application has a controller for managing Books:
假设我们的应用程序有一个控制器来管理Books。
@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;
}
}
Then when we run our application, we can view the documentation at:
然后,当我们运行我们的应用程序时,我们可以在以下位置查看文档。
http://localhost:8080/swagger-ui-custom.html
Let’s drill down to the /api/book endpoint and see the details for its request and response:
让我们深入到 /api/book 端点,看看其请求和响应的细节:
4. Integrating springdoc-openapi With Spring WebFlux
4.将springdoc-openapi与Spring WebFlux相结合
We can integrate springdoc-openapi and Swagger UI in a Spring WebFlux project by adding springdoc-openapi-webflux-ui:
我们可以通过添加springdoc-openapi-webflux-ui在Spring WebFlux项目中集成springdoc-openapi和Swagger UI。
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-webflux-ui</artifactId>
<version>1.6.4</version>
</dependency>
As before, the docs will be accessible at:
和以前一样,这些文件可以在以下网站上查阅。
http://localhost:8080/swagger-ui.html
In order to customize the path, we could again add the springdoc.swagger-ui.path property in our application.properties.
为了自定义路径,我们可以再次在我们的application.properties中添加springdoc.swagger-ui.path属性。
5. Exposing Pagination Information
5.暴露分页信息
Spring Data JPA integrates with Spring MVC quite seamlessly. One example of such integration is Pageable support:
Spring Data JPA与Spring MVC进行了相当无缝的集成。这种整合的一个例子是Pageable支持。
@GetMapping("/filter")
public Page<Book> filterBooks(@ParameterObject Pageable pageable) {
return repository.getBooks(pageable);
}
The support for Pageable is available out-0f-the box since springdoc-openapi v1.6.0 . Page, size, and sort query parameters get added to the generated documentation.:
从springdoc-openapi v1.6.0开始,对Pageable的支持是开箱即用的。Page、size和sort查询参数被添加到生成的文档中。
6. Using springdoc-openapi Maven Plugin
6.使用springdoc-openapi Maven插件
The springdoc-openapi library provides a Maven plugin springdoc-openapi-maven-plugin for generating OpenAPI descriptions in json and yaml formats.
springdoc-openapi库提供了一个Maven插件springdoc-openapi-maven-plugin,用于生成json和yaml格式的OpenAPI描述。
The springdoc-openapi-maven-plugin plugin works with the spring-boot-maven plugin. Maven runs the openapi plugin during the integration-test phase.
springdoc-openapi-maven-plugin插件与spring-boot-maven插件协同工作。Maven在集成测试阶段运行openapiplugin。
Let’s see how we can configure the plugin in our pom.xml:
让我们看看如何在我们的pom.xml中配置该插件。
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.3.3.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>
We can also configure the plugin to use custom values:
我们还可以配置该插件以使用自定义值。
<plugin>
<executions>
.........
</executions>
<configuration>
<apiDocsUrl>http://localhost:8080/v3/api-docs</apiDocsUrl>
<outputFileName>openapi.json</outputFileName>
<outputDir>${project.build.directory}</outputDir>
</configuration>
</plugin>
Let’s take a closer look at the parameters that we can configure for the plugin:
让我们仔细看看我们可以为该插件配置的参数。
- apiDocsUrl – URL where the docs can be accessed in JSON format, with a default of http://localhost:8080/v3/api-docs
- outputFileName – Name of the file where the definitions are stored, defaults to openapi.json
- outputDir – Absolute path for the directory where the docs are stored, by default ${project.build.directory}
7. Automatic Document Generation Using JSR-303 Bean Validation
7.使用JSR-303 Bean验证的自动文档生成
When our model includes JSR-303 bean validation annotations, such as @NotNull, @NotBlank, @Size, @Min, and @Max, the springdoc-openapi library uses them to generate additional schema documentation for the corresponding constraints.
当我们的模型包括JSR-303Bean验证注解时,例如@NotNull, @NotBlank, @Size, @Min, 和@Max,springdoc-openapi库使用它们来为相应的约束生成额外的模式文档。
Let’s see an example using our Book bean:
让我们看一个使用我们的Book bean的例子。
public class Book {
private long id;
@NotBlank
@Size(min = 0, max = 20)
private String title;
@NotBlank
@Size(min = 0, max = 30)
private String author;
}
Now the documentation generated for the Book bean is a little more informative:
8. Generate Documentation Using @ControllerAdvice and @ResponseStatus
8.使用@ControllerAdvice和@ResponseStatus生成文档
Using @ResponseStatus on methods in a @RestControllerAdvice class will automatically generate documentation for the response codes. In this @RestControllerAdvice class, the two methods are annotated with @ResponseStatus:
在@RestControllerAdvice类中的方法上使用@ResponseStatus将自动生成响应代码的文档。在这个@RestControllerAdvice类中,两个方法被注解为@ResponseStatus。
@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);
}
}
As a result, we can now see the documentation for the response codes 400 and 404:
9. Generate Documentation Using @Operation and @ApiResponses
9.使用@Operation和@ApiResponses生成文档
Next let’s see how we can add some description to our API using a couple of OpenAPI-specific annotations.
接下来让我们看看如何使用几个OpenAPI专用注释为我们的API添加一些描述。
In order to do that, we’ll annotate our controller’s /api/book/{id} endpoint with @Operation and @ApiResponses:
为了做到这一点,我们将在控制器的/api/book/{id}注解@Operation和@ApiResponses端点。
@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());
}
Here’s the effect:
效果是这样的。
As we can see, the text we added to @Operation is placed at the API operation level. Similarly, the description added to various @ApiResponse elements in the @ApiResponses container annotation is also visible here, adding meaning to our API responses.
我们可以看到,我们添加到@Operation的文本被放置在API操作层面。同样,添加到@ApiResponse容器注解中的各种@ApiResponses元素的描述在这里也是可见的,为我们的API响应增加了意义。
Evidently, we do not get any schema for the responses 400 and 404 above. As we defined an empty @Content for them, only their descriptions are displayed.
很明显,我们没有得到上述400和404响应的任何模式。由于我们为它们定义了一个空的@Content,只有它们的描述被显示出来。
10. Kotlin Support
10.Kotlin支持
Since Spring Boot 2.x has first-class support for Kotlin, SpringDoc supports this JVM language out of the box for Boot 2.x applications.
由于Spring Boot 2.x对Kotlin有一流的支持,SpringDoc对Boot 2.x应用程序支持这种JVM语言,开箱即用。
To see this in action, we’ll create a simple Foo API in Kotlin.
为了看到这一点,我们将在Kotlin中创建一个简单的Foo API。
After the initial setup, we’ll add a data class and a controller. We’ll add them in a sub-package of our Boot App so that when it’s run, it picks our FooController up along with the earlier BookController:
在初始设置之后,我们将添加一个数据类和一个控制器。我们将把它们添加到Boot App的一个子包中,这样当它运行时,就会把我们的FooController和先前的BookController一起拿过来。
@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
}
Now when we hit our API documentation URL, we’ll see the Foo API as well:
现在当我们点击我们的API文档URL时,我们也会看到Foo API。
To enhance the support of Kotlin types, we can add this dependency:
为了加强对Kotlin类型的支持,我们可以添加这个依赖项。
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-kotlin</artifactId
<version>1.6.4</version>
</dependency>
After that, our Foo schema will look more informative, as it did when we added JSR-303 Bean Validation:
之后,我们的Foo模式将看起来更有信息量,就像我们添加JSR-303 Bean验证时那样。
11. Conclusion
11.结论
In this article, we learned to set up springdoc-openapi in our projects. Then we saw how to integrate springdoc-openapi with the Swagger UI. We also saw how to do this with Spring Webflux projects.
在这篇文章中,我们学习了如何在我们的项目中设置springdoc-openapi。然后我们看到了如何将springdoc-openapi与Swagger UI集成。我们还看到了如何在Spring Webflux项目中这样做。
Next we used the springdoc-openapi Maven Plugin to generate OpenAPI definitions for our APIs, and we saw how to expose paging and sorting information from Spring Data. After that, we looked at how springdoc-openapi generates documentation automatically using JSR 303 bean validation annotations and the @ResponseStatus annotations in @ControllerAdvice class.
接下来我们使用springdoc-openapi Maven插件为我们的API生成OpenAPI定义,我们看到了如何从Spring Data中公开分页和排序信息。之后,我们看了springdoc-openapi如何使用JSR 303 Bean验证注解和@ControllerAdvice类中的@ResponseStatus注解自动生成文档。
We also learned how to add a description to our API using a few OpenAPI-specific annotations. Finally, we took a peek at OpenAPI’s support of Kotlin.
我们还学习了如何使用一些OpenAPI特有的注解来为我们的API添加描述。最后,我们看了一下OpenAPI对Kotlin的支持。
The springdoc-openapi generates API documentation as per OpenAPI 3 specification. Moreover, it also handles the Swagger UI configuration for us, making API document generation a fairly simple task.
springdoc-openapi按照OpenAPI 3规范生成API文档。此外,它还为我们处理Swagger用户界面的配置,使API文档的生成成为一项相当简单的任务。
As always, the code is available over on GitHub.
像往常一样,代码可在GitHub上获得。