在筛选器中访问request.JSON后,Grails 2.5.0控制器命令对象绑定

时间:2015-07-24 22:28:17

标签: json grails controller action command-objects

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

为什么?它对我没有任何意义。

有没有办法允许在过滤器中使用request.JSON,还有命令对象绑定吗?

1 个答案:

答案 0 :(得分:4)

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

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

将请求正文绑定到命令对象标题http://grails.github.io/grails-doc/2.5.0/guide/theWebLayer.html#dataBinding

  

请注意,正在解析请求的正文以使其工作。   之后任何尝试读取请求正文的行为都将失败   相应的输入流将为空。控制器动作   可以使用命令对象,也可以解析主体   请求自己(直接或通过引用类似的东西)   request.JSON),但不能同时做到。

那么,你想要实现的是不可能直接实现的。但是,你可以做一些不同的事情。在您的过滤器中,读取传入的请求正文并存储到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提供了一个清洁解决方案Http Servlet request lose params from POST body after read it once的链接。