使用Validator做SpringMVC的验证框架 - 自定义验证组件

章节列表

  1. 第一章:使用Validator做SpringMVC的验证框架 - 配置SpringMVC环境
  2. 第二章:使用Validator做SpringMVC的验证框架 - 使用Validator
  3. 第三章:使用Validator做SpringMVC的验证框架 - Validator前端验证
  4. 第四章:使用Validator做SpringMVC的验证框架 - 自定义验证组件

前面的几章已经为大家简单的介绍了Validator的功能已经使用方法,下面接着为大家介绍怎么使用Validator自定义验证组件

Validator框架源码地址:https://github.com/devefx/validator

1 - 创建后台验证组件

大家可能发现了,我们前面的注册功能少了一个很重要的参数,那就是验证码。众所周知验证是为了防止机器人恶意注册的,这一步的验证是需要与服务器进行数据交互的验证,不是简单数据格式判断就能知道正误的。下面我让大家看看Validator框架强大的扩展性

首先修改一下register.jsp,在“个人主页”下面添加一个”验证码“

                <tr>
                    <td>个人主页:</td>
                    <td><input name="homepage"></td>
                </tr>
                <!-- 验证码输入框 -->
                <tr>
                    <td>验证码:</td>
                    <td><input name="code" placeholder="请输入1234"></td>
                </tr>

接着我们创建一个“com.devefx.website.validator.constraints”包用来放我们自定义的后台验证组件,同时创建一个java源码文件“CodeValidator”作为验证码验证组件。

CodeValidator.java

package com.devefx.website.validator.constraints;

import java.io.IOException;
import java.io.Writer;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import com.devefx.validation.annotation.BindScript;
import com.devefx.validation.constraints.FieldValidator;
import com.devefx.validation.kit.StrKit;
import com.devefx.validation.script.JavaScript;

/**
 * 自定义验证码验证器.
 */
public class CodeValidator extends FieldValidator {

    private final String sessionKey;

    public CodeValidator(String field, String sessionKey, String errorCode, String errorMessage) {
        super(field, errorCode, errorMessage);
        this.sessionKey = sessionKey;
    }

    @Override
    public boolean isValid(HttpServletRequest request) throws Exception {
        String value = request.getParameter(field);
        // 如果是空,就交个NotEmptyValidator组件
        if (!StrKit.isEmpty(value)) {
            HttpSession session = request.getSession();
            // 为了讲解方便(实际项目中可不能这么干),我直接把‘1234’当做正确的验证码
            return value.equals(/*session.getAttribute(sessionKey)*/"1234");
        }
        return true;
    }
}

好了,这样一个后台验证组件就开发完成了,接着我们就在RegisterValidator.java中使用吧

RegisterValidator.java


package com.devefx.website.validator;

import com.devefx.validation.Validator;
import com.devefx.validation.constraints.impl.EmailValidator;
import com.devefx.validation.constraints.impl.EqualFieldValidator;
import com.devefx.validation.constraints.impl.LengthValidator;
import com.devefx.validation.constraints.impl.MobileValidator;
import com.devefx.validation.constraints.impl.NotBlankValidator;
import com.devefx.validation.constraints.impl.URLValidator;
import com.devefx.website.validator.constraints.CodeValidator;

public class RegisterValidator extends Validator {
    @Override
    public void setup() {
        // 用户名验证
        add(new NotBlankValidator("username", "username", "用户名不能为空"));
        add(new LengthValidator("username", 6, 20, "username", "用户名长度限制6至20位"));
        // 密码验证
        add(new NotBlankValidator("password", "password", "密码不能为空"));
        add(new LengthValidator("password", 6, 20, "password", "密码长度限制6至20位"));
        add(new EqualFieldValidator("password_safe", "password", "password_safe", "两次密码不一致"));
        // 手机号验证
        add(new NotBlankValidator("phoneno", "phoneno", "手机号不能为空"));
        add(new MobileValidator("phoneno", "phoneno", "请输入正确的手机号"));
        // 邮箱验证
        add(new NotBlankValidator("email", "email", "邮箱不能为空"));
        add(new EmailValidator("email", "email", "请输入正确的邮箱"));
        // 个人主页验证
        add(new URLValidator("homepage", "homepage", "请输入正确的主页地址"));
        // 验证码验证
        add(new NotBlankValidator("code", "code", "验证码不能为空"));
        add(new CodeValidator("code", "registerCode", "code", "请输入正确的验证码"));
    }
}

我们启动项目试验一下吧,首先我们输入一个错误的验证码

演示1

我们可以发现Validator这时候并没有帮我们立即验证验证码是否正确

演示2

上面的图可以看出:只有在其他参数正确的情况下,并进行提交的时候才开始检查出验证码有误,这是因为我们只为他编写了后台验证码,而没有前台验证器的时候实际上分成了两批验证。

2 - 编写前端验证组件代码

前端验证器组件也遵循统一规范,首先我们创建一个“com.devefx.website.validator.constraints.js”包,再新建一个CodeValidator.js文件

CodeValidator.js

function CodeValidator(field, sessionKey, errorCode, errorMessage) {
    FieldValidator.apply(this, [field, errorCode, errorMessage]);
    this.isValid = function (request, control) {
        var value = request.getParameter(field);
        if (!isEmpty(value)) {
            // 使用异步
            control.async();
            // ajax异步请求
            $.ajax({
                url: "/module/code", // 验证接口访问地址
                type: "post", // 请求方式
                data: {"sessionKey": sessionKey, "code": value},
                success: function (result) {
                    // 根据接口返回结果再同步到验证器
                    if (result == "success") {
                        return control.sync(true);
                    }
                    control.sync(false);
                }
            });
        }
        return true;
    };
}

第一行声明了一个函数,此函数名称必须与需要绑定的Java验证组件名称相同,参数含义与Java验证组件的构造函数相同
第二行代码是js中继承的实现,我们同样继承FieldValidator
第三行实现了验证方法。

isValid(request[, control]) 方法

参数 说明
request 用来获取请求的参数值
control 可选,当此验证需要异步执行的时候,用来获取控制权

参数

request
  类型:Request
  Request提供getParameter(name)方法,可以通过input的name获取input的value

control
  类型:Object
  提供async、sync(valid)两个方法,async获取到控制权;sync(valid)交还控制权同时告知验证结果

我们可以看到上面定义是前端验证器需要/module/code接口的支持。
我们在“com.devefx.website”包里面创建一个Java源码

ValidatorController.java

package com.devefx.website.controller;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.devefx.validation.ConstraintValidator;
import com.devefx.website.validator.constraints.CodeValidator;

@Controller
@RequestMapping("/module")
public class ValidatorController {
    /**
     * 检测验证码是否输入正确
     * 
     * @param sessionKey 会话中验证码对应的key
     * @return String
     */
    @ResponseBody
    @RequestMapping(value="/code", method=RequestMethod.POST)
    public String codeValidate(HttpServletRequest request,
            @RequestParam("sessionKey") String sessionKey) {
        try {
            ConstraintValidator validator = new CodeValidator("code", sessionKey, null, null);
            // 如果验证通过
            if (validator.isValid(request)) {
                return "success";
            }
        } catch (Exception e) {
            // ignore
        }
        return "fail";
    }
}

注意:上面的sessionKey,我们是为了方便登录、注册共用才保留的,你们可以根据实际情况决定是否使用

3 - 为后台验证组件实现并、绑定前端验证组件

我们修改一下CodeValidator.java文件,给他实现Script接口,并绑定前端组件

CodeValidator.java

package com.devefx.website.validator.constraints;

import java.io.IOException;
import java.io.Writer;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import com.devefx.validation.Script;
import com.devefx.validation.annotation.BindScript;
import com.devefx.validation.constraints.FieldValidator;
import com.devefx.validation.kit.StrKit;
import com.devefx.validation.script.JavaScript;

/**
 * 自定义验证码验证器.
 */
@BindScript("com/devefx/website/validator/constraints/js/CodeValidator.js")
public class CodeValidator extends FieldValidator implements Script {

    private final Script script;
    private final String sessionKey;

    public CodeValidator(String field, String sessionKey, String errorCode, String errorMessage) {
        super(field, errorCode, errorMessage);
        this.sessionKey = sessionKey;
        script = JavaScript.create(this, field, sessionKey, errorCode, errorMessage);
    }

    @Override
    public boolean isValid(HttpServletRequest request) throws Exception {
        String value = request.getParameter(field);
        // 如果是空,就交个NotEmptyValidator组件
        if (!StrKit.isEmpty(value)) {
            HttpSession session = request.getSession();
            // 为了讲解方便(实际项目中可不能这么干),我直接把‘1234’当做正确的验证码
            return value.equals(/*session.getAttribute(sessionKey)*/"1234");
        }
        return true;
    }

    public void output(Writer out) throws IOException {
        script.output(out);
    }
}

通过@BindScript注解将前端验证组件绑定给后台验证组件,同时实现Script接口用来输出前端调用代码

4 - 注册自定义组件

做完上面的步骤,我们已经到最后一步了,打开Config.java文件

Config.java

package com.devefx.website.validator.config;

import com.devefx.validation.web.config.Modules;
import com.devefx.validation.web.config.Routes;
import com.devefx.validation.web.config.ValidatorConfig;
import com.devefx.website.validator.RegisterValidator;
import com.devefx.website.validator.constraints.CodeValidator;

public class Config implements ValidatorConfig {

    public void configModules(Modules modules) {
        // 这里可以添加自定义验证组件

        // 注册自定义组件
        modules.add(CodeValidator.class);
    }

    public void configRoute(Routes routes) {
        // 这里配置验证器的访问路线

        // 设置基准路径
        routes.setBasePath("/validator");

        // 注册验证器
        routes.add("/registerValidator.js", RegisterValidator.class);

    }

}

大功告成,重启一下项目来看看效果吧。

演示3

可以看到我们自定义的验证组件已经能立即进行验证了。

5 - 后语

上面我只为大家介绍了一种自定义验证组件,大家应该还能想到更多用法。
比如:用户名是否重名验证、必须登陆验证、访问权限验证等等。

基本上Validator全部的功能我已经接受完毕,由于是第一次写博客教程,或许很多地方介绍的不够详细,如果大家有什么不明白之处可以通过下面的评论功能或者加入【Java技术交流群】

猜你喜欢

转载自blog.csdn.net/devefx/article/details/51595671