自定义Grails验证

自定义Grails验证,grails,groovy,grails-validation,Grails,Groovy,Grails Validation,通常,对于Grails域或命令类,您需要声明约束,框架会添加一个validate()方法来检查这些约束是否对当前实例有效,例如 class Adult { String name Integer age void preValidate() { // Implementation omitted } static constraints = { name(blank: false) age(min: 18) } } def p = new

通常,对于Grails域或命令类,您需要声明约束,框架会添加一个
validate()
方法来检查这些约束是否对当前实例有效,例如

class Adult {

  String name
  Integer age

  void preValidate() { 
    // Implementation omitted
  }

  static constraints = {
    name(blank: false)
    age(min: 18)
  }
}

def p = new Person(name: 'bob', age: 21)
p.validate()
在我的例子中,我希望确保在验证类之前总是执行
preValidate
。我可以通过添加一个方法来实现这一点

def customValidate() {
  preValidate()
  validate()
}
但是使用这个类的每个人都需要记住调用
customValidate
,而不是
validate
。我也不能这么做

def validate() {
  preValidate()
  super.validate()
}

因为
validate
不是父类的方法(它是通过元编程添加的)。还有其他方法可以实现我的目标吗?

当您的域/命令类具有preValidate()方法时,您应该能够通过在元类上使用自己版本的validate来实现这一点。在
BootStrap.groovy
中,类似于以下代码的东西可能适合您:

class BootStrap {

    def grailsApplication   // Set via dependency injection

    def init = { servletContext ->

        for (artefactClass in grailsApplication.allArtefacts) {
            def origValidate = artefactClass.metaClass.getMetaMethod('validate', [] as Class[])
            if (!origValidate) {
                continue
            }

            def preValidateMethod = artefactClass.metaClass.getMetaMethod('preValidate', [] as Class[])
            if (!preValidateMethod) {
                continue
            }

            artefactClass.metaClass.validate = {
                preValidateMethod.invoke(delegate)
                origValidate.invoke(delegate)
            }
        }
    }

    def destroy = {
    }
}

您可以使用beforeValidate()事件完成目标。这一点在本手册中有描述