Как работают сервлеты? Создание экземпляров, сеансы, общие переменные и многопоточность

Предположим, у меня есть веб-сервер, который содержит множество сервлетов. Для передачи информации между этими сервлетами я устанавливаю переменные сеанса и экземпляра.

теперь, если 2 или более пользователей отправляют запрос на этот сервер, что происходит с переменными сеанса? Будут ли они общими для всех пользователей или они будут разными для каждого пользователя. Если они разные, то как сервер мог различать разных пользователей?

еще один подобный вопрос, если есть n пользователи получают доступ к определенному сервлету, затем этот сервлет получает экземпляр только при первом доступе к нему первого пользователя или он создается для всех пользователей отдельно? Другими словами, что происходит с переменными экземпляра?

7 ответов


ServletContext

когда контейнер сервлета (как Apache Tomcat) запускается, он будет развертывать и загружать все свои веб-приложения. При загрузке веб-приложения контейнер сервлета создает ServletContext раз и сохраняет его в памяти сервера. Веб-приложение web.xml файл анализируется, и каждый <servlet>, <filter> и <listener> найдено (или каждый класс с аннотацией @WebServlet, @WebFilter и @WebListener соответственно) создается один раз и также хранится в памяти сервера. Для каждого экземпляра фильтра, его init() метод вызывается с новой FilterConfig.

когда контейнер сервлета выключается, он выгружает все веб-приложения, вызывает destroy() метод всех его инициализации сервлетов и фильтров, и все ServletContext, Servlet, Filter и Listener экземпляры будут разрушены.

когда Servlet есть <servlet><load-on-startup> или @WebServlet(loadOnStartup) значение больше 0, его init() метод также вызывается во время запуска с новым ServletConfig. Эти сервлеты инициализируются в том же порядке, указанном этим значением (1 -> 1-й, 2 - > 2-й и т. д.). Если одно и то же значение задано для нескольких сервлетов, то каждый из этих сервлетов загружается в том порядке, в котором они отображаются в web.xml или @WebServlet классов. В случае, если значение" load-on-startup " отсутствует, значение init() метод будет вызываться всякий раз, когда HTTP-запрос попадает в этот сервлет в первый раз.

HttpServletRequest и HttpServletResponse

контейнер сервлета присоединен к веб-серверу, который прослушивает HTTP-запросы на определенный номер порта (порт 8080 обычно используется во время разработки и порт 80 в производстве). Когда клиент (пользователь с веб-браузером) отправляет HTTP-запрос, контейнер сервлета создает new HttpServletRequest и HttpServletResponse объекты и передает их через какой-либо определенной


сеансы

enter image description hereenter image description here

короче говоря: веб-сервер выдает уникальный идентификатор каждый посетитель на первый визит. Посетитель должен вернуть это удостоверение, чтобы его узнали в следующий раз. Этот идентификатор также позволяет серверу правильно отделять объекты, принадлежащие одному сеансу, от объектов, принадлежащих другому.

Экземпляр Сервлета

Если нагрузка-на-автозагрузки is false:

enter image description hereenter image description here

Если нагрузка-на-автозагрузки is правда:

enter image description hereenter image description here

Как только он находится в режиме обслуживания и на канавке,то же самое servlet будет работать на запросах от всех других клиентов.

enter image description here

почему не рекомендуется иметь один экземпляр для каждого клиента? Подумайте об этом: вы наймете одного парня пиццы для каждого заказа, который пришел? Сделай это, и ты в два счета вылетишь из бизнеса.

Он поставляется с небольшим риском, хотя. Помните: этот единственный парень держит всю информацию о заказе в кармане: так что, если вы не осторожны безопасность резьбы на сервлетах, он может в конечном итоге дать неправильный заказ определенного клиента.


сеанс в Java сервлетах такой же, как и сеанс на других языках, таких как PHP. Он уникален для пользователя. Сервер может отслеживать его различными способами, такими как куки, переписывание url и т. д. Это Java doc статья объясняет это в контексте сервлетов Java и указывает, что именно то, как поддерживается сеанс, является детализацией реализации, оставленной дизайнерам сервера. Спецификация только предусматривает, что она должна поддерживаться как уникальная для пользователя несколько подключений к серверу. Проверьте эта статья от Oracle для получения дополнительной информации об обоих из ваших вопросов.

редактировать есть отличный учебник здесь о том, как работать с сессией внутри сервлетов. И здесь это глава из Sun о Java-Сервлетах, что они такое и как их использовать. Между этими двумя статьями, вы должны быть в состоянии ответить на все ваши вопросы.


когда servletcontainer (например, Apache Tomcat) запускается, он будет читать из интернета.xml-файл (только один для каждого приложения), если что-то пойдет не так или появится ошибка на боковой консоли контейнера, в противном случае он будет развертывать и загружать все веб-приложения с помощью web.xml (так называемый дескриптор развертывания).

на этапе создания экземпляра сервлета servletInstance готов, но не может обслуживать запрос клиента, потому что он отсутствует с двумя частями информации:
1:контекст информация
2: начальная информация о конфигурации

Servlet engine создает объект интерфейса servletConfig, инкапсулирующий в него вышеуказанную недостающую информацию servlet engine вызывает init () сервлета путем suplying ссылки на объект servletConfig в качестве аргумента. После того, как init () полностью выполнен, сервлет готов к серверу клиентского запроса.

в) время жизни сервлета, сколько раз инстанцирования и initaialization происходит ??

A) только один раз (для каждого запроса клиента создается новый поток) только один экземпляр сервлета обслуживает любое количество клиентских запросов, т. е. после обслуживания одного клиентского запроса сервер не умирает. Он ожидает других запросов клиента т. е. то, что CGI (для каждого запроса клиента создается новый процесс) ограничение преодолевается сервлетом (внутренне servlet engine создает поток).

Q) Как работает концепция сеанса?

A) всякий раз, когда getSession () вызывается на объекте HttpServletRequest

Шаг 1:объект запроса evalauated для входящего идентификатора сессии.

Шаг 2: если ID недоступен, создается новый объект HttpSession и генерируется соответствующий идентификатор сеанса (т. е. Hashtable), идентификатор сеанса сохраняется в объекте ответа httpservlet, а ссылка на объект HttpSession возвращается в сервлет (doGet/doPost).

Шаг 3: если id доступный новый объект сеанса не создан идентификатор сеанса выбирается из запроса поиск объекта производится в коллекции сеансов с помощью идентификатора сеанса в качестве ключа.

после успешного поиска идентификатор сеанса сохраняется в HttpServletResponse, а ссылки на существующие объекты сеанса возвращаются в doGet() или doPost () UserDefineservlet.

Примечание:

1) когда управление выходит из кода сервлета клиенту, не забывайте, что объект сеанса удерживается servletcontainer ie, servletengine

2) многопоточность оставлена сервлету devlopers people для реализации ie., обрабатывать несколько запросов клиента ничего не беспокоиться о многопоточном коде

Inshort форма:

сервлет создается при запуске приложения (он развертывается в контейнере сервлета) или при первом обращении к нему (в зависимости от параметра загрузки при запуске) при создании экземпляра сервлета вызывается метод init () сервлета затем сервлет (его один и только экземпляр) обрабатывает все запросы (его метод service () вызывается несколькими потоками). Вот почему не рекомендуется иметь в нем синхронизацию, и вы должны избегать переменных экземпляра сервлета когда приложение не развернуто (контейнер сервлета останавливается), вызывается метод destroy ().


сеансы - что сказал Крис Томпсон.

экземпляров - экземпляр сервлета создается, когда контейнер получает первый запрос, сопоставленный сервлету (если сервлет не настроен для загрузки при запуске с <load-on-startup> элемент web.xml). Этот же экземпляр используется для обслуживания последующих запросов.


Спецификация Servlet JSR-315 четко определяет поведение веб-контейнера в службе (и doGet, doPost, doPut и т. д.) методы (2.3.3.1 вопросы многопоточности, стр. 9):

контейнер сервлета может отправлять параллельные запросы через службу метод сервлета. Для обработки запросов разработчик сервлета необходимо предусмотреть адекватные условия для одновременной обработки с несколькими потоки в методе службы.

хотя это не рекомендуется, альтернативой для разработчика является реализуйте интерфейс SingleThreadModel, для которого требуется контейнер чтобы гарантировать, что существует только один поток запроса за раз в метод службы. Контейнер сервлета может удовлетворять этому требованию посредством сериализация запросов на сервлете или поддержание пула сервлетов экземпляры. Если сервлет является частью веб-приложения, которое было помеченный как распространяемый, контейнер может содержать пул из сервлета экземпляры в каждой JVM, по которой распространяется приложение.

для сервлетов, не реализующих интерфейс SingleThreadModel, если метод обслуживания (или методы, такие как doGet или doPost, которые являются отправляется в метод service абстрактного класса HttpServlet) определено с помощью ключевого слова synchronized, контейнера сервлета нельзя использовать подход пула экземпляров, но необходимо сериализовать запросы через него. Настоятельно рекомендуется Разработчики не синхронизируют метод службы (или методы, отправленные ему) в этих обстоятельства из-за пагубного влияния на производительность


нет. сервлеты являются не потокобезопасными

is позволяет получить доступ к более чем одному потоку за раз

если вы хотите сделать сервлет потокобезопасным . Вы можете пойти на

Implement SingleThreadInterface(i) который является пустым интерфейсом, нет

методы

или мы можем пойти для синхронизации методов

мы можем сделать весь метод обслуживания как синхронизированный путем использование синхронизированного

keword перед методом

пример:

public Synchronized class service(ServletRequest request,ServletResponse response)throws ServletException,IOException

или мы можем поместить блок кода в синхронизированный блок

пример:

Synchronized(Object)

{

----Instructions-----

}

Я чувствую, что синхронизированный блок лучше, чем сделать весь метод

синхронизироваться