我正在开发一个 GAE/J 应用程序,使用 JDO 来管理数据存储区。它提供了许多端点来与数据交互等。我还在为这些端点开发一个 Javascript 客户端。
情况:
首先,我有一个端点方法Token getSessionToken(User usr)
,它生成一个 session token ,将其分配给用户并将用户和 session token 存储在数据存储区中。
然后我有另一个端点方法 Info getInfo(Token token)
,它接收 session token ,检查该 session token 是否对应于用户,如果是,则返回一些信息。
问题
从我的 Javascript 客户端,我调用第一个方法,一切都很好。然后,我使用之前检索的 session token 调用第二个方法,并且收到一条错误,指出该 session token 不对应于任何用户...
我已经检查过,我意识到发生此错误只是因为新的 session token 尚未持久化!
问题
我目前的解决方案是让Javascript客户端调用第二个方法一次,如果收到错误,等待一段时间再调用...有更好的解决方案吗?
<小时/>编辑:
这是第一个方法调用中涉及的代码,以了解为什么需要这么长时间......
端点:
@ApiMethod(
name = "getSessionToken",
path = "get_session_token",
httpMethod = HttpMethod.GET
)
public SessionToken getSessionToken (@Named("email") String email, @Named("password") String password)
throws InternalServerErrorException {
SessionToken sessionToken = new UsersController().getSessionToken(email, password);
return sessionToken;
}
控制:
public SessionToken getSessionToken(String email, String password) throws InternalServerErrorException {
SessionToken sessionToken = null;
PersistenceManager pm = PMF.get().getPersistenceManager();
Transaction txn = DatastoreServiceFactory.getDatastoreService().beginTransaction();
try {
DAO dao = new DAO(pm);
User user = dao.getUserByLogin(email, password);
dao.deleteSessionToken(user.getSessionToken());
sessionToken = SessionTokenManager.generateToken(user.getEmail(), user.getPassword());
user.setSessionToken(sessionToken);
user = dao.insertUser(user);
txn.commit();
} catch (Exception e) {
throw new InternalServerErrorException();
} finally {
if (txn.isActive()) {
txn.rollback();
}
pm.close();
}
return sessionToken;
}
DAO:
public User getUserByLogin(String email, String password) throws InternalServerErrorException {
User user = null;
Query query = null;
try {
query = this.pm.newQuery(User.class);
query.setFilter("email == emailParam && password == passwordParam");
query.declareParameters("String emailParam, String passwordParam");
List<User> results = (List<User>) query.execute(email, password);
user = results.get(0);
} catch (Exception e) {
e.printStackTrace();
throw new InternalServerErrorException("Error in DAO.getUserByLogin()");
} finally {
query.closeAll();
}
return user;
}
/////
public void deleteSessionToken(SessionToken sessionToken) throws InternalServerErrorException {
try {
this.pm.deletePersistent(sessionToken);
} catch (Exception e) {
e.printStackTrace();
throw new InternalServerErrorException("Error in DAO.deleteSessionToken()");
}
}
/////
public User insertUser(User user) throws InternalServerErrorException {
try {
this.pm.makePersistent(user);
} catch (Exception e) {
e.printStackTrace();
throw new InternalServerErrorException("Error in DAO.insertUser()", e);
}
return user;
}
型号:
@PersistenceCapable
public class User {
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;
@Persistent
private String name;
@Persistent
private String email;
@Persistent
private String password;
@Persistent
private Folder rootFolder;
@Persistent
private SessionToken sessionToken;
@Persistent(defaultFetchGroup = "true")
private AccountContainer accountContainer;
//getters & setters
}
/////
@PersistenceCapable
public class SessionToken {
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;
@Persistent
private String token;
@Persistent
private Long created;
@Persistent
private String sha1;
//getters & setters
}
最佳答案
也许以下其中一种是可能的并且适合您的需求
您能否将这两个调用合并为“getSessionTokenAndInfo”调用?您将 token 和信息一起返回的地方。根据您的代码的工作方式, token 和用户对象可能已经可用并且不需要加载?
使用某种形式的缓存,以便第一个端点在 memcache 中留下一些内容,这样就不需要在第二次调用中尝试从数据存储中检索它(至少在大多数情况下,memcache 应该是可靠的)对于这种情况来说足够了)。
关于java - Google App Engine 数据存储持久性太慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16441387/