ServletContext
Коли контейнер сервлетів (наприклад, Apache Tomcat ) запускається, він розгорнуть і завантажить усі свої веб-програми. Коли веб-додаток завантажується, контейнер сервлетів створює ServletContext
один раз і зберігає його в пам'яті сервера. Веб - додаток web.xml
і все включено web-fragment.xml
файли аналізуються, і кожне <servlet>
, <filter>
і <listener>
знайшов (або кожен клас з анотацією @WebServlet
, @WebFilter
і @WebListener
відповідно) конкретизується раз і зберігається в пам'яті сервера , а також. Для кожного створеного фільтра його init()
метод викликається новим FilterConfig
.
Якщо у Servlet
a <servlet><load-on-startup>
або @WebServlet(loadOnStartup)
значення більше ніж 0
, тоді його init()
метод також викликається під час запуску з новим ServletConfig
. Ці сервлети ініціалізуються в тому ж порядку, визначеному цим значенням ( 1
1-е, 2
2-е і т.д.). Якщо ж значення задано більше одного сервлету, то кожен з цих сервлет завантажуються в тому ж порядку , як вони з'являються в web.xml
, web-fragment.xml
або @WebServlet
завантаженні класів. У разі відсутності значення "завантаження при запуску" init()
метод буде викликатись, коли запит HTTP потрапляє в цей сервлет вперше.
Коли контейнер сервлета буде закінчений з усіма описаними вище етапами ініціалізації, тоді ServletContextListener#contextInitialized()
буде викликано заклик.
Коли сервлет контейнер закривається вниз, він вивантажує всі веб - додатки, викликає destroy()
метод всіх його ініціалізувати сервлетів і фільтрів, а також всі ServletContext
, Servlet
, Filter
і Listener
екземпляри громив. Нарешті ServletContextListener#contextDestroyed()
заповіт буде застосовано.
HttpServletRequest та HttpServletResponse
Контейнер сервлетів приєднаний до веб-сервера, який слухає HTTP-запити на певний номер порту (порт 8080 зазвичай використовується під час розробки, а порт 80 у виробництві). Коли клієнт (наприклад, користувач із веб-браузером або програмно використовуючимURLConnection
) надсилає HTTP-запит, контейнер сервлетів створює нові HttpServletRequest
та HttpServletResponse
об'єкти та передає їх через будь-який визначений Filter
ланцюг і, зрештою, Servlet
екземпляр.
Що стосується фільтрів , doFilter()
метод викликається. Коли код контейнера сервлетів дзвонить chain.doFilter(request, response)
, запит і відповідь продовжуються до наступного фільтра або натискають сервлет, якщо немає інших фільтрів.
У разі сервлетів використовується service()
метод. За замовчуванням цей метод визначає, який із doXxx()
методів викликати на основі request.getMethod()
. Якщо визначений метод відсутній у сервлета, то у відповіді повертається помилка HTTP 405.
Об'єкт запиту забезпечує доступ до всієї інформації про HTTP-запит, такі як його URL, заголовки, рядок запиту та тіло. Об'єкт відповіді надає можливість керувати та надсилати відповідь HTTP так, як вам потрібно, наприклад, дозволяє встановлювати заголовки та тіло (як правило, з генерованого вмісту HTML із файлу JSP). Коли відповідь HTTP введено та закінчено, об'єкти запиту та відповіді рециркулюються та стають доступними для повторного використання.
HttpSession
Коли клієнт відвідує веб-сервер вперше та / або HttpSession
отримує його вперше через request.getSession()
, контейнер сервлетів створює новий HttpSession
об'єкт, генерує довгий і унікальний ідентифікатор (який ви можете отримати session.getId()
) і зберігає його в сервері пам'ять. Контейнер сервлетів також встановлює Cookie
в Set-Cookie
заголовку відповіді HTTP з JSESSIONID
його іменем та унікальним ідентифікатором сеансу як своїм значенням.
Відповідно до специфікації файлів cookie HTTP (у договорі повинен дотримуватися будь-який пристойний веб-браузер та веб-сервер), клієнт (веб-браузер) зобов'язаний відправити це cookie назад у наступних запитах у Cookie
заголовку, доки файл cookie дійсний ( тобто унікальний ідентифікатор повинен посилатися на сеанс, який не закінчився, і домен і шлях є правильними). Використовуючи вбудований монітор HTTP-трафіку вашого браузера, ви можете переконатися, що файл cookie є дійсним (натисніть F12 в Chrome / Firefox 23+ / IE9 + і перевірте вкладку Net / Network ). Контейнер сервлетів перевіряє Cookie
заголовок кожного вхідного запиту HTTP на наявність файлу cookie з ім'ям JSESSIONID
та використовує його значення (ідентифікатор сесії) для отримання асоційованого HttpSession
з пам'яті сервера.
В HttpSession
залишається живий , поки він знаходиться в режимі очікування (тобто не використовується в запиті) більше , ніж значення тайм - ауту , зазначених в <session-timeout>
, настройки в web.xml
. Значення затримки за замовчуванням становить 30 хвилин. Отже, коли клієнт не відвідує веб-доданок довше зазначеного часу, контейнер сервлетів переносить сеанс. Кожен наступний запит, навіть із вказаним файлом cookie, більше не матиме доступу до тієї ж сесії; контейнер сервлетів створить новий сеанс.
На стороні клієнта файли cookie сеансу залишаються живими, поки працює екземпляр браузера. Отже, якщо клієнт закриває екземпляр браузера (усі вкладки / вікна), сеанс переноситься на сторону клієнта. У новому екземплярі веб-переглядача файл cookie, пов’язаний із сеансом, не існував, тому він більше не надсилався. Це спричиняє створення абсолютно нового HttpSession
файлу cookie сеансу.
Коротко
- У
ServletContext
житті так довго , як веб - додаток життя. Він ділиться між усіма запитами на всіх сесіях.
- У
HttpSession
житті до тих пір , поки клієнт взаємодіє з веб - додаток з тим же примірником браузера, і сеанс не минуло на стороні сервера. Він поділяється між усіма запитами в одному сеансі.
HttpServletRequest
І HttpServletResponse
жити з моменту сервлет отримує запит HTTP від клієнта, поки повну відповідь (веб - сторінки) не надходило. Він не поділений ніде.
- Все
Servlet
, Filter
і Listener
екземпляри живуть до тих пір , як веб - додаток живе. Вони поділяються між усіма запитами на всіх сесіях.
- Будь-яке,
attribute
що визначене в ServletContext
, HttpServletRequest
і HttpSession
буде жити до тих пір, поки живе даний предмет. Сам об'єкт являє собою «сферу» в рамках управління бобом , такі як JSF, CDI, Spring і т.д. Ці структури зберігати свої Scoped бобів в якості attribute
його найближчого відповідності обсягу.
Безпека нитки
Однак, ваша головна проблема - це, можливо, безпека ниток . Тепер ви повинні знати, що сервлети та фільтри поділяються між усіма запитами. Це приємна річ у Java, її багатопотоковість і різні потоки (читайте: HTTP-запити) можуть використовувати один і той же екземпляр. Інакше відтворити їх було б занадто дорого, init()
і destroy()
їх для кожного запиту.
Ви також повинні усвідомити, що ніколи не слід призначати будь-які запити чи дані, що охоплюють сеанс, як змінну екземпляра сервлета чи фільтра. Їм буде надано доступ до всіх інших запитів на інших сесіях. Це не безпечно для ниток! Наведений нижче приклад ілюструє це:
public class ExampleServlet extends HttpServlet {
private Object thisIsNOTThreadSafe;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Object thisIsThreadSafe;
thisIsNOTThreadSafe = request.getParameter("foo"); // BAD!! Shared among all requests!
thisIsThreadSafe = request.getParameter("foo"); // OK, this is thread safe.
}
}
Дивись також: