【问题标题】:Routing based on query parameter in Play frameworkPlay框架中基于查询参数的路由
【发布时间】:2013-03-19 01:39:23
【问题描述】:

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

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

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

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

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

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

谷歌搜索和检查 SO 只是弹出了大量示例,其中参数以某种方式在请求路径中编码,因此多个路径被路由到相同的操作,但我想要相反:一个路径路由到不同的操作。

我的一位同事说,我们可以有一个“调度程序”操作,它会根据“操作”参数进行重定向。它会比当前的解决方案更有条理,但它不会消除应该有选择地传递给下一个操作的一长串可选参数,所以我希望有人知道一个更好的解决方案:-)

顺便说一句,调用我的应用的外部系统是由另一家公司开发的,我对这个设计没有影响,所以不能改变我的应用的触发方式。

【问题讨论】:

    标签: scala playframework-2.0


    【解决方案1】:

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

    GET  /someRoute      controller.dispatcher(action: String)
    

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

    【讨论】:

      【解决方案2】:

      注意:我是不是经验丰富的 Scala 开发人员,所以可能提供的 sn-ps 可以优化......对你来说重要的是它们是有效的并且可以工作。 p>

      那么...

      您不需要在routes 文件中声明每个可选参数。这是类型参数验证的绝佳捷径,最好的选择是说服“其他公司”使用您准备的 API...无论如何,如果您没有这种可能性,您也可以处理 他们的根据需要提出的要求。

      总的来说:dispatcher 方法似乎在这个地方是正确的,幸运的是,您不需要在 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)
      }
      

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

      【讨论】:

      • 您的回答已经过去了将近 2 年。最新的播放框架有没有更好的解决方案?
      • @Ikrom,我认为更好的解决方案就像接受的答案,但使用选项参数:GET /someRoute controller.dispatcher(action: Option[String])
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-07-07
      • 1970-01-01
      • 1970-01-01
      • 2018-09-18
      • 2015-08-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多