Scala 播放框架处理会话状态

Scala 播放框架处理会话状态,scala,session,playframework-2.1,Scala,Session,Playframework 2.1,我有一个基于Play框架和Scala的Webapp。它是向用户呈现一组问题,每个问题都有一组答案。有些问题有单选按钮类型和答案,有些问题有复选框作为答案。当用户单击开始测试时,我调用控制器,获取问题列表及其答案,并将结果作为案例类返回给视图模板。我现在需要在用户回答每个问题时保持测试状态。他可以上一个,下一个,我需要记录他回答的所有问题 来自JavaEE背景,我认为我可以在会话中存储case类,并在控制器中操作它。但不幸的是,这看起来并不是这样的,因为Play框架的会话是字符串的键值对,而不是字

我有一个基于Play框架和Scala的Webapp。它是向用户呈现一组问题,每个问题都有一组答案。有些问题有单选按钮类型和答案,有些问题有复选框作为答案。当用户单击开始测试时,我调用控制器,获取问题列表及其答案,并将结果作为案例类返回给视图模板。我现在需要在用户回答每个问题时保持测试状态。他可以上一个,下一个,我需要记录他回答的所有问题


来自JavaEE背景,我认为我可以在会话中存储case类,并在控制器中操作它。但不幸的是,这看起来并不是这样的,因为Play框架的会话是字符串的键值对,而不是字符串对象。我现在只能使用我的应用程序,因为我对Play框架的经验有限,我想征求一些建议。

Play只支持会话字符串,因为它将所有会话状态存储在cookie中-这意味着Play节点可以扩展,而无需任何集群/状态共享技术

如果要存储的数据很小(小于2k),则只需将其序列化为JSON,或者在您的情况下,更简单的做法是将其序列化为逗号分隔的答案列表


否则,您可以将其存储在诸如memcached或redis之类的缓存中。

Play framework中根本没有状态,因此,如果您希望在多个HTTP请求之间保留一些数据,则可以方便地使用会话作用域,该作用域实际创建具有密钥/值对(字符串、字符串)的cookie,并且它们的大小限制为4KB

我的建议是使用Json,玩Json库非常棒。如果您有带有JSON组合符的模型,那么它就简单多了

Ok(render(Questions)).withSession("answers" -> Json.prettyPrint(Json.toJson(Answer)))
读取会话值的操作如下:

def index = Action { implicit request =>
      session.get("answers").map { answers =>
        val jsValueAnswers: JsValue = Json.parse(answers)
        val answersModel: YourAnswerModel = Json.fromJson(jsValueAnswers) 
        Ok("Got previous answers and created session cookie with them")
        .withSession("answers2" -> Json.prettyPrint(Json.toJson(answersModel)))
      }
    }
希望这对你有所帮助


Cheers

Play是一个设计为无状态的框架,因此您找不到任何服务器端会话的具体概念。当然,这并不是严格禁止的,如果您需要它,在本例中,您可以使用服务器端技术(缓存或数据库)作为项目的容器,并播放cookie会话来存储访问密钥字符串

这是使用播放缓存存储对象的示例:

import play.api.cache.Cache
import play.api.Play.current

val key = UUID.randomUUID.toString
Cache.set(key, yourModel, 0)
Ok.withSession("answer_key" -> key)
这是一个检索示例:

import play.api.cache.Cache
import play.api.Play.current

val key = session.get("answer_key").getOrElse("none")
val yourModel = Cache.getAs[ModelClass](key).getOrElse(//whatever you want if not exists)

memcached是一种数据库吗?我从来没用过。从它的名字来看,它看起来像是一种缓存,我可以用它来存储模拟会话的键、值对,并在那里存储我的对象。这是为了这个目的吗。问题是我需要在会话中存储整个测试,而不仅仅是用户看到的当前问题的答案。用户看到的问题有一组答案,他将选择一个并提交给服务器。然后,我应该接受他对该问题的回答,并针对该问题更新我的测试对象。我只是想知道如何利用Json来实现这一点。请你详细说明一下,因为我不足以存储将要呈现的问题的当前答案!一切都取决于对象的模型,您可以为对象编写自己的读/写/格式,或者使用宏Inception。case-class-Answer(id:Long,value:String)case-class-TestObject(id:Long,List(Answers))implicit-val-answerRead=Json.read-implicit-val-answerWrite=Json.writeMade一团之前的注释:)我这里是新的:)所以,在您的情况下,将会话值从字符串转换为json,而不是在每次POST/GET和更新时都转换为对象,这在我看来不是一个好的解决方案,因此我建议您使用James建议并使用memcached。缓存方法的问题是,即使在为会话指定超时之后,也不能保证数据会存在对象以在缓存中生存。所以我不想信任缓存。我不认为这是一个真正的问题。Play使用作为默认实现,它实现一个持久磁盘存储,在VM重启之间存储数据。您在JEE web会话中的类似行为。使用cookie,序列化数据的大小限制为4KB,而不使用缓存。为什么您认为这不是一个真正的问题?Play缓存机制背后的思想是检索频繁请求的对象,而不是作为会话的替代品。看看链接:第一段说缓存中的数据可能会丢失!正因为这个原因,我不想相信它。我认为这对你来说不是一个真正的问题。但我理解你的论点,你可以使用数据库和缓存进行优化。当然,作为cookies的替代品(Cookies不认为适合作为数据容器)。