Play的特殊之处
当你需要跨多个HTTP请求来共享数据时,你可以将它们保存在Session或者Flash域中。Session中的数据在user Session整个周期有效,而Flash域中的数据仅仅保存至下一个request请求。
很重要的一个概念,是Session和Flash的数据并不由服务器保存,而是在各个HTTP请求中被添加到cookie里。这意味着数据量不能太大(小于4Kb)而且仅仅只能保存String格式的数据。默认的cookie名称是 PLAY_SESSION。当然你可以在 application.conf 中修改 play.http.session.cookieName来改变默认值。
如果cookie名称被改变了,先前的cookie可以通过上一章提到过的方法来删除。
当然,cookie的值由一个secret签名来保证不被客户端修改(否则cookie将会失效)。
Play Session并不是用来当做缓存的。如果你需要将某些数据缓存到关联的Session中,你可以使用Play内置的缓存机制,并在用户Session中保存关联用户缓存的唯一ID。
Session设置
请移步Configuring Session Cookies查看application.conf中session cookie的更多设置。
Session超时/失效
默认的,Session没有超时时间。它将在用户关闭浏览器时失效。如果你需要一个可编程的超时时间,可以通过在 application.conf 设置 play.http.session.maxAge 来限定,此配置会将 play.http.session.jwt.expiresAfter 设置为同样的值。maxAge 将从浏览器移除cookie,同时JWT的 exp 将在cookie中被设置,并在超时后将其失效。移步这里查看更多信息。
在Session中保存数据
Session仅仅是一个Cookie而已,因此它也是一个HTTP Header。你可以像操作其他Header一样操作它:
Ok("Welcome!").withSession(
"connected" -> "user@gmail.com")
注意上面的操作会替换整个session,如果你只是需要向一个已有的Session添加一个元素,你可以在传入的Session中添加一个元素,然后将它指定为一个新的Session:
Ok("Hello World!").withSession(request.session + ("saidHello" -> "yes"))
你也可以通过这种方式来从Session中删除数据:
Ok("Theme Reset!").withSession(request.session - "theme")
读取Session值
从HTTP 请求中取得一个Session:
def index = Action { requset =>
request.session.get("connected").map { user =>
Ok("Hello " + user)
}.getOrElse {
Unauthorized("Oops, you are not connected")
}
}
丢弃整个Session
有一个特殊的方法来丢弃整个Session:
Ok("Bye").withNewSession
Flash域
Flash几乎和Session一模一样,只有两点区别:
- 数据仅仅保存一个request
- Flash cookie没有被签名,便于用户修改
重要: Flash域应该仅仅在非Ajax应用中传递success/error消息。因为在复杂的web应用中没有任何request顺序的保证,Flash域可能会面临很多竞争性条件。
下面是一些Flash域的例子:
def index = Action { implicit request =>
Ok {
request.flash.get("success").getOrElse("Welcome!")
}
}
def save = Action {
Redirect("/home").flashing(
"success" -> "The item has been created")
}
你可以增加一个implicit的Flash参数,以便在view中获取Flash域的值:
@()(implicit flash: Flash)
...
@flash.get("success").getOrElse("Welcome!")
...
并在Action中,指定一个 implicit request => :
def index = Action { implicit request =>
Ok(views.html.index())
}
一个隐式的Flash将在view中随着隐式的request一起提供。
如果看到'could not find implicit value for parameter flash: play.api.mvc.Flash' 的错误提示,说明你的Action在当前域没有找到隐式的request。