Проверка данных
Сейчас API примет статью с пустым заголовком или вовсе без текста. Валидация — проверка входных данных до того, как они попадут в логику приложения. Правила записывают аннотациями стандарта Jakarta Validation прямо на полях записи, а Micronaut проверяет их и при нарушении отвечает 400 с понятным списком ошибок.
Подключение
Если вы не выбрали возможность validation в генераторе, добавьте её вручную. Что именно добавить, покажет команда mn feature-diff --features=validation в папке проекта. В pom.xml нужны две зависимости:
<!-- pom.xml, внутри <dependencies> -->
<dependency>
<groupId>io.micronaut.validation</groupId>
<artifactId>micronaut-validation</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
<scope>compile</scope>
</dependency>И обработчик аннотаций — в настройки maven-compiler-plugin, рядом с уже имеющимися <path>:
<!-- pom.xml, внутри <annotationProcessorPaths> -->
<path>
<groupId>io.micronaut.validation</groupId>
<artifactId>micronaut-validation-processor</artifactId>
<version>${micronaut.validation.version}</version>
<exclusions>
<exclusion>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-inject</artifactId>
</exclusion>
</exclusions>
</path>После изменения обработчиков пересоберите проект целиком: ./mvnw clean compile.
Правила на записи
// src/main/java/com/example/ArticleForm.java
package com.example;
import io.micronaut.serde.annotation.Serdeable;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
@Serdeable
public record ArticleForm(
@NotBlank @Size(max = 100) String title,
@NotBlank String body) {
}| Аннотация | Что проверяет |
|---|---|
@NotNull | Значение не null |
@NotBlank | Строка не пустая и не из одних пробелов |
@Size(min, max) | Длина строки или размер списка |
@Min, @Max | Границы числа |
@Email | Похоже на адрес почты |
Включение в контроллере
Поставьте @Valid перед параметром метода в ArticleController:
// src/main/java/com/example/ArticleController.java
@Post
public HttpResponse<Article> create(@Body @Valid ArticleForm form) {
Article article = articleService.create(form);
return HttpResponse.created(article, URI.create("/articles/" + article.id()));
}@Valid импортируется из jakarta.validation. Обработчик аннотаций видит его и ещё при компиляции оборачивает метод проверкой — во время работы рефлексия не нужна.
Проверка
curl -i -X POST http://localhost:8080/articles \
-H "Content-Type: application/json" \
-d '{"body":""}'HTTP/1.1 400 Bad Request
Content-Type: application/json
{"_links":{"self":[{"href":"/articles","templated":false}]},"_embedded":{"errors":[{"message":"form.body: must not be blank"},{"message":"form.title: must not be blank"}]},"message":"Bad Request"}Каждое нарушение — отдельный элемент errors с именем параметра и поля. Корректный запрос по-прежнему создаёт статью с ответом 201. Аннотации работают и в сервисах: @Valid или @NotBlank на параметре метода любого бина тоже включает проверку.
Частая ошибка
Самая коварная ошибка — правила есть, но не срабатывают: статья с пустым заголовком сохраняется с ответом 201. Причин две. Либо не подключён micronaut-validation-processor, либо проект не пересобран после его добавления — старые классы скомпилированы без проверки. Убедитесь, что обработчик есть в <annotationProcessorPaths>, и выполните ./mvnw clean compile. Признак, что всё в порядке: в target/classes/com/example/ появился класс $ArticleController$Definition$Intercepted.class.