Документация API: OpenAPI и Swagger UI
Фронтенд-разработчику или другой команде нужно знать, какие адреса есть у API, что они принимают и что возвращают. Такое описание принято делать в формате OpenAPI — это JSON-файл со списком маршрутов, параметров и моделей данных. По нему Swagger UI рисует страницу, где каждый запрос можно посмотреть и сразу выполнить. Для Javalin есть официальный плагин javalin-openapi: вы описываете обработчики аннотацией @OpenApi, а при компиляции обработчик аннотаций (annotation processor — программа, которая запускается вместе с компилятором) собирает из них спецификацию.
Зависимости
Номер версии плагина идёт вслед за Javalin: для Javalin 7.2.3 подходит плагин 7.2.3. В pom.xml добавьте свойство и две зависимости:
<!-- pom.xml -->
<properties>
<!-- ... -->
<javalin.openapi.version>7.2.3</javalin.openapi.version>
</properties>
<dependency>
<groupId>io.javalin.community.openapi</groupId>
<artifactId>javalin-openapi-plugin</artifactId>
<version>${javalin.openapi.version}</version>
</dependency>
<dependency>
<groupId>io.javalin.community.openapi</groupId>
<artifactId>javalin-swagger-plugin</artifactId>
<version>${javalin.openapi.version}</version>
</dependency>А в настройки maven-compiler-plugin — сам обработчик аннотаций:
<!-- pom.xml -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.14.1</version>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>io.javalin.community.openapi</groupId>
<artifactId>openapi-annotation-processor</artifactId>
<version>${javalin.openapi.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>Описание маршрутов
Аннотация ставится на метод контроллера. Все классы аннотаций лежат в пакете io.javalin.openapi:
// src/main/java/com/example/blog/PostController.java
@OpenApi(
path = "/posts/{id}",
methods = HttpMethod.GET,
summary = "Пост по номеру",
tags = "Посты",
pathParams = @OpenApiParam(name = "id", type = Long.class, required = true),
responses = {
@OpenApiResponse(status = "200", content = @OpenApiContent(from = Post.class)),
@OpenApiResponse(status = "404", description = "Пост не найден")
}
)
public void getOne(Context ctx) {
// код без изменений
}
@OpenApi(
path = "/posts",
methods = HttpMethod.POST,
summary = "Создать пост",
tags = "Посты",
security = @OpenApiSecurity(name = "BasicAuth"),
requestBody = @OpenApiRequestBody(content = @OpenApiContent(from = NewPost.class), required = true),
responses = {
@OpenApiResponse(status = "201", content = @OpenApiContent(from = Post.class)),
@OpenApiResponse(status = "400", description = "Ошибка проверки данных"),
@OpenApiResponse(status = "401", description = "Нужен вход")
}
)
public void create(Context ctx) {
// код без изменений
}path и methods должны совпадать с настоящим маршрутом: плагин не сверяет их с apiBuilder. from = Post.class превращает запись в схему JSON, для списка пишут from = Post[].class. Так же опишите getAll и delete.
Подключение плагинов
// src/main/java/com/example/blog/Main.java
config.registerPlugin(new OpenApiPlugin(openapi -> {
openapi.withDefinitionConfiguration((version, builder) -> {
builder.info(info -> info.title("API блога").version("1.0.0"));
builder.withBasicAuth("BasicAuth");
});
}));
config.registerPlugin(new SwaggerPlugin());OpenApiPlugin (пакет io.javalin.openapi.plugin) отдаёт спецификацию по адресу /openapi, SwaggerPlugin (io.javalin.openapi.plugin.swagger) — страницу /swagger. withBasicAuth("BasicAuth") объявляет схему входа, на которую ссылается @OpenApiSecurity. У адресов документации нет ролей, поэтому проверка Auth::check их пропускает.
Проверка
Выполните mvn compile exec:java и запросите спецификацию:
curl http://localhost:8080/openapi{
"openapi" : "3.1.0",
"info" : {
"title" : "API блога",
"version" : "1.0.0"
},
...
"/posts/{id}" : {
"get" : {
"tags" : [ "Посты" ],
"summary" : "Пост по номеру",
"parameters" : [ {
"name" : "id",
"in" : "path",
"required" : true,
"schema" : {
"type" : "integer",
"format" : "int64"
}
} ],
...
Откройте http://localhost:8080/swagger в браузере: в группе «Посты» видны четыре запроса, внизу — схемы NewPost и Post. Кнопка Authorize принимает логин и пароль, а Try it out отправляет настоящий запрос к серверу.
Частая ошибка
Без блока annotationProcessorPaths проект компилируется без ошибок, но спецификация пустая:
{
"info" : {
"title" : "API блога",
"version" : "1.0.0"
},
"components" : {
"securitySchemes" : { ... },
"schemas" : { }
},
"paths" : { }
}
В спецификации нет даже поля openapi с номером версии, и Swagger UI вместо списка запросов пишет Unable to render this definition: The provided definition does not specify a valid version field. Обработчик аннотаций кладёт файл target/classes/openapi-plugin/openapi-default.json — если его нет, проверьте настройки maven-compiler-plugin и пересоберите проект командой mvn clean compile.