ServletContext
Когда контейнер сервлета (например, Apache Tomcat ) запускается, он развертывает и загружает все свои веб-приложения. Когда веб-приложение загружено, контейнер сервлета создает ServletContext
один раз и сохраняет его в памяти сервера. web.xml
веб-приложения и все включенные файлы web-fragment.xml
анализируются, и каждый <servlet>
, <filter>
и <listener>
найден (или каждый класс помечен @WebServlet
, @WebFilter
и @WebListener
соответственно) создается один раз и сохраняется в памяти сервера. Для каждого экземпляра фильтра его метод init()
вызывается с новым FilterConfig
.
Если Servlet
имеет значение <servlet><load-on-startup>
или @WebServlet(loadOnStartup)
больше 0
, то его метод init()
также вызывается во время запуска с новым ServletConfig
. Эти сервлеты инициализируются в том же порядке, который указан в этом значении (1
- 1-й, 2
- 2-й и т. Д.). Если одно и то же значение указано для нескольких сервлетов, каждый из этих сервлетов загружается в том же порядке, в котором они отображаются в классовой загрузке 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-ответа с JSESSIONID
в качестве имени и уникальным идентификатором сеанса в качестве значения.
Согласно спецификации HTTP cookie (контракт, которого должен придерживаться любой приличный веб-браузер и веб-сервер), клиент (веб-браузер) обязан отправлять этот куки-файл обратно в последующих запросах в 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
своей ближайшей соответствующей области.
Thread Safety
Тем не менее, ваша главная проблема, возможно, безопасность потоков .Теперь вы должны знать, что сервлеты и фильтры являются общими для всех запросов.Это хорошая вещь в 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.
}
}
См. Также: