JFinal的架构中没有专门的Validator,它的validator就是Interceptor。完全可以把它当成一个普通的Interceptor使用。
例如在save方法上添加@Before({ Tx.class, SkuValidator.class }),表示它将执行Tx、SkuValidator中的public void intercept(Invocation inv) 方法,该方法是Interceptor的接口方法。Validator是抽象类,实现了Interceptor,定义了protected abstract void validate(Controller c);和protected abstract void handleError(Controller c);这两个方法就是我们继承Validator之后需要实现的方法。
Validator的intercept方法的实现如下,这是一个典型的模板方法模式的应用。
final public void intercept(Invocation invocation) {
Validator validator = null;
try {validator = getClass().newInstance();}
catch (Exception e) {throw new RuntimeException(e);}
validator.controller = invocation.getController();
validator.invocation = invocation;
try {validator.validate(validator.controller);}
catch (ValidateException e) {/* should not be throw */}// short circuit validate need this
if (validator.invalid)
validator.handleError(validator.controller);
else
invocation.invoke();
}
Validator类是抽象类,不可能有自己的实例,validator = getClass().newInstance();这句话就可以实例化子类的一个实例,然后给validator的私有属性赋值,再调用其validate方法,这里利用了多态,在自己的validate方法中实现你的验证逻辑,这个方法的参数传入Controller,你就可以调用一切Controller的方法,比如获取参数等。如果验证有错,调用addError,该方法中首先设置invalid为true,然后将错误信息设置到controller中。最后如果设置了shortCircuit,将直接抛出异常,validator.validate方法如果检测到这个异常,然后什么也不做,以后的也就不验证了,所以短路验证只需要设置该shortcircuit为真即可。【通过异常巧妙地实现短路验证】。
protected void addError(String errorKey, String errorMessage) {
invalid = true;
controller.setAttr(errorKey, errorMessage);
if (shortCircuit) {
throw new ValidateException();
}
}
验证逻辑调用完事儿之后,判断invalid成员,如果为真,表示有错误,直接调用handleError,否则通过。handleError方法也需要你自己实现,可以跳转到某些页面或者返回原来的页面,当然在之前可以准备一个回显的数据,可以调用参数传进来的controller的一切方法。另外validator自己提供了一些校验的方法,例如validateRequired,validateRegex等。
// 校验表单是否重复提交,在保存的时候应用即可,其他代码完全不用修改
// 1.进入input页面之前调用controller.createToken
// 2.在input页面中加入隐藏域<input type="hidden" name="jfinal_token" value="${jfinal_token!''}">
// 3.在保存的方法中应用这个拦截器
public class FormTokenValidator implements Interceptor{
/**
* @param inv
* @see com.jfinal.aop.Interceptor#intercept(com.jfinal.aop.Invocation)
*/
@Override
public void intercept(Invocation inv){
Controller controller = inv.getController();
if(!controller.validateToken()){
//其他事情
controller.render("/common/error_page.html");
} else{
inv.invoke();
}
}
}