Playframework用户演员与用户会话

时间:2016-01-12 12:49:29

标签: scala playframework websocket akka

我对Scala,Play Framework和Akka都很陌生。在我目前正在处理的项目中,Web应用程序的用户应该能够以异步方式向服务器询问几件事(比如开始特定的计算)。如果服务器完成,它应该通知用户也是异步。我通过 WebSocket 连接来解决这个需求,该连接是在用户首次连接应用程序并且WebSocket由UserActor处理时建立的,该连接附加到用户会话:

def ws = WebSocket.tryAcceptWithActor[JsValue, JsValue] { implicit request =>

    Future.successful(request.session.get(UID) match {
        case None => Left(Forbidden)
        case Some(uid) => Logger.info("WebSocket has accepted the request with uid " + uid)
                          Right(UserActor.props(uid))
    })
}

目前, UserActor 唯一能做的就是从WebSocket收到JsValue的邮件。请求索引时会生成会话的UID:

def index = Action { implicit request => {
    val uid = request.session.get(UID).getOrElse {
      counter += 1
      counter.toString
    }
    Ok(views.html.index(uid)).withSession {
      Logger.debug("create uid " + uid)
      request.session + (UID -> uid)
    }}
}

UserActor应代表服务器上的实际用户,因此包括用户可以在服务器上执行的所有操作的逻辑。只要我通过WebSocket发送所有用户互动,这就可以正常工作。

现在其他用户输入是什么情况,比如表单提交?该应用程序包含一个表单,其数据不应超过WebSocket,而是通过POST请求(可能使用AJAX)提交,并在控制器中绑定到模型中,如文档中所述。 / p>

def saveContact = Action { implicit request =>
  contactForm.bindFromRequest.fold(
    formWithErrors => {
      BadRequest(views.html.contact.form(formWithErrors))
    },
    contact => {
      val contactId = Contact.save(contact)
      Redirect(routes.Application.showContact(contactId)).flashing("success" -> "Contact saved!")
    }
  )
}

此示例取自Playframework documentation

现在,如何将表单提交处理程序与UserActor链接?假设我想告诉用户actor已提交表单。一个简单的例子是,UserActor一旦收到,就会将WebSocket的一个值重新发送回客户端。所以基本上问题就解决了我想从任何UserActor发送Controller消息的问题。

我可能想出通过WebSocket发送所有表单数据的想法,但我也希望将来能够实现大数据的上传,我想解决这个问题,如in this blog post所述。然后我可以想象的一个场景是应该为它收到的每个块发送UserActor

我想一个问题是UserActorWebSocketActor是相同的,我宁愿拆分他们的逻辑,这样UserActor只与Session相关联,但我不知道如何做到这一点。也许我需要另一个演员,比如UserManager,它会跟踪当前的UserActors并启用对UserActors的访问权限?

您是否有任何建议,建议或可能的示例应用程序也处理此案例?非常感谢你提前。

祝你好运

1 个答案:

答案 0 :(得分:0)

请勿将传递给tryAcceptWithActor的演员用作User的代表。它应代表与该用户的特定会话。可能是用户可能在特定时间打开的许多并发会话(多个浏览器或选项卡)之一。

创建一个单独的actor来表示用户及其可以执行的所有操作。现在会话actor应该将他们的消息转发给用户actor。传统的控制器方法也可以将请求转发给相应的用户角色。