Session and Flash scopes【翻译】


在Play中的Session and Flash scopes有什么不同

如果你想跨多个HTTP请求存储数据,你需要把它们存储到Session或者Flash scopes中。在Session中的数据存储在整个用户Session周期可用,在Flash scope 存储的数据仅在下次请求时可用。

理解Session 和Flash数据不是存储在服务端而是使用Cookie机制添加到每一个随后的HTTP请求中这一点很重要。这意味着数据大小是非常有限的(最大4K),并且你只能存储String类型的值。Cookie的默认名是 PLAY_SESSION。这可以在应用的配置文件中修改Key

如果Cookie的名字被修改,可以使用在设置和清除Cookie中提到的方法清除之前的Cookie。

当然,由于Cookie值使用了秘钥签名因此客户端不能修改Cookie的数据(或者数据会无效)

Paly没有打算把 Session当缓存用。如果你需要缓存一些与特定Session相关的数据,你可以使用Play内置缓存机制,在用户Session存储一个唯一ID,让这些数据与特定的用户相关联。

默认情况下,Session没有专门的超时。当用户关闭浏览器时它才过期。如果对于特定的应用,你需要一个实用的超时,在用户的Session内存储一个时间戳,而你的应用需要使用它(例如,最大的Session持续时间,最大的不活跃周期等等),你也可以通过配置的Key值play.http.session.maxAge(单位毫秒),设置一个SessionCookie的最大年龄,但是注意这不能防止攻击者获取或重新使用已经过期的数据。

在Session中存储数据

由于Session仅仅是一个Cookie,也只是一个HTTP头。你可以像操作其他结果属性那样操作Session的数据:

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 { request =>  
request.session.get("connected").map { user =>  
Ok("Hello " + user)  
}.getOrElse {
Unauthorized("Oops, you are not connected")  
}
}

移除整个Session

这是一个专门移除整个Session的操作:

Ok("Bye").withNewSession  

Flash scope

Flash scope的原理跟Session非常像,但是有两点不同:

  • 数据只保存在一个请求中
  • Flash Cookie 没有签名,用户有可能修改这里的值

重点:Flash scope应当仅被用来在简单的非Ajax应用中传输成功/错误信息。由于数据仅保持到下一次请求,并且由于在复杂的Web应用中不能保证请求的顺序,Flash scope受制于竞争条件。

这是几个使用Flash scope的例子:

def index = Action { implicit request =>  
Ok {  
request.flash.get("success").getOrElse("Welcome!")  
}
}

def save = Action {  
Redirect("/home").flashing(  
"success" -> "The item has been created")
}

在你的视图中获取Flash scope值,增加一个隐式的Flash参数:

@()(implicit flash: Flash)
...
@flash.get("success").getOrElse("Welcome!")
...

在你的Action中,如下所示指定一个implicit request =>:

def index = Action { implicit request =>  
Ok(views.html.index())  
}

隐式Flash将基于隐式请求提供给视图。

如果出现错误‘could not find implicit value for parameter flash: play.api.mvc.Flash’,那么这是因为你的Action在作用域内没有隐式请求。

祝青

继续阅读此作者的更多文章