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
. Эти сервлеты инициализируются в том же порядке, который указан в этом значении ( 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 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.
}
}
Смотрите также: