Получить доступ

Сервлеты, фильтры и встроенный контейнер

Сервлет и встроенный Tomcat, модель thread-per-request, потокобезопасность контроллеров, Filter против Interceptor и forward/redirect.

Сервлет и встроенный контейнер

Сервлет-контейнер управляет жизненным циклом сервлета: init() при загрузке, service() (→ doGet/doPost) на каждый запрос, destroy() при выгрузке. В Spring MVC единственный центральный сервлет — DispatcherServlet, через него проходят все запросы.

Ключевой сдвиг Spring Boot: контейнер встроен (по умолчанию Tomcat; альтернативы — Jetty, Undertow). Приложение собирается в самодостаточный исполняемый jar со встроенным сервером, а не разворачивается WAR-файлом на внешний сервер приложений — это упрощает деплой и контейнеризацию.

Модель thread-per-request

Контейнер держит пул рабочих потоков (у Tomcat по умолчанию ~200). Каждый входящий запрос берёт один поток из пула и держит его всё время обработки, включая блокирующие ожидания (БД, внешние вызовы).

Отсюда потолок: при блокирующем IO число одновременных запросов ограничено размером пула — потоки простаивают в ожидании. Это и есть мотивация WebFlux (неблокирующая модель) и виртуальных потоков (дешёвые потоки), которым посвящены отдельные уроки.

Потокобезопасность контроллеров

Один экземпляр сервлета (и singleton-контроллера Spring) обслуживает множество запросов параллельно разными потоками. Поэтому состояние конкретного запроса НЕЛЬЗЯ хранить в полях контроллера/сервлета — это гонка данных.

Правило: в полях держат только потокобезопасные зависимости (другие бины), а данные запроса живут в параметрах метода, локальных переменных или request-scope бинах. Мутабельное поле-«состояние» в singleton-контроллере — классический баг.

Filter против Interceptor

Servlet Filter работает на уровне контейнера ДО DispatcherServlet и оборачивает всю обработку: CORS, security, сжатие, логирование, correlation id. Фильтры образуют цепочку (FilterChain), а порядок задают через @Order или FilterRegistrationBean.

HandlerInterceptor работает ВНУТРИ MVC, вокруг выбранного обработчика: preHandle/postHandle/afterCompletion, с доступом к тому, какой handler выбран. Выбор: нужна низкоуровневая обработка любого запроса и доступ к сырым servlet API — Filter; нужна логика, привязанная к MVC-обработчику — Interceptor.

forward и redirect

forward — серверная передача обработки другому ресурсу в рамках ТОГО ЖЕ запроса: новый запрос браузера не делается, URL не меняется. redirect — ответ 3xx, после которого клиент делает НОВЫЙ запрос на другой URL (URL в адресной строке меняется).

Отсюда паттерн PRG (Post/Redirect/Get): после успешного POST отвечают редиректом на GET-страницу, чтобы перезагрузка (F5) не повторяла отправку формы/платежа.

Как отвечать на собеседовании

Объясните встроенный контейнер (jar вместо WAR) и модель thread-per-request (поток из пула на запрос, блокировка на IO → мотивация WebFlux/виртуальных потоков). Подчеркните потокобезопасность singleton-контроллеров (нет состояния запроса в полях). Различите Filter (до DispatcherServlet, контейнерный, цепочка) и Interceptor (внутри MVC, вокруг handler), и forward vs redirect с паттерном PRG.

Вопросы по теме

Читайте также

Закрытая бета

Знать тему — половина дела

На живом собеседовании sotto слышит вопрос интервьюера и показывает короткий ответ и план. Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем