GAE: Way to get reference to an HttpSession from i

2019-07-11 07:37发布

Under Google App Engine any object that you want to store in a HttpSession has to implement Serializable, and all of its fields have to be serializable, because an instance running in GAE might be migrated from one JVM to another. This means that if I want to store a FooBar instance into an HttpSession I can't have a field in it pointing back to the HttpSession.

However, I can store the ID returned by getId(). According to this question the ability to get a session from its ID has been depreciated for security reasons, but the GAE implementation is different. According to this blog post you can use the ID to get the DataStore entity representing the HttpSession, but I want a reference to the Java object, not the underlying data being used to migrate it between JVMs.

So, is there any way to do what I want?

1条回答
聊天终结者
2楼-- · 2019-07-11 08:23

Relevant paragraph from your link:

A Datastore entity of kind "_ah_SESSION" is created for each new HttpSession. The entity key is "_ahs" + session.getId(). Each _ah_SESSION entity has two properties "_values" and "_expires".

The "_values" property is simply the serialized byte[] representation of a HashMap that includes the the session data.

So what you can do is as follows:

// When putting FooBar to session
FooBar fooBar;
HttpSession session;
session.setAttribute("fooBar", fooBar);

And, on the other side:

// 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");

I wrote the code from memory, so please test it in production first and add standard things like cast check, but the general idea is the same.

查看更多
登录 后发表回答