重构 Grails 命令验证

Posted

技术标签:

【中文标题】重构 Grails 命令验证【英文标题】:Refactoring Grails command validation 【发布时间】:2014-09-04 17:01:47 【问题描述】:

在我的应用程序中,我有很多如下代码:

def add(CreatePersonCommand command) 
    if(command.hasErrors()) 
        redirect(action: 'add')
        return
    

我不喜欢这种重复,所以我想重构它。我希望 Grails 会有如下内容:

@Validate(action:'someAction')
def add(CreatePersonCommand command) 


或者

def add(@Valid CreatePersonCommand command) 

这将自动验证命令,并在出现错误时重定向到 GSP。我尝试使用拦截器和过滤器创建类似的东西,但失败了,因为我无法访问过滤器中的操作和命令。

也许我遗漏了一些东西,但有没有更好的方法来处理这个问题,或者实现类似上面的东西?

【问题讨论】:

不存在这样的功能。这将很容易实现。如果我要这样做,我会编写一个 AST 转换来完成它。所有当前的命令对象处理都是由 AST 转换强加的。 我之所以这么问,是因为我正在考虑我们可以在 Grails 核心中做哪些事情来改进这一点。如果命令对象有错误或其他选项,提供类似机制来指定要呈现的视图通常很有用。可能还为您提供一些机制来提供您自己的处理程序,该处理程序在命令对象出现错误时调用,您可以做任何您想做的事情。 我没有把它作为答案,因为它不是真正的答案,至少不是那种对 *** 有益的答案。我认为这个问题对 *** 也不是特别有用。它被设置为一个问题,但实际上只是开始讨论更适合 Grails 小组groups.google.com/d/forum/grails-dev-discuss 的可能性。 " 它应该在发生错误时重定向到一个视图。哪个 AST 转换现在可以解决这个问题?"目前没有 AST 转换可以解决这个问题。 Grails 中不存在此功能。 @JeffScottBrown - 我在 Githb 上创建了一个功能请求 github.com/grails/grails-core/issues/603 【参考方案1】:

考虑到问题中的 cmets,我想出了一个临时解决方法。

有一个类似的命令:

@grails.validation.Validateable
class FooCommand implements Serializable 
    String username
    String email
    static constraints = 
        username nullable: false, blank: false, minSize: 6
        email email: true, nullable: false, blank: false
    

只有当参数验证命令对象和操作 error 时才会执行操作 index 的控制器以在验证错误的情况下重定向到:

class FooController 
    def index() 
        render 'ok!'
    
    def error() 
        render 'errors = ' + params.errors
    

然后,您可以为所有请求(或您想要的请求)定义一个过滤器,并根据请求尝试执行的控制器和操作,您可以使用所需的参数验证命令对象,如下所示:

class FooFilters 
    def filters = 
        all(controller:'*', action:'*') 
            before = 
                if (params.controller == 'foo' && (!params.action || params.action == 'index')) 
                    FooCommand cmd = new FooCommand(params.subMap(['username','email']))
                    if (!cmd.validate()) 
                        redirect controller: 'foo', action: 'error', params: [errors:cmd.errors]
                        return false
                    
                
                return true
            
        
    

可以通过多种方式改进此代码。但我认为作为示例解决方案就足够了。

【讨论】:

【参考方案2】:

虽然不完全符合您的要求,但我写了一个插件,它做了类似的事情。它使用和 AST 添加处理程序,如果未提供默认处理程序,它还使用默认处理程序增强控制器。然而,处理程序只给出了具有命令的命令对象,作为名称的最后一部分,因为插件也试图给命令对象更多的约定。

http://plugins.grails.org/plugin/virtualdogbert/command

【讨论】:

以上是关于重构 Grails 命令验证的主要内容,如果未能解决你的问题,请参考以下文章

Grails:如何使用命令对象验证由项目列表组成的 POST 正文?

Grails 命令对象自定义验证消息代码

Grails:验证包含分隔的电子邮件地址列表的字符串

Mongodb身份验证不适用于grails,而是来自控制台

Grails Spring 安全插件 AJAX 身份验证

Grails 命令对象可以有可变数量的参数吗?