使用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
?
答案 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