在grails中控制器操作之间传递对象的最佳方式
答
(迟到了,但是......)我使用的Grails 2.4.4,它允许我做如下:
def usernameLogin() {
SecurityToken securityToken = authService.loginWithUserPass(params.user, params.pass)
chain action: 'afterLogin', model: [securityToken: securityToken]
}
def ssoLogin() {
SecurityToken securityToken = authService.ssoLogin(params.remoteUser, params.key)
chain action: 'afterLogin', model: [securityToken: securityToken]
}
def afterLogin() {
SecurityToken securityToken = (SecurityToken) chainModel['securityToken']
if (securityToken.valid) {
forward action: 'loggedInRedirect'
}
else {
forward action: 'loginFailed'
}
}
- SecurityToken是包含字符串和枚举对象
- 密钥使用源动作“链动作”,2)使用在chainModel目标动作
希望这有助于为1)。
答
较早的答案不完整。所以,我正在将它们与我的输入一起编译并使它们更清晰。
你有两个选择:
-
链接的行动:
def action1() = { DomainClass domainInstance = DomainClass.findById(params.id); chain (action: 'action2', model: [domainInstance: domainInstance]); } def action2() = { DomainClass domainInstance = chainModel?.domainInstance ?: DomainClass.findById(params.id); [domainInstance: domainInstance]; }
然而,继任者的行动似乎使用一个新的数据库会话 不是重用的前身(可能也可以在Grails中配置为 ,但我不知道如何)。因此任何延迟加载的实体可能不会完全加载到后续操作中,并且 可能会给LazyInitializationException(当然取决于您的ORM配置)。
-
转发请求:
def action1() = { DomainClass domainInstance = DomainClass.findById(params.id); forward (action: 'action2', model: [domainInstance: domainInstance]); } def action2() = { DomainClass domainInstance = request?.domainInstance ?: DomainClass.findById(params.id); [domainInstance: domainInstance]; }
不同于前面的情况,请求转发重新使用现有的会议,以便延迟加载的问题不会发生。
正如您所看到的,两者的语法几乎完全相同。但是,由于上述问题,您应该根据相关要求转发请求转发。另一个重要的细节是关于在页面加载时/之后在地址栏中查看的URL。转发请求将保留页面URL,同时链接操作会将页面URL更改为最新操作的页面URL。