Паттерн "Цепочка обязанностей" в Java — фильтры и обработчики
Модель и масштаб — Основы БД, опорные темы, проектирование БД, пакетная работа. Карта — о разделе.
Краткий обзор — в поведенческих паттернах. Здесь — практика на Java — как собрать цепочку обработчиков, где паттерн уже встроен в платформу (Filter, FilterChain) и когда цепочка оправдана в прикладном коде.
Play ITЗагрузка интерактивного демо…
Задача паттерна
Chain of Responsibility (цепочка обязанностей) — поведенческий паттерн GoF. Запрос передаётся по цепочке обработчиков. Каждый звено решает — выполнить свою часть работы и передать запрос дальше, обработать запрос полностью и остановить цепочку, или отклонить запрос (ошибка, отказ).
Простая аналогия — эскалация тикета в поддержке: L1 → L2 → L3. Уровень либо закрывает инцидент, либо передаёт выше.
Типичный сценарий в вебе — последовательная проверка HTTP-запроса: аутентификация → авторизация → rate limit → бизнес-логика. Каждый шаг — отдельный обработчик; порядок можно менять без правок соседних классов.
Play ITЗагрузка интерактивного демо…
Каркас на Java
Общий контракт — абстрактный обработчик со ссылкой на следующее звено и методом setNext для сборки цепочки в fluent-стиле.
Код ITЗагрузка примера кода…
Конкретные обработчики вызывают super.handle(request) после успешной проверки, чтобы запрос дошёл до конца цепочки.
Код ITЗагрузка примера кода…
Сборка и запуск:
RequestHandler chain = new AuthenticationHandler();
chain.setNext(new RateLimitHandler())
.setNext(new BusinessLogicHandler());
chain.handle(request);
Для учебного примера достаточно простого DTO:
public final class HttpRequest {
private final String ip;
private final String token;
public HttpRequest(String ip, String token) {
this.ip = ip;
this.token = token;
}
public String getIp() { return ip; }
public String getToken() { return token; }
}
Где паттерн уже есть в Java-экосистеме
Servlet API — javax.servlet.Filter
Классический пример из экосистемы Java EE и Jakarta EE: каждый Filter — звено цепочки. Контейнер вызывает FilterChain.doFilter(), и фильтры по очереди решают, пропустить запрос дальше или оборвать обработку.
Тот же приём в Spring MVC/Spring Boot: фильтры регистрируются в контейнере или через FilterRegistrationBean.
Spring Security — SecurityFilterChain
В Spring Security десятки внутренних фильтров выстроены в упорядоченную цепочку (SecurityFilterChain). Конфигурация в Security Basic и обзоре Spring — это промышленная версия Chain of Responsibility — аутентификация, CSRF, авторизация по URL и т.д.
Другие примеры
| Место | Роль цепочки |
|---|---|
Jakarta EE / Servlet FilterChain | HTTP-запрос до сервлета |
| Spring Security | Безопасность до DispatcherServlet |
| Логгеры (уровни DEBUG → INFO → WARN) | Сообщение доходит до подходящего аппендера |
| Согласование (approval) | Заявка по сумме — менеджер → директор → CFO |
Когда применять
| Ситуация | Почему подходит цепочка |
|---|---|
| Набор и порядок обработчиков меняются в рантайме или по профилю | Звенья подключаются без правки клиентского кода |
| Неизвестно заранее, кто обработает запрос | Отправитель знает только вход в цепочку |
| Несколько независимых политик над одним запросом | Каждая политика — отдельный класс (SRP) |
| Middleware-пайплайн | Один контракт handle, единый порядок |
Риски и ограничения
Запрос может пройти всю цепочку и остаться без обработки, если финальное звено только "пропускает" дальше, а обработчика с бизнес-логикой нет. Длинную цепочку сложнее отлаживать: нужны логи с именем класса-обработчика и порядком вызова.
Добавляйте терминальное звено, которое либо выполняет работу, либо явно бросает исключение / пишет в лог "запрос не обработан".
Иначе ошибки теряются молча.
Сравнение с соседними паттернами
| Паттерн | Отличие |
|---|---|
| Наблюдатель | Одно событие рассылается всем подписчикам параллельно |
| Цепочка обязанностей | Запрос идёт последовательно, пока звено не обработает или не передаст дальше |
| Команда | Действие инкапсулируется в объект; цепочка — про маршрутизацию запроса |
| Стратегия | Выбирается один алгоритм; в цепочке может сработать несколько проверок подряд |
Чек-лист
| Вопрос | Выбор |
|---|---|
| Нужен фиксированный пайплайн проверок над запросом | Цепочка обработчиков или Servlet/Spring filters |
| Нужно уведомить много подписчиков об одном событии | Observer / domain events |
| Нужно упаковать одно действие с undo/очередью | Command |
| Один из нескольких алгоритмов на выбор | Strategy |
В новом Spring Boot REST-сервисе часто достаточно встроенных фильтров и HandlerInterceptor, без собственной иерархии RequestHandler.
Порядок этапов (фильтры → DispatcherServlet → preHandle → контроллер → afterCompletion) — в жизненном цикле запроса Spring Boot. Собственная цепочка оправдана, когда правила домена не укладываются в Security и нужен явный, тестируемый порядок шагов.
Итог
Chain of Responsibility в Java — это и учебная схема "абстрактный обработчик + next", и основа Filter/FilterChain в веб-стеке. Паттерн уменьшает связность между отправителем запроса и конкретными проверками, ценой явного контроля порядка звеньев и терминального обработчика.