scala Play 框架处理会话状态

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20772841/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 05:57:56  来源:igfitidea点击:

Play framework handling session state

scalasessionplayframework-2.1

提问by sparkr

I have a Webapp that is built on top of the Play framework and Scala. It is about presenting the user with a set of questions with each question having a set of answers. Some of the questions have radio button types an answers and some have check boxes as answers. When the user clicks start test, I call the controller, fetch the list of questions with its answers and return the result as a case class to the view template. I now need to maintain the state of the test as the user answers each question. He can go previous, next and I need to keep track of all the questions that he answered.

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

Coming from a Java EE background, I thought I can store the case class in the session and manipulate it in my controller. But that unfortunately does not look like that as the Play framework's session is a key value pair of String, String and not a String, Object. I'm now stuck with my app and since my experience with the Play framework is limited, I would like to ask for suggestions.

来自 Java EE 背景,我认为我可以在会话中存储案例类并在我的控制器中操作它。但不幸的是,这看起来并不像那样,因为 Play 框架的会话是 String, String 而不是 String, Object 的键值对。我现在坚持使用我的应用程序,由于我对 Play 框架的经验有限,我想征求建议。

回答by B. Pesevski

There is no state at all in Play framework so if you want to keep some data across multiple HTTP requests its handy to use Session scope that actually creates cookies with key/value pair (String, String) and they are limited to 4KB size.

Play 框架中根本没有状态,因此如果您想在多个 HTTP 请求中保留一些数据,可以方便地使用 Session 范围,该范围实际创建带有键/值对(字符串、字符串)的 cookie,并且它们的大小限制为 4KB。

My suggestion is to do it with Json, Play-json library is awesome. IF you have models with JSON Read/Write/Formatcombinators than its simple.

我的建议是用 Json 来做,Play-json 库很棒。如果您有带有 JSON读/写/格式组合器的模型,那么它很简单。

Ok(render(Questions)).withSession("answers" -> Json.prettyPrint(Json.toJson(Answer)))

Reading a session value can be done like this:

读取会话值可以这样完成:

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)))
      }
    }

Hope this help you a bit.

希望这对你有所帮助。

Cheers

干杯

回答by James Roper

Play only supports Strings for sessions because it stores all session state in cookies - this means Play nodes can scale without the need for any sort of clustering/state sharing tech.

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

If the data you want to store is small (less than 2k), then just serialise it into JSON, or it sounds like in your case, even simpler would be to serialise it into a comma separated list of answers.

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

Otherwise, you can store it in a cache such as memcached or redis.

否则,您可以将其存储在缓存中,例如 memcached 或 redis。

回答by Marco

Play is a framework designed to be stateless, so you do not find any concrete concept of server side session. Of course, this is not strictly prohibited, if you need it, as in this case, you can use a server-side technology (cache or database) as a container for your items and Play-cookie session for storing the access key string.

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

This is an example of storing object using Play Cache:

这是使用 Play Cache 存储对象的示例:

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)

and this is an example of retrieval:

这是检索的示例:

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)