Управление данными сеанса Webapp/потоком контроллера для нескольких вкладок

У меня есть веб-приложение Java, которое хранит некоторые данные в сеансе. Данные в сеансе изменяются, когда пользователь взаимодействует с приложением (например, поток управляется контроллером, каждый контроллер имеет несколько страниц формы, на каждой странице формы некоторые данные обновляются в сеансе, а поток переходит к следующей странице формы).

Проблема заключается в том, что некоторые пользователи открывают более одной вкладке для приложения, причем каждая вкладка имеет другой шаг в потоке. На этом этапе данные в сеансе перепутаны, так как вкладки используют один и тот же сеанс (приложение использует сеансы, управляемые cookie).

Говорить пользователям о том, чтобы использовать разные браузеры, чтобы не использовать один и тот же идентификатор сеанса (например, одно окно Firefox и одно окно IE), не является вариантом, так как в какой-то момент кто-то забудет это сделать и вместо этого использует вкладки, их данные.

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

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

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

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

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

Вы столкнулись с такой ситуацией? Как вы справились с этим?

Ответ 1

Обычно это делается путем назначения windowId для каждой вкладки/окна и передачи его по каждому запросу. Jsf поддерживает это через orchestra. Spring mvc будет поддерживать его в следующей версии.

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

  • передайте windowId с каждым запросом и верните его для следующего запроса. Первый раз - сгенерируйте его.
  • для любого атрибута, который вы хотите сохранить в сеансе, введите Map<String, Object>, где ключ находится в windowId

Ответ 2

Это именно то, что Seam было создано для обработки. В Seam существует концепция, называемая Conversation, которая в основном делает именно то, что вы объясняете. Разговоры в основном - это способ разделить сессию на многие части, срок действия которых истекает через некоторое время. Вы можете посмотреть исходный код для класса org.jboss.seam.core.Manager, чтобы увидеть, как он реализован и вдохновлен;)

Ответ 3

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

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

Ответ 4

Вы также можете попробовать обернуть свое приложение внутри Adobe Air

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