ServletContext
Когда контейнер сервлета (например, Apache Tomcat ) запускается, он развертывает и загружает все свои веб-приложения. Когда веб-приложение загружается, контейнер сервлета создает его ServletContextодин раз и сохраняет в памяти сервера. Веб - приложение web.xmlи все включены web-fragment.xmlфайлы анализируются, и каждое <servlet>, <filter>и <listener>нашел (или каждый класс с аннотацией @WebServlet, @WebFilterи @WebListenerсоответственно) конкретизируется раз и хранится в памяти сервера , а также. Для каждого экземпляра фильтра его init()метод вызывается с новым FilterConfig.
Когда a Servletимеет значение <servlet><load-on-startup>или @WebServlet(loadOnStartup)больше чем 0, тогда его init()метод также вызывается во время запуска с новым ServletConfig. Эти сервлеты инициализируются в том же порядке, который указан в этом значении ( 11-й, 22-й и т. Д.). Если же значение задано более одного сервлета, то каждый из этих сервлет загружаются в том же порядке , как они появляются в web.xml, web-fragment.xmlили @WebServletзагрузке классов. Если значение «load-on-startup» отсутствует, 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 a в JSESSIONIDкачестве имени и уникальный идентификатор сеанса в качестве значения.
В соответствии со спецификацией файлов cookie HTTP (контракт, которого должен придерживаться любой приличный веб-браузер и веб-сервер), клиент (веб-браузер) обязан отправлять этот куки-файл обратно в последующих запросах в Cookieзаголовке до тех пор, пока cookie-файл действителен ( т. е. уникальный идентификатор должен относиться к не истекшему сеансу, а домен и путь являются правильными). Используя встроенный в ваш браузер монитор HTTP-трафика, вы можете убедиться, что файл cookie действителен (нажмите F12 в Chrome / Firefox 23+ / IE9 + и откройте вкладку Сеть / Сеть ). Контейнер сервлета будет проверять 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будет жить до тех пор, пока живет рассматриваемый объект. Сам объект представляет «область видимости» в инфраструктурах управления bean-компонентами, таких как JSF, CDI, Spring и т. Д. Эти структуры хранят свои bean-объекты области видимости как 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.
}
}
Смотрите также: