Как определить закрытие браузера?

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

<meta http-equiv = "Refresh" content = "30; url=My_Servlet?User_Action=logout&User_Id=1111">

в теге, чтобы автоматически вывести его из системы.

Но я заметил, что многие пользователи остаются там навсегда, никогда не выходя из системы. Я выяснил, почему, закрывая свои браузеры, они никогда не выходили из системы вручную или автоматически, поэтому их идентификаторы пользователей никогда не будут удалены из действительного вектора идентификаторов пользователей.

Итак, мой вопрос: как мне обнаружить, что пользователи закрывают свои браузеры, чтобы мой сервлет мог удалить их идентификаторы из вектора?


Я вижу свет в конце туннеля, но проблема все еще есть, в моей программе примерно так:

Список активных пользователей:

User_1 : Machine_1 [ IP_1 address ]
User_2 : Machine_2 [ IP_2 address ]
User_3 : Machine_3 [ IP_3 address ]
...

Как мне узнать из слушателя сеанса, сеанс какого пользователя завершился и, следовательно, удалить его из моего списка?

Я надеялся, что когда сеанс завершится, будет вызван метод HttpServlet destroy(), и я могу удалить там идентификатор пользователя, но он никогда не вызывается, когда пользователь закрывает свой браузер, почему? И есть ли в HttpServlet какой-либо другой метод, который вызывается при закрытии сеанса?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
16
0
29 286
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

в JavaScript вы можете использовать событие onbeforeclose, чтобы передать обратный вызов серверу, когда пользователь закрывает браузер.

Обычно для этого я использую синхронный вызов Ajax.

Я предлагаю вам удалить идентификатор, когда механизм сервлета разрушает сеанс. Зарегистрируйте HttpSessionListener, который удаляет идентификатор пользователя при вызове sessionDestroyed().

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

Не существует надежного способа сделать то, что вы пытаетесь сделать, но у sblundy и Diodeus есть планы, которые охватывают большинство обстоятельств. Вы ничего не можете поделать с кем-то, кто отключил Javascript в своем браузере, или у него пропало интернет-соединение, или у него отключилось питание. Вам следует просто отбраковывать сеансы после определенного периода бездействия (что, я думаю, именно то, что предлагает sblundy прослушивать на предмет разрушения сеанса).

Ответ принят как подходящий

На стороне сервера нет способа узнать (если вы не используете какой-либо JavaScript для отправки сообщения на сервер), что браузер закрыт. Как могло быть? Подумайте, как работает HTTP - все запросы и ответы.

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

Количество активных сеансов будет отставать от фактического количества текущих пользователей, поскольку до истечения тайм-аута сеанса должен пройти некоторый период (настраиваемый); однако это должно быть несколько близко (вы можете уменьшить тайм-аут сеанса, чтобы повысить точность), и это намного чище и проще, чем 1) отслеживание сеансов самостоятельно или 2) отправка некоторого асинхронного JavaScript на сервер при закрытии браузера ( отправка которого не гарантируется).

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

matt b 18.11.2008 21:56

Эта ссылка stardeveloper.com/articles/… не работает. Обновите свой ответ.

OO7 02.12.2014 11:07

Мне пришлось сделать это недавно, и после некоторых поисков я нашел несколько решений в сети ... все они не работают повсеместно!

Для этой задачи используются события onbeforeclose и onclose. Но есть две ловушки: они срабатывают, когда пользователь перезагружает страницу или даже просто меняет текущую страницу. Существуют уловки, позволяющие узнать, действительно ли событие является закрытием окна / страницы / вкладки (если посмотреть на некоторые свойства Dom, которые выходят из строя при закрытии события), но:

  • Они зависят от браузера
  • Уловки недокументированы, поэтому хрупкие
  • И на самом деле они меняются в зависимости от версии / обновления браузера ...

И, что хуже всего, эти события теперь игнорируются большинством современных браузеров, потому что они использовались мошеннической рекламой, выскакивающей окна при закрытии браузера. Они не запускаются в Safari, Opera, IE7 и т. д.

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

Решение, которое я дал, заключалось в том, чтобы пинговать с запросом Ajax (отправка идентификатора пользователя) сервер через равные промежутки времени (скажем, 1 минуту). Если сервер не получает пинг, скажем, 3 минуты, он отключает пользователя.

Функционально это практически то же самое, что и использование HttpSessionListener, за исключением того, что вам пришлось самостоятельно кодировать Ajax и обработчик на стороне сервера, заново изобретая колесо.

matt b 19.11.2008 19:05

Вы шутите, да? HttpSessionListener - это интерфейс, он не предоставляет ни Ajax, ни волшебства.

PhiLho 20.11.2008 00:25

Вот грязный способ «обнаружить закрытие браузера» Я нашел это на форуме где-то на этом сайте, и когда найду его снова, я сделаю ссылку на него.

Добавьте дополнительные заголовки в ответ http. Когда поступают дополнительные запросы, они будут содержать эти дополнительные заголовки. Вы можете проверить эти заголовки, и если их нет, вы можете прервать сеанс, чтобы запустился новый. Хотя это не «уведомляет» вас, если браузер закрыт, он может сказать вам, закрыл ли кто-то свое окно и пытается вернуться, поскольку добавленные вами заголовки будут отсутствовать.

 wrapper.setHeader("Cache-Control", "no-cache, no-store, must-     revalidate");
 wrapper.setHeader("Pragma", "no-cache");
 wrapper.setDateHeader("Expires", 0);

 Where wrapper is a response wrapper.

 if (wrapper.getHeaderNames().size() < the number of headers you are expecting)
 request.getSession().invalidate();

 Not perfect but it might help someone.

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

rjdamore 13.04.2013 01:45

Другие вопросы по теме