在过滤器中访问 request.JSON 后的 Grails 2.5.0 控制器命令对象绑定

Grails 2.5.0 controller command object binding after accessing request.JSON in a filter

在 Grails 2.5.0 控制器操作方法中,如果在过滤器中访问 request.JSON,HTTP JSON 主体中的属性似乎不会用于命令对象绑定。

这是为什么?这对我来说没有任何意义。

有什么方法可以让 request.JSON 在过滤器中使用,也可以用于命令对象绑定?

是的,这是 Grails 在与请求进行数据绑定时的默认行为 body。当您在过滤器中通过 request.JSON 读取请求 body 时,相应的输入流将关闭或变空。因此,现在 Grails 无法进一步访问该请求 body 以绑定到命令 object.

因此,您可以在过滤器中自行访问请求 body,也可以将其与命令 object 一起使用,但不能同时使用。

绑定请求Body到命令Objects标题http://grails.github.io/grails-doc/2.5.0/guide/theWebLayer.html#dataBinding:

Note that the body of the request is being parsed to make that work. Any attempt to read the body of the request after that will fail since the corresponding input stream will be empty. The controller action can either use a command object or it can parse the body of the request on its own (either directly, or by referring to something like request.JSON), but cannot do both.

那么,您想要实现的目标是不可能直接实现的。但是,您可以做一些不同的事情。在你的过滤器中,读取传入的请求 body 并存储到 paramssession (如果过滤器将请求传递给控制器​​)​​然后手动绑定参数:

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 提供了一个 link 更干净的解决方案 Http Servlet request lose params from POST body after read it once.