Spring MVC @Sessionattributes问题在多个浏览器选项卡中

时间:2014-11-05 12:23:14

标签: java spring-mvc session-management

我们正在使用最新版本的春天。

我们正在使用spring mvc的@Sessionattributes来存储会话范围内的数据。

问题是当我们使用浏览器的多个选项卡时,它无法正常工作。

我们有一个搜索页面,允许用户使用多个字段搜索数据库。我们使用@Sessionattributes将结果存储在会话中。

问题: 例如,用户提供一些输入和搜索,结果存储在名为“searchresults”的会话中。

如果用户打开新标签页并再次使用不同的标准进行搜索,则搜索结果将存储在名为“searchresults”的会话中。

因此,如果用户重新加载第一个标签...他将在第二个标签中搜索结果...

所以...:会话中的“searchresults”会有来自第二个标签的结果......所以即使用户刷新第一个标签,他也会看到他使用第二个标签获得的结果..

这个春天有没有解决方案......

2 个答案:

答案 0 :(得分:2)

是的,lewthor表示多个标签共享一个会话。

处理这种情况的一种方法是使用一个特定于标签的网址组件,该组件将包含在会话密钥中。如果您在产品列表页面上,并且每个产品都打开一个新标签页,那么如果您确保标签打开时的网址不同,例如通过在网址/product/{product.id}中使用产品ID,您需要做的就是将ID添加到会话密钥searchresults{product.id}

还有一个以@SessionAttribute为中心的解决方案,一个仅用于此目的的自定义,在此处blog中描述,并基于描述的here旧博客。该解决方案实现了一个CustomSessionAttributeStore,并维护了一个Map of Maps,其中内部Map是deafult SessionAttributes,由会话ID标识(在您的情况下是标签ID)

public class ConversationalSessionAttributeStore implements SessionAttributeStore, InitializingBean {

  @Inject
  private RequestMappingHandlerAdapter requestMappingHandlerAdapter;
  private Logger logger = Logger.getLogger(ConversationalSessionAttributeStore.class.getName());

  private int keepAliveConversations = 10;

  public final static String CID_FIELD = "_cid";
  public final static String SESSION_MAP = "sessionConversationMap";

  @Override
  public void storeAttribute(WebRequest request, String attributeName, Object attributeValue) {
    Assert.notNull(request, "WebRequest must not be null");
    Assert.notNull(attributeName, "Attribute name must not be null");
    Assert.notNull(attributeValue, "Attribute value must not be null");

    String cId = getConversationId(request);
    if (cId == null || cId.trim().length() == 0) {
      cId = UUID.randomUUID().toString();
      request.setAttribute(CID_FIELD, cId, WebRequest.SCOPE_REQUEST);
    }

    logger.debug("storeAttribute - storing bean reference for (" + attributeName + ").");
    store(request, attributeName, attributeValue, cId);
  }

  private String getConversationId(WebRequest request) {
    return request.getParameter(CID_FIELD);
  }
}

整个项目发布在GitHub

答案 1 :(得分:1)

这是因为浏览器将单独的选项卡视为同一会话。您可以使用浏览器的开发工具来检查从两个不同选项卡发送的会话cookie,以确认这一点 - 它们将是相同的。

因此,Spring正确地将来自不同选项卡的所有请求视为同一会话。如果您希望用户能够在不同的标签页中进行单独的搜索,则必须以会话属性以外的其他方式管理搜索结果。