在Google App Engine下,您要存储在HttpSession
中的任何对象都必须实现Serializable
,并且其所有字段都必须是可序列化的,因为在GAE中运行的实例可能会从一个JVM到另一个。这意味着,如果我想将FooBar
个实例存储到HttpSession
中,我就不能在其中指向一个字段,指向HttpSession
。
但是,我可以存储getId()
返回的ID。根据{{3}},出于安全原因,已从其ID获取会话的能力已被折旧,但GAE实施方式不同。根据{{3}},您可以使用ID来获取表示HttpSession
的DataStore实体,但我想要引用Java对象,而不是用于在JVM之间迁移它的基础数据。
那么,有什么办法可以做我想要的吗?
答案 0 :(得分:3)
Relevant paragraph from your link:
为每个新创建类型为“_ah_SESSION”的数据存储区实体 HttpSession中。实体键是“_ahs”+ session.getId()。每 _ah_SESSION实体有两个属性“_values”和“_expires”。
“_values”属性只是序列化的byte []表示 包含会话数据的HashMap。
所以你可以做的如下:
// When putting FooBar to session
FooBar fooBar;
HttpSession session;
session.setAttribute("fooBar", fooBar);
而另一方面:
// When getting session from datastore
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
Key sessionKey = KeyFactory.createKey("_ah_SESSION", sessionId);
Entity sessionEntity = datastore.get(sessionKey);
byte[] sessionBytes = sessionEntity.getProperty("_values");
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(sessionBytes);
ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
Map<?, ?> sessionMap = (Map) objectInputStream.readObject();
FooBar restoredFooBar = (FooBar) sessionMap.get("fooBar");
我是从内存中编写代码的,所以请先在生产中测试一下,然后添加标准内容,比如强化检查,但总体思路是一样的。