示例项目使用的是springMVC+mybatis+freemarker架构,项目功能比较简单,只包括参数校验。
项目背景
很多项目由于开发周期比较短,为了完成功能上的需求而忽略了很多细节,这些项目在后期都需要大量的维护工作,其中就包括参数验证这个细节。
在前端的工作中,有些表单元素的验证实时性要求比较高,有些需要在输入错误后回复到之前的状态,这些细节都可以提高用户的体验,对于我们开发人员来说,前端使用第三方框架可以将参数的校验和表单元素的提交相分离,降低代码之前的耦合度,降低后期的维护成本,方便项目的国际化。
在后端的工作中,由于一些非法参数的传入使后台多了很多异常,有时候也会破坏代码的逻辑,从而产生脏数据,参数的校验会使系统更加健壮,使用第三方框架可以实现错误信息的可配置化和国际化。
参数的校验在项目开发中占据着很重要的地位,介于这些原因,写了自己的第一篇博文介绍参数校验的工作,错误信息的配置尽力做到前后端一致。
所用到的第三方插件
- 前端使用jquery.validate.js
- 后端使用fo-validation-0.9.1.RELEASE.jar
jquery.validate.js的使用
html页面布局(使用到了bootstrap)
<body background="${ctx}/static/image/background/bg_login.jpg" style="background-size: 100%;">
<div class="container">
<h3></h3>
<div class="row">
<div class="mydiv col-sm-4 col-sm-offset-4">
<form id="userinfo" method="post" action="/user/login" class="form-horizontal" role="form">
<div class="form-group">
<label for="username" class="col-sm-3 control-label">用户名</label>
<div class="col-sm-9">
<input type="text" name="username" class="form-control" id="username"
placeholder="请输入用户名">
</div>
</div>
<div class="form-group">
<label for="password" class="col-sm-3 control-label">密码</label>
<div class="col-sm-9">
<input type="password" class="form-control" id="password" name="password"
placeholder="请输入密码">
</div>
</div>
<div class="form-group">
<label for="confirm_password" class="col-sm-3 control-label">确认密码</label>
<div class="col-sm-9">
<input type="password" class="form-control" id="confirm_password" name="confirm_password"
placeholder="确认密码">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-3 col-sm-4">
<div class="checkbox">
<label>
<input type="checkbox" id="remember" name="remember">记住密码
</label>
</div>
</div>
<div class="col-sm-offset-1 col-sm-4">
<a href="javascript:;">忘记密码?</a>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-3 col-sm-4">
<button type="submit" class="btn btn-primary">登录</button>
</div>
<div class="col-sm-offset-1 col-sm-4">
<button type="submit" class="btn btn-success">注册</button>
</div>
</div>
</form>
</div>
</div>
</div>
</body>
js参数校验
$(function(){
$(window).resize();
//由于remote的校验要求后台的返回结果只能是true或者false
//自定义校验方法可以扩展remote功能,后台可以返回各种数据
//添加自定义校验方法addMethod(name, method, message)
//这个方法通过ajax请求调用后台代码查询用户信息,返回状态码和提示信息
//调用方法在后面代码片段中
$.validator.addMethod("userCanUse",function(value,element,params){
var reqParams = {"userId":value};
var isRight = true;
$.ajax({
url:"/datamanager/user/validateUser",
data:reqParams,
async:false,
type:"post",
dataType:"json",
success:function(data){
if(data.returnCode!="000"){//用户信息不合法
isRight = false;
//由于jquery.validate提示信息只有一个
//我们这里是根据后台返回的结果进行动态提示,所以我们在后面的errorPlacement把这种类型的错误信息屏蔽掉
$("h3").text("error:("+$(element).attr("name")+")"+data.returnMessage);
}else{//输入用户可用
isRight = true;
//如果成功信息只有一个,跟其他输入框一样的话就可以放在success里面添加成功样式,我们这里成功只有一种情况所以把下面代码注释掉了
//$("h3").text("success:("+$(element).attr("name")+")"+data.returnMessage);
}
}
});
return isRight;//返回校验结果
},$("h3").text());
$("#userinfo").validate({
debug:true,
ignore: ".ignore",
rules: {//校验规则
username: {
required:"#remember:checked",//如果remember复选框选中的话username才是必填项
userCanUse:0//自定义提示信息
},
password: {
required: true,
minlength: 5
},
confirm_password: {
required: true,
minlength: 5,
equalTo: "#password"
}
},
messages: {//错误提示信息,我们这里没有用到,错误样式都是在errorPlacement里面添加的
username: {
required: "请输入Email地址",
},
password: {
required: "请输入密码",
minlength: "密码不能小于{0}个字 符"
},
confirm_password: {
required: "请输入确认密码",
minlength: "确认密码不能小于{0}个字符",
equalTo: "两次输入密码不一致不一致"
}
},
onkeyup:false,
errorPlacement: function(error, element) {
if(!$(element).hasClass("asynCheck")//异步请求包含多种错误提示
&&error.text().trim()!="")
$("h3").text("error:("+$(element).attr("name")+")"+error.text());
},
success: function(label) {
$("h3").text("success:"+label[0]["htmlFor"]);
}
});
});
js里面添加的自定义校验方法调用的后台代码
@RequestMapping("/validateUser")
@ResponseBody
public ResponseModel validateUser(String userId){
ResponseModel responseModel = new ResponseModel();
if(userId==null||userId.startsWith("1")){
responseModel.setReturnCode("301");
responseModel.setReturnMessage("用户不存在");
}else if(userId.startsWith("2")){
responseModel.setReturnCode("302");
responseModel.setReturnMessage("用户被冻结");
}else if(userId.startsWith("3")){
responseModel.setReturnCode("303");
responseModel.setReturnMessage("用户申请中");
}else{
responseModel.setReturnCode("000");
responseModel.setReturnMessage("用户可以使用");
}
return responseModel;
}
fo-validation-0.9.1.RELEASE.jar的使用
maven导入依赖的jar包
<dependency>
<groupId>cc.fozone.validation</groupId>
<artifactId>fo-validation</artifactId>
<version>0.9.1.RELEASE</version>
</dependency>
spring中添加参数校验的配置
<!-- 配置参数认证 -->
<!-- 基于 Spring 配置读取 -->
<bean id="springValidateConfig" class="cc.fozone.validation.config.SpringValidateConfig">
<property name="validators">
<value>validators.fo.xml</value>
</property>
<property name="rules">
<value>rules.fo.xml</value>
</property>
</bean>
<!-- 配置验证服务 -->
<bean id="basicValidateService" class="cc.fozone.validation.BasicValidateService">
<constructor-arg index="0" ref="springValidateConfig"/>
</bean>
<!-- 配置基于Spring的验证器 -->
<bean class="cc.fozone.validation.validators.SpringValidator"/>
validators.fo.xml里的配置
<fozone-validators>
<validator name="required" class="cc.fozone.validation.validators.RequiredValidator"/>
<validator name="match" class="cc.fozone.validation.validators.MatchValidator"/>
<validator name="between" class="cc.fozone.validation.validators.BetweenValidator"/>
<validator name="min" class="cc.fozone.validation.validators.MinValidator"/>
<validator name="max" class="cc.fozone.validation.validators.MaxValidator"/>
<validator name="equals" class="cc.fozone.validation.validators.EqualsValidator"/>
<validator name="timestampLessEqual" class="cc.fozone.validation.validators.TimestampLessEqualValidator"/>
<validator name="timestampCreaterEqual" class="cc.fozone.validation.validators.TimestampCreaterEqualValidator"/>
<validator name="spring" useSpring="true" class="cc.fozone.validation.validators.SpringValidator"/>
</fozone-validators>
rules.fo.xml里配置项目中需要的校验规则
<fozone-validation>
<include file="validate/user.rules.fo.xml"/>
<include file="validate/project.rules.fo.xml"/>
</fozone-validation>
user.rules.fo.xml
<fozone-validation>
<group name="user.validate">
<field name="username">
<rule name="min" message="密码至少5个字符">
<param name="value" value="5"/>
</rule>
</field>
</group>
</fozone-validation>
controller调用参数验证方法
Map<String,String> map = basicValidateService.validate(userModel,"user.validate");
具体的介绍可以从参考资料里获取
参考资料:
http://www.runoob.com/jquery/jquery-plugin-validate.html
http://my.oschina.net/41zone/blog/324657?fromerr=PfE1H6Ko