jfnal特性之Validator后端验证源码探究
所谓Vadidator是什么
public abstract class Validator implements Interceptor
Validator是个抽象类,定义了必备的验证方法,具体的validator只需继承该类即可拥有极简的验证方式,从上面的代码也可以看出,所谓Validator实质上就是一个拦截器
Validator如何使用
官方文档很清晰,不赘言
具体代码分析
以demo中的BlogValidator为切入口,分析validate方法中的validateRequiredString方法的具体行为
protected void validateRequiredString(String field, String errorKey, String errorMessage) {
// 根据方法调用时传递进来的表单域名称,获取对应的值,至于controller是如何可以被获取到的,涉及到Validator作为拦截器的intercept方法
String value = controller.getPara(field);
// 简单的判空操作
if (value == null || "".equals(value.trim()))
// 添加验证失败标志,为request添加error信息
addError(errorKey, errorMessage);
}
validator内部定义了许多验证方法,但是实现思路上与上面并无二致。
Validator的intercept方法
有关于拦截器的intercept方法何时被调用,在运行时初探时已经分析过,下面只关注Validator的intercept方法具体做了些什么
final public void intercept(ActionInvocation invocation) {
Validator validator = null;
try {
// 又见反射,jfinal中无处不有反射的使用,actionmapping时contorller的获取也是如此
// 获取当前validator拦截器的实例
validator = getClass().newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
// 初始化validator
validator.controller = invocation.getController();
validator.invocation = invocation;
try {
// 调用 开发者继承重写的validate方法,即上一步分析的内容
validator.validate(validator.controller);
} catch (ValidateException e) {/* should not be throw */
} // short circuit validate need this
if (validator.invalid)
// 验证不通过,测调用开发者继承重写的handleError方法
// handleError如何处理,延后分析
validator.handleError(validator.controller);
else
// 通过,继续递归调用的下一步
invocation.invoke();
}
intercept方法肯定会被调用,而它的逻辑又必须如此写,所以作者将其以final修饰,不希望被开发者修改
#handleError分析
protected void handleError(Controller controller) {
// 本质上就是在request中设置之前从客户端传递过来的model属性,如 blog.title、blog.content等
controller.keepModel(Blog.class);
// 根据请求的地址不同,返回不同的响应
String actionKey = getActionKey();
if (actionKey.equals("/blog/save"))
controller.render("add.jsp");
else if (actionKey.equals("/blog/update"))
controller.render("edit.jsp");
}
小结
validate使用起来很简单也很有效,不过占用了一个action级别的拦截器,而action级别的拦截器用@before注解只能注册一个,如果有多个拦截器需要配置到action级别上,该如何做?使用拦截器栈即可