我想知道在 grails 应用程序中使用命令对象是否有任何首选模式。特别是如果我应该定义另一种方法来保存对象或使用相同的控制器方法来呈现表单和保存?
让我展示一个示例,其中包含用于呈现表单和保存对象的单独方法
def user(int id) {} // shows the edit user form - user.gsp. Submit takes us to saveUser method
def saveUser(UserCommand cmd) {} // actually saves the user, then redirects somewehre else
一切都应该工作,但是:
如果存在验证错误,则该saveUser
方法必须执行该user
方法所做的整个逻辑。如果在显示用户表单之前,我们必须从数据库加载其他对象,执行一些计算等......它必须再次完成,因为我们必须再次显示表单并包含验证错误。这会导致不必要的代码重复。当验证失败时,我无法重定向到user
方法,因为我会丢失命令对象以及与之相关的任何错误。因此我将无法显示验证错误。
使用相同方法保存和呈现表单的另一个示例
def user(UserCommand cmd, Integer id) {
def u=User.load(id)
if (request.method=="POST"&&cmd.validate()) {
// populate u with command object values and save in database
// then redirect somewhere
}
}
此示例消除了对代码重复的需要。仅在有POST
请求时才保存用户,在其他情况下仅显示表单。如果出现验证错误,它们可以访问并显示在 gsp 页面上。
主要问题是即使有GET
对用户页面的请求(这意味着显示 user.gsp 表单),也会创建并验证一个空的命令对象实例(因为它是在同一个控制器中定义的)。因此,每次显示表单时都会出现验证错误,即提供的值为空(因为命令对象为空)
两种场景都可以轻松修改以正常工作(例如:在场景 1 中的会话中重定向之前保存命令对象,并且仅POST
在场景 2 中有请求时才显示验证错误)但它需要额外的代码并且似乎不是很优雅.
有没有更简单 - 更多“圣杯”的解决方案来解决这个问题?