Play 2.0 中文资料 - 会话和 Flash 域

会话和 Flash 域在 Play 中有何不同

如果你不得不要跨多个 HTTP 请求来保存数据, 你可以存在会话或是 Flash 域中. 存储在会话中的数据在整个会话期间可用, 而存储在 Flash 域中数据只对下一次请求有效.

理解到会话和 Flash 数据不是由服务器来存储,而是以 Cookie 机制添加到每一次后续的 HTTP 请求是很重要的. 这也就意味着数据的大小是很受限的 (不到 4 KB) ,而且你只能存储字符串.

当然了, Cookie 值是由密钥签名了的,这使得客户端不存修改 Cookie 数据(或者说这样做会让它失效).

Play 会话不能当成缓存来用.  假如你需要缓存与某一会话相关的数据, 你可以使用 Play 内置的缓存机制并存储一个唯一的 ID 在用户会话中与之关联.

会话没有技术上的超时控制. 它在用户关闭 Web 浏览器后就会过期. 如果你的应用需要一种功能性的超时控制, 那就在用户会话中存储一个时间戳,并在应用需要的时候用它 (例如: 最大的会话持续时间, 最大的非活动时间, 等等.).

读取会话值

你可以从 HTTP 请求中获取传入的会话:

另一种方式是,你能从请求中隐式的获取会话:

Unmi 注: request.session 的类型是  Map[String, String],其中存放的就是一个个 Session 键值对,而 Map 的 get(key:String) 方法返回的是 Option[String],即 Some(value) 或是 None 值(key不存在时取得的值),Some(value).map() 方法能处理期中的 value 值。.getOrElse() 方法是在 session.get("connected") 为 None 时执行的操作。

看一下 Play 存储的会话在 Cookie 中的样子:

可以看到存储 Cookie 时用的 Key 是 “PLAY_SESSION"。值用了密钥签名了,随意修改了值也是无效的。

存储数据到会话中

由于 Session 是个 Cookie, 也是个 HTTP 头,所以你可用操作其他 Result 属性那样的方式操作 Session 数据:

Unmi 注: 上面的方法调用的是 Results.scala 中的 def withSession(session: (String, String)*): A 方法。

注: 这会替换掉整个 Session. 假如你需要添加元素到已有的 Session 中, 方法是先添加元素到传入的 Session 中, 接着把它作为新的Session:

你可以用同样的方式从传入的 Session 中移除任何值:

Unmi 注: 上面两段代码调用的是 Results.scala  中的 def withSession(session: Session): A 方法。因为 session 是 Map[String, String] 类型,所以可以用 +/- 号来增减元素。

废弃整个 Session

有一个特殊的操作用来废弃整个 Session:

Flash 域

Flash 域工作方式非常像 Session, 但有两点不同:

  • 数据仅为一次请求而保留
  • Flash 的 Cookie 未被签名, 这留给了用户修改它的可能性.

重点: Flash 域仅能用于简单的非 Ajax 应用中在传送 成功/错误 的消息. 由于数据只保存给下一次请求,而且在复杂的 Web 应用中无法保证请求的顺序,所以在竞争条件下 Flash 可能不那么好使.

下面是使用 Flash 域的例子:

Unmi 注: Flash 域的数据可在服务端重定向到的下一个请求中可见。再来看一个 Flash 域的 Cookie 发生了什么,因为使用了 Redirect 转向,所以用浏览器捕捉不到这时候的 Cookie 值,但可以用 curl -v 命令来查看,见下图:

上图中可以见到当转向到下个请求 /home 时用的 Cookie 的 Key 是 ”PLAY_FLASH“,并且值未被签名。

类别: PlayFramework, Scala. 标签: , , . 阅读(426). 订阅评论. TrackBack.

Leave a Reply

Be the First to Comment!

avatar
wpDiscuz