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.
}
}
Смотрите также:
PHPSESSID
cookie, ASP.NET сASP.NET_SessionID
cookie и так далее. Вот почему переопределение URL с помощью;jsessionid=xxx
некоторых сред JSP / Servlet MVC автоматически не одобряется. Просто убедитесь, что идентификатор сеанса никогда не отображается в URL-адресе или другими способами на веб-страницах, чтобы не подвергнуться нападению неосведомленный конечный пользователь.сессии
Вкратце: веб-сервер выдает уникальный идентификатор каждому посетителю при его первом посещении. Посетитель должен принести этот идентификатор, чтобы его можно было узнать в следующий раз. Этот идентификатор также позволяет серверу правильно отделять объекты, принадлежащие одному сеансу, от сеанса другого.
Сервлет Инстанция
Если загрузка при запуске имеет значение false :
Если загрузка при запуске - это правда :
Как только он перейдет в сервисный режим и в паз, тот же сервлет будет работать с запросами всех других клиентов.
Почему не стоит иметь один экземпляр на клиента? Подумайте об этом: вы будете нанимать по одному парню пиццы на каждый заказ? Сделайте это, и вы будете вне бизнеса в кратчайшие сроки.
Это идет с небольшим риском, хотя. Помните: этот парень хранит всю информацию о заказе в своем кармане: поэтому, если вы не будете осторожны с безопасностью потоков в сервлетах , он может в итоге отдать неправильный заказ определенному клиенту.
источник
to many requests at this moment. try again later
Сеанс в Java-сервлетах аналогичен сеансу в других языках, таких как PHP. Это уникально для пользователя. Сервер может отслеживать это различными способами, такими как файлы cookie, перезапись URL-адреса и т. Д. В этой статье, посвященной Java, объясняется это в контексте сервлетов Java и указывается, что именно то, как поддерживается сеанс, является подробностью реализации, оставленной разработчикам сервера. Спецификация только предусматривает, что она должна поддерживаться как уникальная для пользователя при нескольких подключениях к серверу. Проверьте эту статью от Oracle для получения дополнительной информации по обоим вашим вопросам.
Edit Существует отличный учебник здесь о том , как работать с сеансом внутри сервлет. И вот глава от Sun о Java-сервлетах, что они из себя представляют и как их использовать. Между этими двумя статьями вы должны быть в состоянии ответить на все ваши вопросы.
источник
ServletContext
объект. Этот объект имеет ноль, один или несколько объектов сеанса - набор объектов сеанса. Каждый сеанс идентифицируется некоторой строкой идентификатора, как показано в мультфильмах на другом ответе. Этот идентификатор отслеживается на клиенте с помощью cookie или перезаписи URL. У каждого объекта сеанса есть свои переменные.Когда сервлет-контейнер (например, Apache Tomcat) запускается, он будет читать из файла web.xml (только один на приложение), если что-то пойдет не так или обнаружит ошибку на консоли на стороне контейнера, в противном случае он развернет и загрузит весь веб-интерфейс. приложения с помощью web.xml (так называемый дескриптор развертывания).
На этапе создания экземпляра сервлета экземпляр сервлета готов, но не может обслуживать клиентский запрос, поскольку отсутствует с двумя частями информации:
1: контекстная информация
2: исходная информация о конфигурации
Механизм сервлета создает интерфейсный объект servletConfig, инкапсулируя в него недостающую информацию, описанную выше. Механизм сервлета вызывает init () сервлета, предоставляя ссылки на объект servletConfig в качестве аргумента. Как только init () полностью выполнен, сервлет готов обслуживать запрос клиента.
Q) Сколько раз в жизни сервлета происходит инициализация и инициализация ??
A) только один раз (для каждого клиентского запроса создается новый поток) только один экземпляр сервлета обслуживает любое количество клиентских запросов, т. Е. После обслуживания один клиентский сервер запросов не умирает. Он ожидает других клиентских запросов, т. Е. Какой CGI (для каждого клиентского запроса создается новый процесс) ограничение преодолевается с помощью сервлета (внутренний механизм сервлета создает поток).
Q) Как работает концепция сессии?
А) всякий раз, когда getSession () вызывается для объекта HttpServletRequest
Шаг 1 : объект запроса оценивается для входящего идентификатора сеанса.
Шаг 2 : если идентификатор недоступен, создается новый объект HttpSession и генерируется соответствующий ему идентификатор сеанса (т. Е. HashTable). Идентификатор сеанса сохраняется в объекте ответа httpservlet, а ссылка на объект HttpSession возвращается сервлету (doGet / doPost). ,
Шаг 3 : если идентификатор доступен, новый объект сеанса не создан. Идентификатор сеанса выбирается из запроса. Поиск объекта производится в коллекции сеансов с использованием идентификатора сеанса в качестве ключа.
После успешного поиска идентификатор сеанса сохраняется в HttpServletResponse, а ссылки на существующие объекты сеанса возвращаются в doGet () или doPost () UserDefineservlet.
Замечания:
1) когда управление уходит от кода сервлета к клиенту, не забывайте, что объект сеанса удерживается контейнером сервлета, т. Е. Механизмом сервлета
2) многопоточность оставлена разработчикам сервлетов для реализации, т. Е. Обрабатывать множественные запросы клиента, не беспокоясь о многопоточном коде
Краткая форма:
Сервлет создается при запуске приложения (оно развертывается в контейнере сервлета) или при первом обращении к нему (в зависимости от настройки загрузки при запуске), когда создается сервлет, вызывается метод init () сервлета затем сервлет (его единственный экземпляр) обрабатывает все запросы (его метод service () вызывается несколькими потоками). Вот почему не рекомендуется иметь какую-либо синхронизацию, и вам следует избегать переменных экземпляра сервлета, когда приложение не развернуто (контейнер сервлета останавливается), вызывается метод destroy ().
источник
Сессии - что сказал Крис Томпсон.
Instantiation - сервлет создается, когда контейнер получает первый запрос, сопоставленный с сервлетом (если сервлет не настроен для загрузки при запуске с
<load-on-startup>
элементом inweb.xml
). Этот же экземпляр используется для обслуживания последующих запросов.источник
Спецификация сервлета JSR-315 четко определяет поведение веб-контейнера в методах службы (и doGet, doPost, doPut и т. Д.) (2.3.3.1 Проблемы многопоточности, Страница 9):
источник
Как ясно из приведенных выше объяснений, с помощью реализации SingleThreadModel сервлет может гарантировать безопасность потока с помощью контейнера сервлета. Реализация контейнера может сделать это двумя способами:
1) Сериализация запросов (постановка в очередь) для одного экземпляра - это похоже на сервлет, НЕ реализующий SingleThreadModel, НО синхронизирующий методы service / doXXX; ИЛИ
2) Создание пула экземпляров - что является лучшим вариантом и компромисс между загрузкой / инициализацией / временем сервлета по сравнению с ограничительными параметрами (память / время ЦП) среды, в которой размещен сервлет.
источник
Нет. Сервлеты не безопасны
Это позволяет получить доступ к более чем одному потоку одновременно
если вы хотите сделать его Servlet как потокобезопасным., вы можете пойти на
Implement SingleThreadInterface(i)
пустой интерфейс нетметоды
или мы можем пойти на методы синхронизации
мы можем сделать весь метод обслуживания как синхронизированный, используя синхронизированный
Ключевое слово перед методом
Пример::
или мы можем положить блок кода в синхронизированный блок
Пример::
Я чувствую, что синхронизированный блок лучше, чем весь метод
синхронизированный
источник