spring mvc前端验证代码生成器

spring mvc只提供了服务端验证功能,客户端验证需要自己编写,这是一项重复枯燥的工作,所以考虑基于验证注解自动生成客户端验证代码

一、自定义EL函数

 

/**
 * 自定义EL函数调用
 * 
 * @author ouyang
 *
 */
public class OkweiEL {

	public static final String REDIS_PACKAGE = "wei.wap.form";

	private static final String HTML = "<script type='text/javascript'> \r\n"
			+ "	$().ready(function() { \r\n"
			+ " if(!$.isFunction($.fn.validate)) { alert('未加载validation'); return; }\r\n"
			+ "		$('%s').validate({  \r\n" + "			rules : { %s \r\n"
			+ "			},\r\n" + "			messages : { %s \r\n" + "	  	},  \r\n" + " %s "
			+ "		})  \r\n;" + "	});" + "//from %s</script>";

	/**
	 * 默认的错误显示位置处理
	 */
	private static final String ErrorPlacementHandlerDefault = "    errorPlacement: function(error, element) {    $('<br/>').appendTo(element.parent());  error.appendTo(element.parent()); } ";

	/**
	 * 自定义的错误显示位置处理
	 */
	private static final String ErrorPlacementHandlerCustom = "  errorPlacement: function(error, element) {  %s(error,element); } ";

	private static final String ERROR_CLASS = "";

	 

	private static final String ERROR_HTML = "<script type='text/javascript'>alert('%s');</script>";

	public static String validate(String className, String pathList,
			String formSelector, String redisVersion) {
		return validate(className, pathList, formSelector, redisVersion, null);
	}

	/**
	 * 前端验证生成器,作为自定义EL函数调用 依赖 1.引入jquery validation.js 2.定义form bean
	 * 带验证注解,可包含自定义验证注解 放在jsp页面引入所有js的代码后面 规则参考 已做缓存,更新策略:className对应的class被修改
	 * http://www.runoob.com/jquery/jquery-plugin-validate.html
	 * 
	 * @param className
	 *            类名,可定义一个页面全局变量存储再传入本函数,以免重复写多次该类名
	 * @param pathList
	 *            属性列表,意义同 spring mvc form tag里面的path,多个用,分隔,为空默认处理所有属性
	 * @param formSelector
	 *            form 选择器
	 * @param redisVersion
	 *            redis版本,可为空;rediskey = form class修改日期+redis版本 的组合
	 * @param errLocationJsHandler
	 *            处理错误信息显示位置的 js 函数,如果为空则按默认位置处理
	 * @return html
	 */
	public static String validate(String className, String pathList,
			String formSelector, String redisVersion,
			String errLocationJsHandler) {

		// 根据class文件修改时间做缓存
		String classPath = OkweiEL.class.getResource("/").getPath();
		classPath = classPath.replaceAll("%20", " ")
				+ className.replace(".", "/") + ".class";
		long modified = LoaderTagSupport.getLastModified(classPath);
		String redisKey = REDIS_PACKAGE
				+ "."
				+ className.substring(className.indexOf("form.") + 5)
				+ "."
				+ modified
				+ (StringHelp.IsNullOrEmpty(redisVersion) ? "" : "."
						+ redisVersion);
		String validateJs = RedisUtil.getString(redisKey);
		if (!StringHelp.IsNullOrEmpty(validateJs)) {
			return validateJs.replace("from ori", "from re" + modified);
		}

		StringBuilder rules = new StringBuilder();
		StringBuilder messages = new StringBuilder();
		try {

			// 动态产生 validation js
			Class<?> act = Class.forName(className);
			Field[] fieldList = null;
			if (StringHelp.IsNullOrEmpty(pathList))
				fieldList = act.getDeclaredFields();
			else {
				String[] pathArr = pathList.split(",");
				fieldList = new Field[pathArr.length];
				for (int i = 0; i < pathArr.length; i++) {
					fieldList[i] = act.getDeclaredField(pathArr[i]);
				}
			}

			for (Field field : fieldList) {

				String name = field.getName();
				rules.append(name + ":{");
				messages.append(name + ":{");

				Method curMethod = act.getMethod("get"
						+ name.substring(0, 1).toUpperCase()
						+ name.substring(1));

				NotNull notNull = curMethod
						.getDeclaredAnnotation(NotNull.class);
				NotBlank notblank = curMethod
						.getDeclaredAnnotation(NotBlank.class);
				NotEmpty notempty = curMethod
						.getDeclaredAnnotation(NotEmpty.class);
				// 最小整数
				Min min = curMethod.getDeclaredAnnotation(Min.class);
				// 最大整数
				Max max = curMethod.getDeclaredAnnotation(Max.class);
				// 任何正则匹配
				Pattern pattern = curMethod
						.getDeclaredAnnotation(Pattern.class);
				// 2个属性对比
				EqualTo equalTo = curMethod
						.getDeclaredAnnotation(EqualTo.class);
				BiggerThan bt = curMethod
						.getDeclaredAnnotation(BiggerThan.class);
				// 远程校验
				Remote remote = curMethod.getDeclaredAnnotation(Remote.class);

				// 任意数字,可限定小数个数,非小数个数
				Digits digits = curMethod.getDeclaredAnnotation(Digits.class);
				// 最小小数
				DecimalMin decimalMin = curMethod
						.getDeclaredAnnotation(DecimalMin.class);
				// 最大小数
				DecimalMax decimalMax = curMethod
						.getDeclaredAnnotation(DecimalMax.class);
				// 字符长度范围
				Size size = curMethod.getDeclaredAnnotation(Size.class);
				// 字符长度范围
				Length len = curMethod.getDeclaredAnnotation(Length.class);
				// 任意数字范围,也可用于简单的验证是否数字 @Range(message="请输入数字")
				Range range = curMethod.getDeclaredAnnotation(Range.class);

				 
				if (digits != null) {
					rules.append("pattern:['"
							+ String.format(ValidatorConstant.DIGITS,
									digits.integer(), digits.fraction())
									.replace("\\", "\\\\") + "',");
					if (!StringHelp.IsNullOrEmpty(digits.message()))
						rules.append("'" + digits.message() + "'],");
					else {
						rules.append("'],");
					}
				}

				if (range != null) {
					rules.append("range:[" + range.min() + "," + range.max()
							+ "],");
					if (!StringHelp.IsNullOrEmpty(range.message()))
						messages.append("range:'" + range.message() + "',");
				}
				if (size != null) {
					rules.append((size.min() > 0 ? "required:true," : "")
							+ "rangelength:[" + size.min() + "," + size.max()
							+ "],");
					if (!StringHelp.IsNullOrEmpty(size.message()))
						messages.append((size.min() > 0 ? "required:'"
								+ size.message() + "'," : "")
								+ "rangelength:'" + size.message() + "',");
				}
				if (len != null) {
					rules.append((len.min() > 0 ? "required:true," : "")
							+ "rangelength:[" + len.min() + "," + len.max()
							+ "],");
					if (!StringHelp.IsNullOrEmpty(len.message()))
						messages.append((len.min() > 0 ? "required:'"
								+ len.message() + "'," : "")
								+ "rangelength:'" + len.message() + "',");
				}
				if (notNull != null) {
					rules.append("required:true,");
					if (!StringHelp.IsNullOrEmpty(notNull.message()))
						messages.append("required:'" + notNull.message() + "',");
				}
				if (notblank != null) {
					rules.append("required:true,");
					if (!StringHelp.IsNullOrEmpty(notblank.message()))
						messages.append("required:'" + notblank.message()
								+ "',");
				}
				if (notempty != null) {
					rules.append("required:true,");
					if (!StringHelp.IsNullOrEmpty(notempty.message()))
						messages.append("required:'" + notempty.message()
								+ "',");
				}
				if (min != null) {
					rules.append("min:" + min.value() + ",");
					if (!StringHelp.IsNullOrEmpty(min.message()))
						messages.append("min:'" + min.message() + "',");
				}
				if (decimalMin != null) {
					rules.append("min:" + decimalMin.value() + ",");
					if (!StringHelp.IsNullOrEmpty(decimalMin.message())) {

						messages.append("min:'" + decimalMin.message() + "',");
					}
				}
				if (decimalMax != null) {
					rules.append("max:" + decimalMax.value() + ",");
					if (!StringHelp.IsNullOrEmpty(decimalMax.message())) {
						messages.append("max:'" + decimalMax.message() + "',");
					}
				}
				if (max != null) {
					rules.append("max:" + max.value() + ",");
					if (!StringHelp.IsNullOrEmpty(max.message()))
						messages.append("max:'" + max.message() + "',");
				}
				if (equalTo != null) {
					rules.append("equalTo:'#" + equalTo.toProperty() + "',");
					if (!StringHelp.IsNullOrEmpty(equalTo.message()))
						messages.append("equalTo:'" + equalTo.message() + "',");
				}

				if (remote != null) {
					String[] pathList2 = remote.pathList().split(",");
					StringBuilder ajaxParams = new StringBuilder();
					for (String string : pathList2) {
						ajaxParams.append(string + ": function() { return $('#"
								+ string + "').val();},");
					}
					ajaxParams.deleteCharAt(ajaxParams.length() - 1);
					rules.append("remote: {" + "url: \"" + remote.url()
							+ "\", \r\n" + "type: \"post\",     \r\n"
							+ "dataType: \"json\",  \r\n" + "data: {"
							+ ajaxParams.toString() + "}  \r\n " + "}  \r\n "
							+ ",");
					if (!StringHelp.IsNullOrEmpty(remote.message()))
						messages.append("remote:'" + remote.message() + "',");
				}
			 
				if (pattern != null) {
					rules.append("pattern:['"
							+ pattern.regexp().replace("\\", "\\\\") + "',");
					if (!StringHelp.IsNullOrEmpty(pattern.message()))
						rules.append("'" + pattern.message() + "'],");
					else {
						rules.append("'],");
					}
				}
				if (bt != null) {
					rules.append("biggerthan:['" + bt.toProperty() + "',");
					if (!StringHelp.IsNullOrEmpty(bt.message()))
						rules.append("'" + bt.message() + "'],");
					else {
						rules.append("'],");
					}
				}

				rules.append("},");
				messages.append("},");
			}

		} catch (ClassNotFoundException e) {
			return String.format(ERROR_HTML, "OkweiEL.validate:类" + className
					+ "不存在");
		} catch (NoSuchMethodException e) {
			return String.format(ERROR_HTML,
					"OkweiEL.validate,方法不存在:" + e.getMessage());
		} catch (NoSuchFieldException | SecurityException e) {
			return String.format(ERROR_HTML,
					"OkweiEL.validate,属性不存在:" + e.getMessage());
		}
		validateJs = String
				.format(HTML,
						formSelector,
						rules.toString(),
						messages.toString(),
						StringHelp.IsNullOrEmpty(errLocationJsHandler) ? ErrorPlacementHandlerDefault
								: String.format(ErrorPlacementHandlerCustom,
										errLocationJsHandler), "ori")
				.replace("\r\n", "")
				// 清除 空格 tab缩进
				.replaceAll("[ 	]{2,}", "")
				+ "\r\n" + ERROR_CLASS;
		RedisUtil.setString(redisKey, validateJs);
		return validateJs;
	}

	 

}

声明自定义EL

<?xml version="1.0" encoding="GBK"?>  
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"       
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee   
    http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"       
    version="2.0">     
    <!-- 定义函数版本 -->  
    <tlib-version>1.0</tlib-version>  
    <!-- 定义函数名称 -->  
    <short-name>okwei</short-name>  
    <!-- 定义第一个函数 -->  
    <function>  
        <!-- 生成验证代码 不支持自定义错误显示位置  -->  
        <name>validate</name>  
        <!-- 定义函数处理类 -->  
        <function-class>com.okwei.weiconnect.wap.tag.OkweiEL</function-class>  
        <!-- 定义函数的对应方法 -->  
        <function-signature>  
            java.lang.String validate(java.lang.String,java.lang.String,java.lang.String,java.lang.String)
        </function-signature>
    </function>
    
</taglib>  


二、 定义 form pojo类

 ort com.opensymphony.xwork2.validator.annotations.StringLengthFieldValidator;

/*
 * 登录提交信息
 */
public class RegForm {

	 

	@RequiredStringValidator(message = "手机不能为空")
	public String getPhone() {
		return phone;
	}

	public void setPhone(String phone) {
		this.phone = phone;
	}

	@RequiredStringValidator(message = "密码不能为空")
	@StringLengthFieldValidator(minLength = "6", message = "请输入至少6位密码")
	public String getPwd() {
		return pwd;
	}

	public void setPwd(String pwd) {
		this.pwd = pwd;
	}

	@RequiredStringValidator(message = "请输入店铺名")
	public String getWeiname() {
		return weiname;
	}

	public void setWeiname(String weiname) {
		this.weiname = weiname;
	}

	 

	@RequiredStringValidator(message = "验证码错误")
	public String getVcode() {
		return vcode;
	}

	public void setVcode(String vcode) {
		this.vcode = vcode;
	}

	 

	 

	/*
	 * 手机号
	 */
	private String phone;

	/*
	 * 密码
	 */
	private String pwd;

	 

	/*
	 * 验证码
	 */
	private String vcode;

	/*
	 * 昵称
	 */
	private String weiname;

	 
}

 三、jsp中使用

<article>
		<div class="w fl">
			<form:form action="" method="post" modelAttribute="regform">
				<div class="w fl bg-w p20">
					<div class="w fl line-b inpsue1">
						<div class="fl pusetrr1 imgtp1">
							<img src='${okweiel:imgcdn("images/ig_logs1.png")}' height="25">
						</div>
						<div class="pusetrr2">
							<form:input path="tel" placeholder="输入注册手机号" />
						</div>
					</div>
					<div class="w fl line-b inpsue1">
						<div class="fl pusetrr1 imgtp3">
							<img src='${okweiel:imgcdn("images/ig_logs3.png" )}' height="20">
						</div>
						<div class="pusetrr2">
							<form:password path="pwd" placeholder="设置登录密码" />
						</div>
					</div>
					<div class="w fl line-b inpsue1">
						<div class="fl pusetrr1 imgtp2">
							<img src='${okweiel:imgcdn("images/ig_logs2.png")}' height="15">
						</div>
						<div class="fl pusetrr3">
							<form:input path="vcode" placeholder="输入验证码" />
						</div>
						<div class="fr pusetrr4" id="btnsc">获取验证码</div>
					</div>

				</div>
				 
				<div class="w fl pl20 pr20 mt15">
					<div class="w fl uqdiser">
						<input type="submit" value="提交">
					</div>
				</div>
				<form:errors path="*" cssClass="formerr"></form:errors>
				<div class="w fl mt30 tc f14">
					<a href="${pageContext.request.contextPath }/logreg"  title="已注册账号绑定微信" class="cB">已有账号,去登录></a>
				</div>
				  <div class="w fl wx_logins pr mt30">
					<div class="pa wxin_tile f12 c9">使用微信快速登录</div>
				</div>

				<div class="w fl wxin_dlus mt15 mb15">
					<a href="${pageContext.request.contextPath}/logreg/wxbind"><img
						src='${okweiel:imgcdn("images/wx_logins.png")}' width="60"></a>
				</div>
			 
			</form:form>
		</div>
	</article>
	<!--关键语句-->
	${okweiel:validate("xxx.form.RegisterForm","","#regform","0006")}

四、controller中使用

	/**
	 * 显示注册页
	 * 
	 * @param model
	 * @return
	 */
	@RequestMapping("reg")
	public String reg(Model model) {
		model.addAttribute("regform", new RegisterForm());
		return "loginReg/reg";
	}
	
	
	/**
	 * 提交注册
	 * 
	 * @param form
	 * @param formValid
	 * @param model
	 * @param redirectAttributes
	 * @return
	 */
	@RequestMapping(value = "reg", method = RequestMethod.POST)
	public String doReg(@Valid @ModelAttribute("regform") RegisterForm form,
			BindingResult formValid, Model model, HttpSession session) {
		// 检查手机 检查验证码 交给service
		if (formValid.hasErrors()) {
			return "loginReg/reg";
		}
		ReturnModel loginModel = loginService.userRegist(form.getTel(),
				form.getVcode(), "", form.getPwd());
		if (loginModel.getStatu() == ReturnStatus.Success) {
		 
			 
				return "redirect:/logreg"; 
		} else {
			formValid
					.addError(new ObjectError("regerror", loginModel.getMsg()));
			return "loginReg/reg";
		}
	}
五、效果图



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值