`
helloqiner
  • 浏览: 24443 次
  • 来自: ...
文章分类
社区版块
存档分类

在Nutz框架中提供Pojo校验(验证)功能的支持

阅读更多

 

作为java程序员,往往对于springstrutsHibernateiBatis 等国外的开源框架都比较熟悉。它们的确经典,的确强大,的确好用。但是随着时间的发展,这些框架越来越庞大!Hibernate的核心包已经超过2M, spring呢,它现在已经被拆分为 18 个子项目,而且还有继续扩大的趋势。为了一个小小的功能,引入那么一大堆lib包,任谁都得考虑一下吧。

……

这个问题一直存在,直到 Nutz 框架的出现。

一个不到 900K 的开源框架,不仅包含了 iocaopdaomvclog,还整合了很多好用的工具类,基本上我们做一个项目需要用到的功能都提供了。

还有要说明的是,它可是国人的开源项目哦,提供全套中文文档,及大量的中文注释。国内的开发人员应该会感到比较亲切吧。

 

更详细的信息,请参看Nutz的官方网站: http://code.google.com/p/nutz/ 

Nutz框架虽然提供了很多功能,却独独拉了校验功能的支持。我们知道,一个程序,尤其是Web程序,如果没有服务器端验证,那么将非常容易受到攻击的。

“自己动手,丰衣足食”。既然官方没有提供,那就自己搞一套吧。还好基于Nutz现有的工具类,实现起来并不太复杂。

 

整个验证框架提供了12种常见的验证形式,且支持自定义正则表达式,基本上可以满足实际的需要。对于有特殊要求的字段验证,允许用户自己定义验证的方法。

校验不仅可以用于Web层,你可以把它用于程序的任何层面(如入库前对pojo 字段值进行验证)。

目前验证框架基于注解,因为对于字段的验证需求一般比较固定,所以同代码一块管理比较方便。当然你也可以扩展它,提供其它形式的验证。如果你有更好的改动,请也一并发我邮箱一份哈。

废话不多说,直接上代码吧。

 

/**
 * 验证支持注解
 * 
 * @author QinerG(QinerG@gmail.com)
 */
@Retention(RetentionPolicy.RUNTIME)
@Target( { ElementType.PARAMETER, ElementType.FIELD })
public @interface Validations {

	/**
	 * 必填字段验证规则
	 */
	public boolean required() default false;

	/**
	 * 手机号验证规则
	 */
	public boolean mobile() default false;

	/**
	 * 帐号验证规则(字母开头,允许字母数字下划线),常与字串长度验证规则混合使用
	 */
	public boolean account() default false;

	/**
	 * Email 验证规则
	 */
	public boolean email() default false;

	/**
	 * QQ 号验证规则
	 */
	public boolean qq() default false;

	/**
	 * 字串必须为中文验证规则
	 */
	public boolean chinese() default false;

	/**
	 * 邮政编码验证规则
	 */
	public boolean post() default false;

	/**
	 * 正则表达式验证规则
	 */
	public String regex() default "";

	/**
	 * 重复性验证规则。请放置待比较的字段名
	 */
	public String repeat() default "";

	/**
	 * 字符串最大、最小长度验证规则
	 */
	public int[] strLen() default {};

	/**
	 * 数值型数据取值范围区间验证规则,兼容 int、long、float、double
	 */
	public double[] limit() default {};

	/**
	 * 自定义效验规则,可以自行指定验证的方法名称 <br/> 该方法必须是public的,且没有参数返回值为boolean型
	 */
	public String custom() default "";

	/**
	 * 错误提示语
	 */
	public String errorMsg();
}

 

这就是注解类的全部代码。该注解是字段(FIELD)级别的,所以你可以把它声明在pojo的属性上。

比如:

 

//账号验证规则,与字符串长度区间验证共同作用
@Validations(account = true, strLen = { 3, 16 }, errorMsg = "account")
private String account;

 

允许多种验证同时声明,errorMsg 是错误提示语,必填。

 

pojo需要验证的时候,可以这样写:

 

AnnotationValidation av = new AnnotationValidation();
Errors ers = av.validate(pojo);
       验证错误的信息都存放在 Errors 对象中了,你可以调用 getErrorsList() 返回错误列表,或者调用 getErrorsMap() 字段与错误提示语的对应关系。

这时也许你会说,这种调用方法很麻烦。每次验证的时候,都需要创建 AnnotationValidation 的实例,有没有更简单的方法呢?

没错,Nutz提供了 AOP 的支持,这样我们就可以很方便的用它来进行拦截验证了。

下面是拦截器的全部代码:

/**
 * 基于注解的验证用拦截器
 * <p>
 * 该拦截器主要用于方法参数的验证,要求该方法中必须有一个 Errors 类型的参数(允许为空),当验证完成后会向这个参数赋值
 * 
 * @author QinerG(QinerG@gmail.com)
 */
@IocBean(name = "validationInterceptor")
public class ValidationInterceptor extends AbstractMethodInterceptor {

	private static AnnotationValidation av = new AnnotationValidation();

	/**
	 * 方法调用前进行拦截,遍历参数进行验证
	 */
	public boolean beforeInvoke(Object obj, Method method, Object... args) {
		Errors es = ValidationUtils.checkArgs(method.getParameterTypes(), args);
		if (null != es) {
			for (Object argsObj : args) {
				if (argsObj instanceof Errors)
					continue;
				av.validate(argsObj, es);
			}
		}
		return true;
	}
}
 

注意:该拦截器主要用于方法参数的验证,要求该方法中必须有一个 Errors 类型的参数(允许为空),当验证完成后会向这个参数赋值。

有了这个拦截器,就方便多了。只需要在需要提供验证功能的方法前使用 @Aop("validationInterceptor") 声明,例如:

@Aop("validationInterceptor")
	public Errors test(Bean bean, Errors es) {
		System.out.println(es.errorCount());
		return es;
	}

之后在调用这个方法的时候,拦截器就会自动执行,并将验证结果注入到参数 Errors 中。下面是 junit测试用例:

@Test
	public void testAop() {		
		Ioc ioc = new NutIoc(new AnnotationIocLoader("org.nutz.validation"));
		
		ServiceDemo sd = ioc.get(ServiceDemo.class);
		Bean b = new Bean();
		Errors ers = sd.test(b, null);
		assertEquals(10, ers.errorCount());
	}
 

这样是不就方便了很多?

应用程序可以用 aop 的方式验证,那么 web 程序呢,也可以这样用吗?那是当然了。在 action 前声明拦截器:

@At("/test")
	@Ok("json")
	@Aop("validationInterceptor")
	public int test(@Param("bean")Bean bean, Errors es) {
		System.out.println(Dumps.obj(bean));
		if (es != null) {
			return es.errorCount();
		}
		return -99;
	}
 

action 里即可以取到 Errors 对象,并可以对其进行显示等相关处理啦。

 

附件为全部源代码,及测试用例。欢迎大家拍砖!

 

分享到:
评论
8 楼 conanca 2011-04-20  
用拦截器实现的,不错不错,很有启发,呵呵。
7 楼 无根V稻草 2011-04-20  
不错不错 研究下下
6 楼 helloqiner 2011-04-20  
有一个工具类 ValidationUtils ,里面全是静态方法,可以帮助手工完成验证
例如:
static boolean ValidationUtils.required(String fieldName, Object target, String errorMsg, Errors errors);
5 楼 hastune 2011-04-20  
feiyan35488 写道
非常不错,不过有没有把这些验证方法 做成public static??这样可以在程序任何地方进行使用了


指的是什么方法???
4 楼 feiyan35488 2011-04-20  
非常不错,不过有没有把这些验证方法 做成public static??这样可以在程序任何地方进行使用了
3 楼 hastune 2011-04-19  
2 楼 zozoh 2011-04-19  
但是只能拦截入口函数,如果要拦截业务对象,只能用 AOP 了,呵呵
1 楼 zozoh 2011-04-19  
还有一种解法就是提供 ActionFilter
或者提供一个新的 Prcessor

相关推荐

Global site tag (gtag.js) - Google Analytics