Play! 框架可扩展性的一些疑问

最近在研究如何将Membase NoSQL应用到Play! 框架中,需求主要是为了将一些用户状态,比如登录状态、页面操作状态等缓存起来。

众所周知,Play!是一个无状态的框架,意思就是Play!没有Session!但是使用过Play!的朋友一定知道Play!的Control里面是有一个session的,别急,这个session实际上并不是我们真正意义上的浏览器session,而是cookie哦!要理解这点,需要我们打开Play!的源码:

/**
* Session scope
*/
public static class Session {
......
static Session restore() {
try {
Session session = new Session();
Http.Cookie cookie = Http.Request.current().cookies.get(COOKIE_PREFIX + "_SESSION");
if (cookie != null && Play.started && cookie.value != null && !cookie.value.trim().equals("")) {
String value = cookie.value;
String sign = value.substring(0, value.indexOf("-"));
String data = value.substring(value.indexOf("-") + 1);
if (sign.equals(Crypto.sign(data, Play.secretKey.getBytes()))) {
String sessionData = URLDecoder.decode(data, "utf-8");
Matcher matcher = sessionParser.matcher(sessionData);
while (matcher.find()) {
session.put(matcher.group(1), matcher.group(2));
}
}
if (COOKIE_EXPIRE != null) {
// Verify that the session contains a timestamp, and that it's not expired
if (!session.contains(TS_KEY)) {
session = new Session();
} else {
if (Long.parseLong(session.get(TS_KEY)) < System.currentTimeMillis()) {
// Session expired
session = new Session();
}
}
session.put(TS_KEY, System.currentTimeMillis() + (Time.parseDuration(COOKIE_EXPIRE) * 1000));
} else {
// Just restored. Nothing changed. No cookie-expire.
session.changed = false;
}
} else {
// no previous cookie to restore; but we may have to set the timestamp in the new cookie
if (COOKIE_EXPIRE != null) {
session.put(TS_KEY, System.currentTimeMillis() + (Time.parseDuration(COOKIE_EXPIRE) * 1000));
}
}

return session;
} catch (Exception e) {
throw new UnexpectedException("Corrupted HTTP session from " + Http.Request.current().remoteAddress, e);
}
}

Map<String, String> data = new HashMap<String, String>(); // ThreadLocal access
boolean changed = false;
public static ThreadLocal<Session> current = new ThreadLocal<Session>();

public static Session current() {
return current.get();
}
......
void save() {
if (Http.Response.current() == null) {
// Some request like WebSocket don't have any response
return;
}
if(!changed && SESSION_SEND_ONLY_IF_CHANGED && COOKIE_EXPIRE == null) {
// Nothing changed and no cookie-expire, consequently send nothing back.
return;
}
if (isEmpty()) {
// The session is empty: delete the cookie
if(Http.Request.current().cookies.containsKey(COOKIE_PREFIX + "_SESSION") || !SESSION_SEND_ONLY_IF_CHANGED) {
Http.Response.current().setCookie(COOKIE_PREFIX + "_SESSION", "", null, "/", 0, COOKIE_SECURE, SESSION_HTTPONLY);
}
return;
}
try {
StringBuilder session = new StringBuilder();
for (String key : data.keySet()) {
session.append("\u0000");
session.append(key);
session.append(":");
session.append(data.get(key));
session.append("\u0000");
}
String sessionData = URLEncoder.encode(session.toString(), "utf-8");
String sign = Crypto.sign(sessionData, Play.secretKey.getBytes());
if (COOKIE_EXPIRE == null) {
Http.Response.current().setCookie(COOKIE_PREFIX + "_SESSION", sign + "-" + sessionData, null, "/", null, COOKIE_SECURE, SESSION_HTTPONLY);
} else {
Http.Response.current().setCookie(COOKIE_PREFIX + "_SESSION", sign + "-" + sessionData, null, "/", Time.parseDuration(COOKIE_EXPIRE), COOKIE_SECURE, SESSION_HTTPONLY);
}
} catch (Exception e) {
throw new UnexpectedException("Session serializationProblem", e);
}
}
......
}


上面的代码很明显的看出,Play!的session操作实际上就是对cookie的操作。

但是对于我来说很不幸的事情并不是这点,而是play!的session是一个静态类!并且还是Scope里面的一个子类,这意味着我无法很轻易的替换它,除非修改这个类的源码。

这样我非常还念基于接口的编程,如果session是一个接口,而不是一个静态类,那么我就可以实现一个基于session接口的实现类,用于替换这个session类,这样的话,我就能将对membase的操作封装在session中,可以做到很灵活的扩展。

也许从中我们可以看出,play!在强调敏捷性的同时,失去了一定的灵活性,又或者,我对play!的了解还不够深入吧。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值