1. Обзор
Документация является неотъемлемой частью создания REST API. В этом руководстве мы рассмотрим SpringDoc — инструмент, который упрощает создание и обслуживание документации по API на основе спецификации OpenAPI 3 для приложений Spring Boot 1.x и 2.x.
2. Настройка springdoc-openapi
Чтобы springdoc-openapi автоматически генерировал документы спецификации OpenAPI 3 для нашего API, мы просто добавляем зависимость springdoc-openapi-ui
в наш pom.xml
:
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.6.4</version>
</dependency>
Затем, когда мы запустим наше приложение, описания OpenAPI по умолчанию будут доступны по пути /v3/api-docs
:
http://localhost:8080/v3/api-docs/
Чтобы использовать собственный путь, мы можем указать в файле application.properties :
springdoc.api-docs.path=/api-docs
Теперь мы сможем получить доступ к документам по адресу:
http://localhost:8080/api-docs/
Определения OpenAPI `по умолчанию имеют формат JSON. Для формата
yaml` мы можем получить определения по адресу:
http://localhost:8080/api-docs.yaml
3. Настройка springdoc-openapi с пользовательским интерфейсом Swagger
Помимо создания самой спецификации OpenAPI 3, мы можем интегрировать springdoc-openapi с пользовательским интерфейсом Swagger, чтобы мы могли взаимодействовать с нашей спецификацией API и использовать конечные точки.
3.1. Зависимость от Maven
Все, что нам нужно сделать, чтобы настроить springdoc-openapi с пользовательским интерфейсом Swagger, — это добавить зависимость springdoc-openapi-ui
в pom.xml
проекта :
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.6.4</version>
</dependency>
Теперь мы можем получить доступ к документации API по адресу:
http://localhost:8080/swagger-ui.html
3.2. Поддержка свойств swagger-ui
Springdoc-openapi также поддерживает свойства swagger -ui
. Их можно использовать как свойства Spring Boot с префиксом springdoc.swagger-ui
.
Например, давайте настроим путь к нашей документации по API. Мы можем сделать это, изменив наш application.properties
, включив в него:
springdoc.swagger-ui.path=/swagger-ui-custom.html
Итак, теперь наша документация по API будет доступна по адресу http://localhost:8080/swagger-ui-custom.html
.
В качестве другого примера, чтобы отсортировать пути API в порядке их HTTP-методов, мы можем добавить:
springdoc.swagger-ui.operationsSorter=method
3.3. Пример API
Предположим, что в нашем приложении есть контроллер для управления 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;
}
}
Затем, когда мы запускаем наше приложение, мы можем просмотреть документацию по адресу:
http://localhost:8080/swagger-ui-custom.html
Давайте перейдем к конечной точке /api/book
и посмотрим подробности ее запроса и ответа:
4. Интеграция springdoc-openapi с Spring WebFlux
Мы можем интегрировать springdoc-openapi и пользовательский интерфейс Swagger в проект Spring WebFlux, добавив springdoc-openapi-webflux-ui
:
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-webflux-ui</artifactId>
<version>1.6.4</version>
</dependency>
Как и прежде, документы будут доступны по адресу:
http://localhost:8080/swagger-ui.html
Чтобы настроить путь, мы могли бы снова добавить свойство springdoc.swagger-ui.path
в наш application.properties
.
5. Разоблачение информации о разбиении на страницы
Spring Data JPA легко интегрируется с Spring MVC. Одним из примеров такой интеграции является поддержка Pageable
:
@GetMapping("/filter")
public Page<Book> filterBooks(@ParameterObject Pageable pageable) {
return repository.getBooks(pageable);
}
Сначала мы могли бы ожидать, что SpringDoc добавит параметры запроса страницы
, размера
и сортировки
в сгенерированную документацию. Однако по умолчанию SpringDoc не соответствует этому ожиданию. Чтобы разблокировать эту функцию, мы должны добавить зависимость springdoc-openapi-data-rest
:
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-data-rest</artifactId>
<version>1.6.4</version>
</dependency>
Теперь он добавляет в документацию ожидаемые параметры запроса:
6. Использование плагина Springdoc-openapi Maven
Библиотека springdoc-openapi предоставляет подключаемый модуль Maven springdoc-openapi-maven-plugin
для создания описаний OpenAPI в форматах json
и yaml
.
Плагин springdoc-openapi-maven-
plugin работает с плагином spring-boot-maven
. Maven запускает подключаемый модуль openapi на этапе
интеграционного тестирования
.
Давайте посмотрим, как мы можем настроить плагин в нашем 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>
Мы также можем настроить плагин для использования пользовательских значений:
<plugin>
<executions>
.........
</executions>
<configuration>
<apiDocsUrl>http://localhost:8080/v3/api-docs</apiDocsUrl>
<outputFileName>openapi.json</outputFileName>
<outputDir>${project.build.directory}</outputDir>
</configuration>
</plugin>
Давайте подробнее рассмотрим параметры, которые мы можем настроить для плагина:
apiDocsUrl
— URL-адрес, по которому можно получить доступ к документам в формате JSON, по умолчаниюhttp://localhost:8080/v3/api-docs.
outputFileName
— имя файла, в котором хранятся определения, по умолчанию —openapi.json.
outputDir
— абсолютный путь к каталогу, в котором хранятся документы, по умолчанию${project.build.directory}
7. Автоматическая генерация документов с использованием проверки компонентов JSR-303
Когда наша модель включает аннотации проверки бина JSR-303, такие как @NotNull
, @NotBlank
, @Size
, @Min
и @Max
, библиотека springdoc-openapi использует их для создания дополнительной документации схемы для соответствующих ограничений.
Давайте посмотрим на пример, используя наш bean-компонент Book
:
public class Book {
private long id;
@NotBlank
@Size(min = 0, max = 20)
private String title;
@NotBlank
@Size(min = 0, max = 30)
private String author;
}
Теперь документация, сгенерированная для компонента Book
, стала немного более информативной:
8. Создайте документацию, используя @ControllerAdvice
и @ResponseStatus
Использование @ResponseStatus
для методов в классе @RestControllerAdvice
автоматически создаст документацию для кодов ответов. В этом классе @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);
}
}
В результате теперь мы можем увидеть документацию для кодов ответа 400 и 404:
9. Создайте документацию, используя @Operation
и @ApiResponses
Далее давайте посмотрим, как мы можем добавить некоторое описание к нашему API, используя пару аннотаций, специфичных для OpenAPI .
Для этого мы аннотируем конечную точку /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());
}
Вот эффект:
Как мы видим, текст, который мы добавили в @Operation
, находится на уровне операции API. Точно так же описание, добавленное к различным элементам @ApiResponse в аннотации контейнера
@ApiResponses
, также отображается здесь, добавляя смысл нашим ответам API.
Очевидно, мы не получаем никакой схемы для ответов 400 и 404 выше. Поскольку мы определили для них пустой @Content
, отображаются только их описания.
10. Поддержка Котлина
Поскольку Spring Boot 2.x имеет первоклассную поддержку Kotlin, SpringDoc поддерживает этот язык JVM из коробки для приложений Boot 2.x.
Чтобы увидеть это в действии, мы создадим простой Foo
API в Kotlin.
После первоначальной настройки мы добавим класс данных и контроллер. Мы добавим их в подпакет нашего загрузочного приложения, чтобы при запуске он выбирал наш 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
}
Теперь, когда мы нажмем URL-адрес документации нашего API, мы также увидим Foo
API:
Чтобы улучшить поддержку типов Kotlin, мы можем добавить эту зависимость:
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-kotlin</artifactId
<version>1.6.4</version>
</dependency>
После этого наша схема Foo будет выглядеть более информативно, как это было, когда мы добавили JSR-303 Bean Validation:
11. Заключение
В этой статье мы научились настраивать springdoc-openapi в наших проектах. Затем мы увидели, как интегрировать springdoc-openapi с пользовательским интерфейсом Swagger. Мы также видели, как это сделать с проектами Spring Webflux.
Затем мы использовали подключаемый модуль Springdoc-openapi Maven для создания определений OpenAPI для наших API и увидели, как предоставлять информацию о разбиении на страницы и сортировке из данных Spring. После этого мы рассмотрели, как springdoc-openapi автоматически генерирует документацию, используя аннотации проверки бина JSR 303 и аннотации @ResponseStatus в классе
@ControllerAdvice
.
Мы также узнали, как добавить описание к нашему API, используя несколько аннотаций, специфичных для OpenAPI. Наконец, мы взглянули на поддержку Kotlin в OpenAPI.
Springdoc-openapi создает документацию по API в соответствии со спецификацией OpenAPI 3. Кроме того, он также обрабатывает для нас конфигурацию пользовательского интерфейса Swagger, что делает создание документа API довольно простой задачей.
Как всегда, код доступен на GitHub .