Управление данными сеанса webapp / потоком контроллера для нескольких вкладок
У меня есть веб-приложение Java, которое хранит некоторые данные в сеансе. Данные в сеансе изменяются, когда пользователь взаимодействует с приложением (например, поток управляется контроллером, каждый контроллер имеет несколько страниц формы, на каждой странице формы некоторые данные обновляются в сеансе, и поток переходит на следующую страницу формы).
Проблема состоит в том, что некоторые пользователи открывают более одной вкладки для приложения, каждая вкладка с отдельным шагом в потоке. На этом этапе данные в сеансе перепутаны, так как вкладки используют один и тот же сеанс (приложение использует сеансы, управляемые cookie).
Указывать пользователям использовать разные браузеры, чтобы они не разделяли один и тот же идентификатор сеанса (например, одно окно Firefox и одно окно IE), - не вариант, так как наверняка в какой-то момент кто-то забудет это сделать и вместо этого использовать вкладки, что приведет к путанице в их данных.
Добавление некоторых проверок, которые обнаруживают, что другой поток запрашивается из другой вкладки, и отображает сообщение для пользователя, говорящее, что это не разрешено, также не вариант, так как это раздражает пользователей, и мы не хотим, чтобы мы это делали?:D
Дело в том, что использование другой вкладки полезно для пользователей, потому что они более эффективны в том, для чего они используют приложение, поэтому я сохраняю эту опцию. Но теперь возникает вопрос: как лучше управлять данными одного сеанса для большего количества вкладок?
Я подумал о том, чтобы контроллер генерировал токен при запуске потока и передавал этот токен каждой странице формы, которая, в свою очередь, отправляла его обратно для идентификации себя. Если другая вкладка запрашивает то же действие контроллера при наличии текущего потока, сгенерируйте другой токен и передайте его.
По сути, я хочу, чтобы у каждого потока был токен, и внутри сеанса я не буду просто хранить один набор данных, но буду иметь набор данных для каждого токена, а затем сопоставлять запросы на основе токена.
Теперь проблема в том, что для этого подхода потребуется много переписать приложение, и мне было интересно, есть ли лучшая практика для управления такой ситуацией или кто-то может предложить другие подходы. Я открыт для идей.
Сталкивались ли вы с такой ситуацией? Как вы справиться с этим?
4 ответа
Обычно это делается путем назначения windowId для каждой вкладки / окна и передачи его при каждом запросе. JSF поддерживает это через оркестр. Spring mvc поддержит его в следующей версии.
Недавно я нуждался в этом для простого случая, поэтому я реализовал это сам. Прошло полчаса. Тем не менее, мой кругозор был очень ограничен:
- передать
windowId
с каждым запросом и возвращайте его обратно для следующего запроса. Первый раз - сгенерируйте его. - для любого атрибута, который вы хотите сохранить в сеансе, установите
Map<String, Object>
где ключ являетсяwindowId
Вы также можете попробовать обернуть ваше приложение в Adobe Air
А затем ограничьте доступ к вашему веб-приложению только с этого эфира. При этом вам не нужно учитывать фрагментацию веб-браузера и их уникальное поведение.
Это именно то, что Шов был создан для обработки. В Seam есть концепция, называемая Conversation, которая в основном делает именно то, что вы объясняете. Беседы - это, в основном, способ разделить сессию на множество частей, срок действия которых может истечь через некоторое время. Вы можете посмотреть исходный код класса org.jboss.seam.core.Manager, чтобы увидеть, как он на самом деле реализован и вдохновлен;)
В зависимости от сложности вашего приложения вы можете исследовать вкладки реализации в вашем приложении. Это дает вам полный контроль над потоком, в то же время предоставляя пользователям функциональность, которую они хотят. Я бы сказал, что это ошибочное решение, наиболее надежное, поскольку у вас не будет зависимости от того, как браузер обрабатывает сеансы, сводя к минимуму количество "известных неизвестных".
Конечно, это потенциально может быть связано с большими начальными затратами, в зависимости от структуры вашего приложения. Без дополнительной информации о вашем приложении вы будете лучшим выбором.