在Grails中发布嵌套资源的问题
我在理解Grails Restful控制器如何工作方面遇到了问题。 我正在尝试向嵌套资源发出post请求(见下文)。 我不确定我是否理解我需要更改以使其工作,因为看起来GET请求与其父资源项建立Bid的关联,但是当我尝试POST时,我被警告该项不能为空。
任何帮助表示赞赏!
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 { static responseFormats = ['json', 'xml'] BidController() { super(Bid) } @Override def getObjectToBind() { request.parameterMap.put('itemId', params.itemId) return request } }
ItemController.groovy
class ItemController extends RestfulController { static responseFormats = ['json', 'xml'] ItemController() { super(Item) } }
UrlMappings.groovy
class UrlMappings { static mappings = { "/items"(resources:"item") { "/bids"(resources: "bid") } } }
URL映射
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"}]}
我认为你可以通过覆盖createResource()方法来完成你想要的。
@Override protected Bid createResource() { Bid bid=super.createResource(); bid.item=Item.get(params.itemId) return bid; }
使用嵌套URL时,其他默认控制器操作可能无法按预期工作。 如果要确保只返回属于URL中项目的Bids,您可能还想覆盖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) }
RestfulController的实现有一个方法getObjectToBind()
,它返回请求对象。 我建议覆盖此方法并返回一个包含关键itemId
的映射,如此方法的注释中所述。
另一种选择可能是,在http json体中发送itemId。 这有点多余,因为信息已经在url中表示。 但作为一种解决方法,这也可能是一个很好的解决方案。
我建议使用@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 { static responseFormats = ['json', 'xml'] BidController() { super(Bid) } //don't override the getObjectTobind }
当我尝试将对象与一对一映射发布到另一个对象时,这对我有用。