我在理解Grails Restful控制器如何工作方面遇到了问题。我正在尝试向嵌套资源发布帖子请求(见下文)。我不确定我是否理解我需要更改以使其工作,因为看起来GET请求与其父资源项构建Bid的关联,但是当我尝试POST时,我被警告该项不能为空。< / p>
感谢任何帮助!
Item.groovy
class Item {
static hasMany = [bids:Bid]
}
Bid.groovy
class Bid {
Integer ownerId
Double amount
static belongsTo = [item:Item]
static constraints = {
ownerId nullable: false
amount nullable: false
}
}
BidController.groovy
class BidController extends RestfulController<Bid> {
static responseFormats = ['json', 'xml']
BidController() {
super(Bid)
}
@Override
def getObjectToBind() {
request.parameterMap.put('itemId', params.itemId)
return request
}
}
ItemController.groovy
class ItemController extends RestfulController<Item> {
static responseFormats = ['json', 'xml']
ItemController() {
super(Item)
}
}
UrlMappings.groovy
class UrlMappings {
static mappings = {
"/items"(resources:"item") {
"/bids"(resources: "bid")
}
}
}
网址映射
Controller: item
| GET | /items | Action: index
| GET | /items/create | Action: create
| POST | /items | Action: save
| GET | /items/${id} | Action: show
| GET | /items/${id}/edit | Action: edit
| PUT | /items/${id} | Action: update
| PATCH | /items/${id} | Action: patch
| DELETE | /items/${id} | Action: delete
Controller: bid
| GET | /items/${itemId}/bids | Action: index
| GET | /items/${itemId}/bids/create | Action: create
| POST | /items/${itemId}/bids | Action: save
| GET | /items/${itemId}/bids/${id} | Action: show
| GET | /items/${itemId}/bids/${id}/edit | Action: edit
| PUT | /items/${itemId}/bids/${id} | Action: update
| PATCH | /items/${itemId}/bids/${id} | Action: patch
| DELETE | /items/${itemId}/bids/${id} | Action: delete
发布请求
POST /AuctionService/items/1/bids HTTP/1.1
Content-Type: application/json
Host: localhost:8080
Connection: close
Content-Length: 34
{
"ownerId": 1,
"amount": 3.00
}
响应
HTTP/1.1 422 Unprocessable Entity
Server: Apache-Coyote/1.1
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Fri, 25 Jul 2014 17:44:03 GMT
Connection: close
{"errors":[{"object":"auctionservice.Bid","field":"item","rejected-value":null,"message":"Property [item] of class [class auctionservice.Bid] cannot be null"}]}
答案 0 :(得分:1)
我认为您可以通过覆盖createResource()方法来完成您想要的任务。
@Override
protected Bid createResource() {
Bid bid=super.createResource();
bid.item=Item.get(params.itemId)
return bid;
}
使用嵌套URL时,其他默认控制器操作可能无法按预期工作。 如果要确保只返回属于URL中项目的出价,您可能还想覆盖queryForResource和index
@Override
protected Stay queryForResource(Serializable id) {
def itemId=params.itemId
Bid.where {
id==id && item.id == itemId
}.find()
}
def index(Integer max) {
params.max = Math.min(max ?: 10, 100)
def itemId=params.itemId
respond Bid.where {
item.id==itemId
}.list(params)
}
答案 1 :(得分:0)
RestfulController的实现有一个方法getObjectToBind()
,它返回请求对象。我建议覆盖此方法并返回一个包含密钥itemId
的映射,如此方法的注释中所述。
另一种选择可能是,在http json体中发送itemId。这有点多余,因为信息已经在网址中表示。但作为一种解决方法,这也可能是一个很好的解决方案。
答案 2 :(得分:0)
我建议使用@Resource注释Domain类,即使您实现自己的控制器也是如此。 Grails文档似乎表明你做了一个或另一个,注释域或编写自己的控制器扩展RestfulContoroller。
我发现没有域类注释,请求对象在createResource()方法中没有正确绑定。所有属性都为null。一旦我添加了域注释,就会按照我的预期重新绑定绑定。
在您的情况下,我希望/希望Grails能够处理所有关系,而无需您自己管理项目ID。所以,
@Resource(uri='items')
class Item {
static hasMany = [bids:Bid]
}
和...
@Resource(uri='bids')
class Bid {
Integer ownerId
Double amount
static belongsTo = [item:Item]
static constraints = {
ownerId nullable: false
amount nullable: false
}
}
希望您不再需要覆盖getObjectToBind()。
class BidController extends RestfulController<Bid> {
static responseFormats = ['json', 'xml']
BidController() {
super(Bid)
}
//don't override the getObjectTobind
}
当我尝试将对象与一对一映射发布到另一个对象时,这对我有用。