Документация API: OpenAPI и Swagger UI
Тот, кто пишет фронтенд или мобильное приложение, должен знать адреса API, параметры и поля JSON. Описывать их вручную долго, а описание быстро устаревает. OpenAPI — стандартный формат описания REST API в JSON или YAML. Библиотека springdoc-openapi читает ваши контроллеры и записи и строит такое описание сама, а Swagger UI превращает его в страницу, где каждый адрес можно вызвать кнопкой.
Подключение
springdoc — не часть Spring Boot, поэтому версию указывают явно. Для Spring Boot 4 нужна ветка 3.x (ветка 2.x — для Spring Boot 3):
<!-- pom.xml -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>3.1.1</version>
</dependency>Больше ничего не нужно: после перезапуска появляются два адреса.
| Адрес | Что там |
|---|---|
http://localhost:8080/swagger-ui.html | Страница Swagger UI (переадресует на /swagger-ui/index.html) |
http://localhost:8080/v3/api-docs | Описание API в формате OpenAPI (JSON) |
Что получилось
Откройте http://localhost:8080/swagger-ui.html. На странице сгруппированы адреса: GET /api/posts, POST /api/posts, POST /api/images и другие. Раскройте любой, нажмите Try it out, затем Execute — запрос уйдёт в приложение, а ниже появятся ответ и готовая команда curl.
Описание в JSON начинается так (сокращено):
{"openapi":"3.1.0","info":{"title":"OpenAPI definition","version":"v0"},"paths":{"/api/posts/{id}":{"get":{"tags":["post-controller"],"operationId":"show", ...springdoc сам узнал адреса, параметры пути и строки запроса, тела запросов и коды вроде 201 и 204 из @ResponseStatus.
Название и описание API
// src/main/java/com/example/blog/OpenApiConfig.java
package com.example.blog;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class OpenApiConfig {
@Bean
public OpenAPI blogOpenApi() {
return new OpenAPI().info(new Info()
.title("API блога")
.description("Статьи, комментарии и пользователи")
.version("1.0"));
}
}Вместо OpenAPI definition в шапке страницы появится «API блога» с описанием.
Аннотации на контроллере
// src/main/java/com/example/blog/PostController.java
@RestController
@RequestMapping("/api/posts")
@Tag(name = "Статьи", description = "Чтение и изменение статей блога")
public class PostController {
@Operation(summary = "Одна статья по номеру")
@ApiResponse(responseCode = "200", description = "Статья найдена")
@ApiResponse(responseCode = "404", description = "Статьи с таким номером нет")
@GetMapping("/{id}")
public Post show(@PathVariable Long id) {
return postService.findById(id);
}
}| Аннотация | Что делает |
|---|---|
@Tag | Название группы адресов вместо post-controller |
@Operation(summary) | Короткая подпись к адресу |
@ApiResponse | Возможный код ответа и его смысл |
@Schema | Описание и пример для поля записи |
Все они из пакета io.swagger.v3.oas.annotations. Поля DTO описывают так:
// src/main/java/com/example/blog/NewPostRequest.java
public record NewPostRequest(
@Schema(description = "Заголовок", example = "Привет, Spring")
@NotBlank @Size(max = 120) String title,
@Schema(description = "Текст статьи", example = "Первая статья")
@NotBlank String body,
@Schema(description = "Имя автора", example = "anna")
@NotBlank String author) {
}Правила проверки springdoc тоже учитывает: в описании title появятся "maxLength":120, а все три поля попадут в список required. Кнопка Try it out подставит примеры из example.
Выключение на сервере
В рабочей версии документацию часто прячут:
# src/main/resources/application-prod.yaml
springdoc:
api-docs:
enabled: false
swagger-ui:
enabled: falseОб этом же напоминает предупреждение при запуске: SpringDoc /swagger-ui.html endpoint is enabled by default.
Частая ошибка
После подключения Spring Security (шестая глава) страница документации перестанет открываться: curl -i http://localhost:8080/swagger-ui.html ответит 302 и отправит на форму входа /login. Адреса springdoc не начинаются с /api, поэтому их обрабатывает цепочка сайта, где всё закрыто. Откройте их явно:
// src/main/java/com/example/blog/SecurityConfig.java
.requestMatchers("/swagger-ui.html", "/swagger-ui/**", "/v3/api-docs/**").permitAll()Строку ставят в цепочку сайта перед anyRequest().