基于Play框架中的查询参数进行路由

时间:2013-03-28 14:46:37

标签: scala playframework-2.0

我的网络应用程序将从外部系统触发。它将调用我的应用程序的一个请求路径,但对不同类型的请求使用不同的查询参数。

其中一个参数是定义要做什么的“动作”。其余的参数取决于“行动”。

所以我可以得到这样的请求参数:

action=sayHello&user=Joe
action=newUser&name=Joe&address=xxx
action=resetPassword
...

我希望能够在路径文件中对其进行类似的编码以便播放,因此它会执行基于查询参数的路由以及尽可能多的其他参数验证。

我所拥有的是具有大量可选参数的所有这些可能性的路由。处理它的动作以大模式匹配开始,以进行调度和参数验证。

谷歌搜索和检查SO只是弹出了大量的样本,其中params以某种方式编码在请求路径中,因此多个路径被路由到同一个动作,但我想反过来:一个路径路由到不同的动作。

我的一位同事说我们可以有一个“调度员”动作,它只会根据“动作”参数重定向。它会比当前解决方案更具结构性,但它不会消除应该有选择地传递给下一个动作的可选参数的长列表,所以我希望人们知道一个更好的解决方案: - )

BTW调用我的应用程序的外部系统是由另一家公司开发的,我对此设计没有任何影响,因此不能改变我的应用程序触发方式。

2 个答案:

答案 0 :(得分:6)

单个调度程序操作可能是要采用的方法,您无需在路径中指定所有可选参数。如果action始终存在,那么这是您真正需要的唯一。

GET  /someRoute      controller.dispatcher(action: String)

然后在您的操作方法中,您可以访问request.queryString以获取任何其他可选参数。

答案 1 :(得分:3)

注意:我经验丰富的Scala开发人员,因此可能会显示片段可以优化...对您来说重要的是它们有效且有效。

<强>因此...

您无需在routes文件中声明每个可选参数。这是类型param验证的最佳捷径,最好的选择是说服'其他公司'使用你准备的API ...无论如何你没有这种可能性你也可以处理 < em>他们的 请求。

一般情况下:调度程序方法似乎在这个地方是正确的,幸运的是,您不需要在routes中声明所有可选参数,并在操作/方法之间传递它它们可以直接从请求中获取。在PHP中,它可以与$_GET['action']和Java版本的Play 2控制器进行比较 - DynamicForm类 - form().bindFromRequest.get("action")

假设你有一条路线:

GET     /dispatcher      controllers.Application.dispatcher

在这种情况下,您的调度程序操作(和其他方法)可能如下所示:

def dispatcher = Action { implicit request =>
    request.queryString.get("action").flatMap(_.headOption).getOrElse("invalid") match {
      case "sayHello" => sayHelloMethod
      case "newUser"  => newUserMethod
      case _          => BadRequest("Action not allowed!")
    }
}

// http://localhost:9000/dispatcher?action=sayHello&name=John
def sayHelloMethod(implicit request: RequestHeader) = {
  val name = request.queryString.get("name").flatMap(_.headOption).getOrElse("")
  Ok("Hello " + name )
}

// http://localhost:9000/dispatcher?action=newUser&name=John+Doe&address=john@doe.com
def newUserMethod(implicit request: RequestHeader) = {
  val name = request.queryString.get("name").flatMap(_.headOption).getOrElse("")
  val address = request.queryString.get("address").flatMap(_.headOption).getOrElse("")
  Ok("We are creating new user " + name + " with address " + address)
}

当然,您需要“手动”验证传入的类型和值,尤其是当操作将在DataBase上运行时,无论如何,您现在已经解决了问题的最大部分。