• 10.2 Validator
    • 1、基本用法
    • 2、setRet(…) 与 getRet()
    • 3、高级用法

    10.2 Validator

    1、基本用法

    Validator自身实现了Interceptor接口,所以它也是一个拦截器,配置方式与拦截器完全一样。以下是Validator示例:

    1. public class LoginValidator extends Validator {
    2. protected void validate(Controller c) {
    3. validateRequiredString("name", "nameMsg", "请输入用户名");
    4. validateRequiredString("pass", "passMsg", "请输入密码");
    5. }
    6. protected void handleError(Controller c) {
    7. c.keepPara("name");
    8. c.render("login.html");
    9. }
    10. }

    protected void validator(Controller c)方法中可以调用validateXxx(…)系列方法进行后端校验,protected void handleError(Controller c)方法中可以调用c.keepPara(…)方法将提交的值再传回页面以便保持原先输入的值,还可以调用c.render(…)方法来返回相应的页面。注意handleError(Controller c)只有在校验失败时才会调用。

    以上代码handleError方法中的keepXxx方法用于将页面表单中的数据保持住并传递回页,以便于用户无需再重复输入已经通过验证的表单域。

    如果传递过来的是 model 对象,可以使用keepModel(…) 方法来保持住用户输入过的数据。同理,如果传递过来的是传统 java bean 对象,可以使用 keepBean(…) 方法来保持住用户输入过的数据。

    keepPara(…) 方法默认将所有数据keep成String类型传给客户端,如果希望keep成为特定的类型,使用keepPara(Class, …) 即可,例如:keepPara(Integer.class, “age”)。

    注意:如果keepPara() 造成模板中出现类型相关异常,解决方法参见Template Engine这章的Extension Method小节。

    2、setRet(…) 与 getRet()

    jfinal 4.0 版本新增了 setRet(Ret) 方法与 getRet() 方法,典型示例如下:

    1. public class LoginValidator extends Validator {
    2.  
    3. protected void validate(Controller c) {
    4. setRet(Ret.fail());
    5.  
    6. validateRequired("userName", "msg", "邮箱不能为空");
    7. validateEmail("userName", "msg", "邮箱格式不正确");
    8. validateRequired("password", "msg", "密码不能为空");
    9. validateCaptcha("captcha", "msg", "验证码不正确");
    10. }
    11.  
    12. protected void handleError(Controller c) {
    13. c.renderJson(getRet());
    14. }
    15. }

    如上例所示,setRet(Ret.fail()) 将向 LoginValidator 注入一个 Ret 对象,从而后续的 validateRequired 等等 validate 方法会将所有验证结果存放在该 Ret 对象之中。

    然后,在 handleError 中的 c.renderJson( getRet() ) 这行代码就可以通过 getRet() 拿到前面注入的 Ret 对象,然后再进行 renderJson(ret)

    这样使用的好处是与 controller 层的 renderJson(Ret) 用法统一起来,因为你的 controller 中可能是这样用的:

    1. public void login() {
    2. Ret ret = loginService.login(...);
    3. renderJson(ret);
    4. }

    上面代码中的 loginService.login(…) 返回的 ret 对象与 LoginValidator 中的 ret 对象统一使用 renderJson(ret) 以后,前端的 JavaScript 对其的处理方式就可以完全统一。

    3、高级用法

    虽然 Validator 中提供了丰富的 validateXxx(…) 系列方法,但毕竟方法个数是有限的,当 validateXxx(…) 系列的方法不能满足需求时,除了可以用 validateRegex(…) 定制正则表达式来满足需求以外,还可以通过普通 java 代码来实现,例如:

    1. protected void validate(Controller c) {
    2. String nickName = c.getPara("nickName");
    3. if (userService.isExists(nickName)) {
    4. addError("msg", "昵称已被注册,请使用别的昵称!");
    5. }
    6. }

    如上代码所示,只需要利用普通的 java 代码配合一个 addError(…) 方法就可以无限制、灵活定制验证功能。

    这里特别强调:addError(…) 方法是自由定制验证的关键。

    此外,Validator 在碰到验证失败项时,默认会一直往下验证所有剩下的验证项,如果希望程序在碰到验证失败项时略过后续验证项立即返回,可以通过如下代码来实现:

    1. protected void validate(Controller c) {
    2. this.setShortCircuit(true);
    3. ....
    4. }

    setShortCircuit(boolean) 用于设置验证方式是否为 “短路型验证”。