Grails hack之扩展validate方法

本文介绍了一种在Grails框架中扩展验证方法的方法,通过修改ValidatePersistentMethod.java,实现了使用黑名单进行属性验证的功能。该方法允许开发者指定不需要验证的属性列表。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Grails的ValidatePersistentMethod.java中主体代码:

 

if(arguments.length > 0) {
    if(arguments[0] instanceof Boolean) {
        evict = ((Boolean)arguments[0]).booleanValue();
    }
    if(arguments[0] instanceof Map) {
        Map argsMap = (Map)arguments[0];

        if(argsMap.containsKey(ARGUMENT_DEEP_VALIDATE))
            deepValidate = GrailsClassUtils.getBooleanFromMap(ARGUMENT_DEEP_VALIDATE, argsMap);

        evict = GrailsClassUtils.getBooleanFromMap(ARGUMENT_EVICT, argsMap);
    }
    if (arguments[0] instanceof List) {
        validatedFields = new HashSet((List) arguments[0]);
    }
}

 

可见它只用到了第一个参数,调用validate方法的代码主要有三种形式:

1.

myDomain.validate(true)

2.

myDomain.validate(deepValidate:true, evict:true)

3.

myDomain.validate(['prop1', 'prop2'])

 

看出来了,there's a piece of the puzzle missing: 形式3的入口参数是个whitelist,如果我需要对myDomain的prop1和prop2之外的其它属性做校验,我希望通过传递一个blacklist给它来达到目的。该怎么办呢?

当然你可以先读取myDomain的所有属性列表,通过做“减法”(减去['prop1', 'prop2'])计算出上述第三种调用形式的参数,然后以第三种形式调用之。

但是这样就会多出几行代码,看起来让人感觉不爽。

 

我们不如hack一下ValidatePersistentMethod.java:

// modified by S.C. on 03JUn2010 ==>
//            if(arguments.length > 0) {
//                if(arguments[0] instanceof Boolean) {
//                    evict = ((Boolean)arguments[0]).booleanValue();
//                }
//                if(arguments[0] instanceof Map) {
//                    Map argsMap = (Map)arguments[0];
//
//                    if(argsMap.containsKey(ARGUMENT_DEEP_VALIDATE))
//                        deepValidate = GrailsClassUtils.getBooleanFromMap(ARGUMENT_DEEP_VALIDATE, argsMap);
//
//                    evict = GrailsClassUtils.getBooleanFromMap(ARGUMENT_EVICT, argsMap);
//                }
//                if (arguments[0] instanceof List) {
//                    validatedFields = new HashSet((List) arguments[0]);
//                }
//            }
            if(arguments.length == 2 && ("exclude".equals(arguments[1].toString())||"-".equals(arguments[1].toString())) && arguments[0] instanceof List) {
                GrailsDomainClassProperty[] properties = domainClass.getProperties();
                HashSet set = new HashSet();
                for(GrailsDomainClassProperty p : properties) {
                    set.add(p.getName());
                }
                set.removeAll((List)arguments[0]);
                validatedFields = set;
            } else if(arguments.length > 0) {
                if(arguments[0] instanceof Boolean) {
                    evict = ((Boolean)arguments[0]).booleanValue();
                }
                if(arguments[0] instanceof Map) {
                    Map argsMap = (Map)arguments[0];

                    if(argsMap.containsKey(ARGUMENT_DEEP_VALIDATE))
                        deepValidate = GrailsClassUtils.getBooleanFromMap(ARGUMENT_DEEP_VALIDATE, argsMap);

                    evict = GrailsClassUtils.getBooleanFromMap(ARGUMENT_EVICT, argsMap);
                }
                if (arguments[0] instanceof List) {
                    validatedFields = new HashSet((List) arguments[0]);
                }
            }
// modified by S.C. on 03JUn2010 <==

 同时还有它的method signature也需要hack一下:

metaClass.validate = {Map args ->
              validateMethod.invoke(delegate, "validate", [args] as Object[])
          }
          metaClass.validate = {Boolean b ->
              validateMethod.invoke(delegate, "validate", [b] as Object[])
          }
          metaClass.validate = {List args ->
              validateMethod.invoke(delegate, "validate", [args] as Object[])
          }
          //+by S.C. on 03Jun2010
          metaClass.validate = {List args, String exclude ->
              validateMethod.invoke(delegate, "validate", [args, exclude] as Object[])
          }

 

简单的测试一下:

class ValidationIntegrationTests extends GrailsUnitTestCase {
    protected void setUp() {
        super.setUp()
    }

    protected void tearDown() {
        super.tearDown()
    }

    void testValidationBlackList() {
        def user = new User()
        assertFalse user.validate(['username'])
        assertTrue  user.validate(['username'],'-')
    }
}

测试结果:

-------------------------------------------------------
Running 1 integration test...
Running test sctms.ValidationIntegrationTests...PASSED
Tests Completed in 406ms ...
-------------------------------------------------------
Tests passed: 1
Tests failed: 0
-------------------------------------------------------
[db4o 7.12.132.14217   2010-06-03 14:33:10]
 'D:\workspace\sctms\web-app\WEB-INF\db\testDb.yap' close request
[db4o 7.12.132.14217   2010-06-03 14:33:10]
 'D:\workspace\sctms\web-app\WEB-INF\db\testDb.yap' closed
[junitreport] Processing D:\workspace\sctms\target\test-reports\TESTS-TestSuites.xml to C:\WINDOWS\TEMP\null1893017616
[junitreport] Loading stylesheet jar:file:/C:/Documents%20and%20Settings/sam/.ivy2/cache/org.apache.ant/ant-junit/jars/ant-junit-1.7.1.jar!/org/apache/tools/ant/taskdefs/optional/junit/xsl/junit-frames.xsl
[junitreport] Transform time: 657ms
[junitreport] Deleting: C:\WINDOWS\TEMP\null1893017616

Tests PASSED - view reports in target\test-reports
 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值