Проверка данных
Клиенту нельзя доверять: он может прислать пустой заголовок, слишком короткий текст или сломанный JSON. Валидация — проверка входных данных до того, как они попадут в хранилище. В Javalin для этого есть валидаторы: методы bodyValidator, queryParamAsClass, pathParamAsClass и headerAsClass возвращают объект Validator, к которому добавляются правила.
Как работает валидатор
- Метод вида
...AsClassилиbodyValidatorсоздаёт валидатор и пробует превратить строку или JSON в нужный тип. - Методы
check(условие, "сообщение")добавляют правила. - Метод
get()возвращает значение или бросаетValidationException, если хоть одно правило нарушено.
ValidationException Javalin сам превращает в ответ 400 со списком ошибок в JSON.
Проверка тела запроса
Замените bodyAsClass в маршруте создания поста на bodyValidator:
// src/main/java/com/example/blog/Main.java
config.routes.post("/posts", ctx -> {
NewPost data = ctx.bodyValidator(NewPost.class)
.check(p -> p.title() != null && !p.title().isBlank(), "Нужен заголовок")
.check(p -> p.body() != null && p.body().length() >= 5, "Текст слишком короткий")
.get();
ctx.status(HttpStatus.CREATED).json(store.create(data));
});Каждое правило получает готовый объект NewPost и возвращает true, если всё в порядке. Отправим неверный пост:
curl -i -X POST http://localhost:8080/posts \
-d '{"title":"","body":"abc","author":"Олег"}'HTTP/1.1 400 Bad Request
Content-Type: application/json
{"REQUEST_BODY":[{"message":"Нужен заголовок","args":{},"value":{"title":"","body":"abc","author":"Олег"}},{"message":"Текст слишком короткий","args":{},"value":{"title":"","body":"abc","author":"Олег"}}]}
Javalin проверил все правила и вернул обе ошибки сразу. Ключ REQUEST_BODY означает, что ошибка в теле запроса.
Проверка параметров
Те же правила работают с параметрами. Ограничим размер страницы в поиске:
// src/main/java/com/example/blog/Main.java
int limit = ctx.queryParamAsClass("limit", Integer.class)
.check(n -> n >= 1 && n <= 50, "Лимит должен быть от 1 до 50")
.getOrDefault(10);На ?limit=100 сервер ответит 400 и {"limit":[{"message":"Лимит должен быть от 1 до 50","args":{},"value":100}]}, а без параметра подставит 10.
Методы получения значения
| Метод | Если значения нет | Если правило нарушено |
|---|---|---|
get() | 400, ошибка NULLCHECK_FAILED | 400 |
getOrDefault(10) | Значение по умолчанию | 400 |
getOrNull() | null | 400 |
Частая ошибка
ctx.bodyAsClass не проверяет данные: на сломанный JSON, например {"title":"x" без закрывающей скобки, клиент получает 500 Server Error, а в логе — JsonEOFException: Unexpected end-of-input. Так выглядит ошибка сервера, хотя ошибся клиент. С bodyValidator тот же запрос получает правильный ответ:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{"REQUEST_BODY":[{"message":"DESERIALIZATION_FAILED","args":{},"value":"{\"title\":\"x\""}]}
Для данных от клиента используйте bodyValidator.