request.JSON
在 Grails 2.5.0 控制器操作方法中,如果已在过滤器中访问,似乎 HTTP JSON 正文中的属性将不会用于命令对象绑定。
这是为什么?这对我来说没有任何意义。
有没有办法允许request.JSON
在过滤器中使用,也可以用于命令对象绑定?
request.JSON
在 Grails 2.5.0 控制器操作方法中,如果已在过滤器中访问,似乎 HTTP JSON 正文中的属性将不会用于命令对象绑定。
这是为什么?这对我来说没有任何意义。
有没有办法允许request.JSON
在过滤器中使用,也可以用于命令对象绑定?
是的,这是 Grails 在与请求正文进行数据绑定时的默认行为。当您通过request.JSON
过滤器读取请求正文时,相应的输入流将被关闭或变为空。因此,现在 Grails 无法进一步访问该请求主体以绑定到命令对象。
因此,您可以在过滤器中自行访问请求正文,也可以将其与命令对象一起使用,但不能同时使用两者。
从将请求正文绑定到命令对象标题http://grails.github.io/grails-doc/2.5.0/guide/theWebLayer.html#dataBinding:
请注意,正在解析请求的主体以使其正常工作。此后任何读取请求正文的尝试都将失败,因为相应的输入流将为空。控制器操作可以使用命令对象,也可以自己解析请求的主体(直接或通过引用 request.JSON 之类的东西),但不能同时进行。
所以,你想要实现的目标是不可能直接实现的。但是,你可以做一些不同的事情。在您的过滤器中,读取传入的请求正文并存储到params
或session
(如果过滤器将请求传递给控制器),然后手动绑定参数:
MyFilters.groovy
class MyFilters {
def filters = {
foo(/* your filter */) {
before = {
// Your checks
Map requestData = request.JSON as Map
session.requestData = requestData
return true
}
}
}
}
现在,在您的控制器操作中,而不是执行以下操作:
class MyController {
def fooAction(MyCommandObject object) {
}
}
做这样的事情:
class MyController {
def fooAction() {
MyCommandObject object = new MyCommandObject(session.requestData)
// Clear from session to clear up the memory
session.requestData = null
}
}
更新:我提供的上述解决方案效果很好,但不干净。@JoshuaMoore 提供了一个链接,其中包含一个更清洁的解决方案Http Servlet request lost params from POST body after read it once。