框架设计之验证那事儿

    前篇文章主要谈了持久化是不是需要的问题,其实一开始我的想法还是觉得是需要持久层的,就像有人说的持久化可以使在编译时知道你的类型和赋值正与否,而使用那些容器确不能,此时也体现出强类型的好处。如果用类似Hashtable这些的容器会使编译通过,结果可能会在程序运行的时候出错。使用此等容器有好有坏,就如鱼和熊掌不能兼得一般,很难权衡(此等问题,还得再向园子大牛级人物讨教一下)。因为之前我也说过了,用实体层的话,可能会运用大量的反射过程,代价太高。在框架没设计验证时,我一开始就采用的是ORM那种思想,到框架加入验证想法,我的想法随之也改变了!上篇文章先说到这里,先谈谈我的框架中对验证层的相关设计吧!这里我只说明设计的思路,暂无源码提供!
    
    我们的Web程序在验证上,可能会存在两端(服务端和客户端)都得有处理同一个验证的过程。(我这里之所以说两端都得同时处理的话,是因为我相信那句话:“永远不要信赖客户提交的数据”,所以我在服务端还是得重复这个验证过程),那么这里的两端的验证是否存在冗余呢?答案是显而易见的,如果按照老老实实的写代码的话,两端肯定得写各自的代码(js和cs代码)。
    好了,我写好了所有Boss规定的所有代码!"啊?什么?",突然Boss告诉我,"小S,这个验证可能不是这样的,可能是文档里我没怎么写清晰,具体的还是得这样做。。。","天呐!老大,您不早说!",我心里想着。不过也没事,我就改一下js吗!哦,No,还有在cs端也有个小手术。
    虽然讲这里改动不是很多,但是产生了连锁改动,有些程序员会放弃(去掉)在服务器端验证代码,嘿,反正你也看不出来,管它呢!我只要快速达到你的要求好了!谁教你当初不想清楚就把文档给我呢!活该!!!去掉服务端的验证,可能影响是不大,但对于遇到恶意性的代码是,那你的好日子也就到头喽!
    社会的进步都是在前人的经验累积下来的,设计模式如此,写程序代码的经验未尝不是如此。我们从一次次的摔倒中,知道了如何不去重复同样的错误!这个小小验证又能难倒我们吗?OK,呵呵,说远了!切入正题了,说说我对此类问题的解决方案吧!(感觉和java中struts的Validate有点类似)。。。
    我对这验证是这样做的,整体是放在一个xml中(xml只是一个载体之一,也可以是数据库),而且我把一些常用的验证全都封装好了!先看一下这个验证配置文件的例子:
    
    
<field name="txtCargoNo" display-name="货物编号" maxlength="11" type="text">
        <depend 
name="required" />
        <depend 
name="isNumeric" />
        <depend 
name="maxLength" param="11" />
        <depend 
name="minLength" param="11" />
        <dpend 
name="server" reflect-validate="ExportCargo.CargoNumberIsExsit" params-validate="txtCargoNo,EG_ID"/>
    </field>
    
    
required表示的字段是必填项,当required符合后,就去检测isNumeric填写的是否正确,然后再下一步。值得一提的是,这里存在一个name="server",它表示是一个服务器端即使验证,也就是我们就得使用的ajax异步验证。reflect-validate:是表示响应的服务层所对应的类和方法名,params-validate:表示验证响应的需要的参数。我在里是需要txtCargoNo,EG_ID两个参数,txtCargoNo表示自身参数,EG_ID表示该操作的实体的ID,(因为在编辑时,这步验证必须把自己本身的ID除外)。
    JS端的验证过程:载体验证xml载入完毕后缓存,并根据配置文件内容,自动生成js代码且也缓存起来(因为每次提交页验证总是不会改变的)
    CS端的表单提交验证过程:当表单Post进来的时候,我会先交给Validate先去除表单的一些特殊符号(如防sql注入的符号,如果是一般文本框得话还得过滤html),清理后生成一个IDictionary
<string,string>,再与文档核对,验证里边的元素是否不在文档规定的提交范围内。再次清理后,就交给Validate的Factory,Facotry会反射根据depand的name(如required)动态调用需要对应到哪个CS验证方法,调用之后,如果不符合条件,那么,说明该值是不符合文档规定的范围。如果符合,只要我的Facotry队列还是不为空,我还是再得继续Validate,如此循环,每遇到不符合条件的我就退出。或者只到我发现所有条件都通过我就退出了。(注,这里的反射如果还得提高性能得话,还得去缓存)
    CS端的Ajax验证:通常我把这个传送也是通过post方式传递,发送txtCargoNo,EG_ID所填入的信息,后面几步步骤同CS端的表单提交验证过程相似。
    注:这里所说的factory方式,js端差不多也是这么做的。
    
    文章写的仓促,无奈手头上还有不少活要干!写先到这里,整体就是这样构架,不知道园子里各位的有何高见?请与大家一起讨论一下。
       附上测试例子:http://export.job-mate.com/BookingNote.jobmate?action=Insert

    
    未完,待续。。。
posted @ 2008-07-22 10:02  netcorner  阅读(2145)  评论(18编辑  收藏  举报