Grails rest-api应用程序处理多个参数

时间:2016-03-07 23:36:42

标签: rest grails

使用Grails 3.1.3,我创建了一个rest-api,以便我能够捕获不仅查询一个参数而且需要多个参数的GET请求。我不知道如何在UrlMappings文件中正确编码。以下是详细信息。

域类:

class ProdDetail {
  Integer pid
  String title
  String category
  Integer year
}

其中一些在BootStrap中:

new ProdDetail(pid:'101', title:'No Highway', author:'Nevil Shute', category:'fiction', year:1948).save(failOnError:true)
new ProdDetail(pid:'214', title:'In the Country of Men', author:'Hisham Matar', category:'misery', year:2007).save(failOnError:true)

控制器:

protected List<ProdDetail> listAllResources(Map params) {

  println params

  try {
     ProdDetail.where {
        if (params.category && params.maxYear) {
           category == params.category && year <= params.int('maxYear')
        } else if (params.category) {
           category == params.category
        } else if (params.maxYear) {
           year <= params.int('maxYear')
        } else {
           pid > 0
        }
     }.list()
  } catch (Exception e) {
     []
  }
}

UrlMappings:

static mappings = {
   "/prodDetails"(resources:'prodDetail')
   "/prodDetails/category/$category?"(controller:'prodDetail', action:'index')
   "/prodDetails/yearUnder/$maxYear?"(controller:'prodDetail', action:'index')
   // the line below is not right I think, what's the correct format?
   "/prodDetails/combo/$category?&$maxYear?"(controller:'prodDetail', action:'index')
}

现在,这两个卷发会起作用:

curl localhost:8080/prodDetails/category/misery
curl localhost:8080/prodDetails/yearUnder/2007

这个未能进入控制器中的所需子句以检测两个参数:

curl localhost:8080/prodDetails/combo/?category=misery&maxYear=2007

它只检测'category'而不是'maxYear',它认为它是'null'。

我怎样才能满足这样的curl

2 个答案:

答案 0 :(得分:2)

如果这些参数不是网址的一部分,则无需在UrlMappings中指定参数:

不需要这个:

"/prodDetails/combo/$category&?$maxYear?"(controller:'prodDetail', action:'index')

是的,您需要这个以匹配控制器/操作的URL(但删除?)

"/prodDetails/yearUnder/$maxYear?"(controller:'prodDetail', action:'index')

此外,您不需要listAllResources(Map params)

中的地图参数

“params”是控制器的注入属性,println params可以正常工作:listAllResources()

我要做的是定义:

listAllResources(String category, int maxYear, ...)其中......是行动可以接收的所有参数,大部分都是可选的,因此如果您的请求中未包含空值,您将收到空值。

请记住:UrlMappings将URL映射到控制器/操作,并且您具有相同的控制器/操作,因此我将删除所有映射并处理操作中的可选参数,只检查哪些是空的。

修改(考虑评论)

问:该方法没有超载来处理类似

的参数

答:方法是动态的,这是Grails / Groovy,而不是Java。即使所有参数都为空,它也会调用action方法。我建议您详细阅读Grails控制器文档。

问:发现listAllResources方法从未被调用

答:从操作中删除protected关键字,只有子类才能调用该方法。此外,您可以添加UrlMapping以避免用户调用该URL(匹配URL并返回404 Not Available或类似内容)

问:我想处理像这个localhost这样的GET请求:8080 / prodDetails / combo?category = misery&amp; year = 2016&amp; title = commonTitle,i)如何在UrlMappings中输入,ii) listAllResources方法看起来像?

A:

static mappings = {
   // if "compo" comes in the action portion, map that to the listAllResources method
   // as I said, if all parameters comes in the query string, no further actions are needed, if you need parameters to be part of the URL path, then you need to play with the $xxxx in the URL
   "/prodDetails/combo"(controller:'prodDetail', action:'listAllResources')
}

def listAllResources()
{
   println params
   // logic here
   render "OK"
}

检查:

答案 1 :(得分:2)

这取决于您希望网址的外观,但假设您希望您的请求如下所示:

http://localhost:8080/prodDetails/combo/misery?maxYear=2007&title=common

UrlMappings应该看起来像

static mappings = {
   "/prodDetails/combo/$category"(controller:'prodDetail', action:'index')
}

然后控制器中的params对象应该包含$category中的任何内容,在此示例中为痛苦,以及?之后的其他参数。

如果您希望参数位于路径中,您可以执行以下操作:

static mappings = {
   "/prodDetails/combo/$category/$title/$maxYear"(controller:'prodDetail', action:'index')
}

请求将是:

http://localhost:8080/prodDetails/combo/misery/common/2007

另一个选择是使用命令对象。所以如果你有:

static mappings = {
   "/prodDetails/combosearch"(controller:'prodDetail', action:'comboSearch')
}

然后在控制器旁边创建了一个名为ComboSearchCommand.groovy的对象,它看起来像:

import grails.validation.Validateable
class ComboSearchCommand implements Validetable {
    String category
    String title
    int maxYear

    static constraints = {
        category blank: false, nullable: true
        title blank: false, nullable: true
        maxYear blank: false, nullable: true
    }
}

(您可以像域对象一样进行验证)

然后在你的控制器中你有方法取命令对象而不是params

protected List<ProdDetail> comboSearch(ComboSearchCommand command) {
    println command.category
}

然后您的网址将是

http://localhost:8080/prodDetails/combosearch?category=misery&maxYear=2007&title=common

参数将绑定到命令对象。

我已经使用了很多,您可以共享验证或让您的命令对象继承域对象的验证,具有很大的灵活性。

https://grails.github.io/grails-doc/latest/guide/single.html#commandObjects