Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Обработчики before и after

Иногда один и тот же код нужен для многих маршрутов: записать запрос в лог, добавить заголовок, проверить вход. Копировать его в каждый обработчик неудобно. Для этого в Javalin есть обработчики before и after: первые выполняются до основного обработчика, вторые — после. В других фреймворках такое называют фильтрами или middleware.

Порядок выполнения

Каждый запрос проходит одну и ту же цепочку:

  1. Все подходящие обработчики before в порядке объявления.
  2. Один основной обработчик маршрута (endpoint).
  3. Обработчики исключений и ошибок, если что-то пошло не так.
  4. Все подходящие обработчики after — они выполняются даже после ошибки.

Лог каждого запроса

Добавьте в блок настроек два обработчика. before запоминает время начала в атрибуте запроса, after печатает метод, путь, код и длительность:

// src/main/java/com/example/blog/Main.java
config.routes.before(ctx -> ctx.attribute("start", System.nanoTime()));
 
config.routes.after(ctx -> {
    long start = ctx.attribute("start");
    long ms = (System.nanoTime() - start) / 1_000_000;
    System.out.println(ctx.method() + " " + ctx.path() + " -> " + ctx.statusCode() + " (" + ms + " мс)");
});

Атрибут — значение, которое живёт только во время одного запроса: ctx.attribute("имя", значение) сохраняет его, ctx.attribute("имя") читает. Вызовите несколько адресов и посмотрите в консоль сервера:

GET /posts -> 200 (5 мс)
GET /posts/99 -> 404 (2 мс)
POST /posts -> 201 (45 мс)
DELETE /posts/3 -> 204 (0 мс)

Первый запрос к JSON всегда медленнее: Jackson при первом вызове готовит свои внутренние структуры.

Обработчики для части адресов

Первым аргументом можно передать путь. Звёздочка * означает «что угодно дальше»:

// src/main/java/com/example/blog/Main.java
config.routes.before("/posts/*", ctx -> System.out.println("Запрос к посту: " + ctx.path()));
config.routes.after(ctx -> ctx.header("X-Blog", "Javalin"));

Первый обработчик сработает для /posts/1 и /posts/new, второй добавит заголовок X-Blog: Javalin ко всем ответам, включая ответы 404.

before и beforeMatched

Обработчик before выполняется для любого запроса, даже если маршрута нет и ответ будет 404. Если код нужен только для существующих маршрутов, используйте beforeMatched и afterMatched. В главе 4 на beforeMatched мы построим проверку прав.

МетодКогда выполняется
before, afterДля всех запросов
beforeMatched, afterMatchedТолько если нашёлся маршрут или статический файл

Частая ошибка

Путь /posts в before совпадает только с адресом /posts, а не со всем, что начинается на него:

// src/main/java/com/example/blog/Main.java
config.routes.before("/posts", ctx -> System.out.println("before /posts: " + ctx.path()));

Запрос /posts печатает строку, а запрос /posts/1 — нет. Чтобы охватить вложенные адреса, добавьте второй обработчик с путём /posts/*.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.