junior
Как контейнер сервлетов управляет жизненным циклом сервлета
Контейнер управляет четырьмя фазами жизненного цикла сервлета: загрузка класса, инициализация, обработка запросов и уничтожение. Сервлет создаётся при первом обращении (или при старте приложения, если задан load-on-startup) и живёт до остановки приложения.
Фазы жизненного цикла
Пример
Загрузка класса → init() → service() (многократно) → destroy()
| Фаза | Что происходит | Сколько раз |
|---|---|---|
| Загрузка | Контейнер загружает класс в память и вызывает конструктор без параметров | 1 раз |
Инициализация (init()) |
Контейнер создаёт ServletConfig и передаёт его через init(). Сервлет получает доступ к параметрам конфигурации |
1 раз |
Обработка запросов (service()) |
Для каждого запроса контейнер создаёт новый поток и вызывает service(), передавая объекты запроса и ответа |
Многократно |
Уничтожение (destroy()) |
Контейнер вызывает destroy() при остановке приложения. Сервлет освобождает ресурсы |
1 раз |
Важно: один экземпляр сервлета обрабатывает все запросы в разных потоках. Поэтому в полях сервлета нельзя хранить данные, специфичные для конкретного запроса — это приведёт к состоянию гонки (race condition).
На собеседовании: ключевой момент — сервлет является синглтоном в рамках контейнера. Метод
service()вызывается в разных потоках одновременно, поэтому сервлет должен быть потокобезопасным. Частая ошибка — забыть упомянуть многопоточность.