1 为什么要使用JSR303?
1) 前端的jQuery校验;
调用此函数的时候,容易被人而已篡改,使其跳过此验证,或者即使错误也会强制变为success。
所以需要在后台进行验证。
2) 后台Ajax验证用户名重复的时候,也对用户名格式进行了判断:
但是这样判断比较麻烦。
3)JSR303校验:
所以需要JSR303校验。
2 具体做法
1) 引入需要的依赖jar包:
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-validator --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>5.1.3.Final</version> </dependency>
2) 实体类属性上加入格式限制:
@Pattern(regexp = "(^[a-zA-Z0-9_-]{6,16}$)|(^[\u2E80-\u9FFF]{2,5})", message = "后台JSR303:用户名必须是2-5位中文或者6-16位英文和数字的组合") private String empName; @Pattern(regexp="^([a-z0-9_\\.-]+)@([\\da-z\\.-]+)\\.([a-z\\.]{2,6})$", message="后台JSR303: 邮箱格式不正确") private String eamil;
3) 修改保存员工借口,加入JSR303的校验,并且将错误信息返回到前端AJAX请求的回调函数中进行显示:
/** * 新增员工信息 * 更新:加入JSR303校验存储的员工信息 * @param employee * @return */ @RequestMapping(value = {"/emp/save"}, method = {RequestMethod.POST}) @ResponseBody public Msg addEmp(@Valid Employee employee, BindingResult result){ if (result.hasErrors()){ Map<String, Object> map = new HashMap<>(); List<FieldError> errors = result.getFieldErrors(); for (FieldError error : errors){ System.out.println("错误信息字段名:" + error.getField() ); System.out.println("错误信息:" + error.getDefaultMessage() ); map.put(error.getField(), error.getDefaultMessage()); } return Msg.fail().add("errorFields", map); } else { employeeService.saveEmp(employee); return Msg.success(); } }
4) Ajax请求回调,判断,如果有错误信息的时候就进行显示:
/**
* 点击保存按钮,保存员工信息
*/
$("#emp_save_btn").click(function () {
//1 先校验 !validate_add_form()==true的时候说明校验有问题
/*if(!validate_add_form()){
return false;
}*/
//2 看用户名是否重复
if($("#empName").attr("empName_validate") == "error"){
return false;
}
//3 发送AJAX请求保存员工信息
$.ajax({
url:"${APP_PATH}/emp/save",
type: "POST",
data:$("#emp_add_form").serialize(),
success: function (result) {
if(result.code == 100){
alert("保存成功");
//1 关闭模态框
$("#Emp_Add_Modal").modal("hide");
//2、来到最后一页,显示刚才保存的数据
//发送ajax请求显示最后一页数据即可
to_page(totalRecord);
}else {
console.log(result);
//显示错误信息 !=undifned 即不为空,表示有错
if (undefined != result.extendInfo.errorFields.eamil){
show_validate_msg("#email", "error", result.extendInfo.errorFields.eamil)
}
if (undefined != result.extendInfo.errorFields.empName){
show_validate_msg("#empName", "error", result.extendInfo.errorFields.empName);
}
}
}
});
});
验证的时候可以将第一步去掉,返回结果如下:
完整代码如下:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>员工信息显示</title> <% pageContext.setAttribute("APP_PATH", request.getContextPath()); %> <script type="text/javascript" src="${APP_PATH }/static/js/jquery-1.12.4.min.js"></script> <link href="${APP_PATH }/static/bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet"> <script src="${APP_PATH }/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script> </head> <body> <!--新增员工Model框--> <div class="modal fade" id="Emp_Add_Modal" tabindex="-1" role="dialog" aria-labelledby="Emp_Add_Modal_label"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> <h4 class="modal-title" id="myModalLabel">新增员工</h4> </div> <div class="modal-body"> <form class="form-horizontal" id="emp_add_form"> <div class="form-group"> <label for="empName" class="col-sm-2 control-label">empName:</label> <div class="col-sm-10"> <input type="text" class="form-control" name="empName" id="empName" placeholder="empName"> <span id="helpBlock11" class="help-block"></span> </div> </div> <div class="form-group"> <label for="email" class="col-sm-2 control-label">email:</label> <div class="col-sm-10"> <input type="email" class="form-control" name="eamil" id="email" placeholder="email"> <span id="helpBlock22" class="help-block"></span> </div> </div> <div class="form-group"> <label class="col-sm-2 control-label">gender:</label> <div class="col-sm-offset-2 col-sm-10"> <label class="radio-inline"> <input type="radio" name="gender" id="gender1_input" checked="checked" value="M"> 男 </label> <label class="radio-inline"> <input type="radio" name="gender" id="gender2_input" value="F"> 女 </label> </div> </div> <div class="form-group"> <label class="col-sm-2 control-label">deptName:</label> <div class="col-sm-4"> <select class="form-control" name="dId" id="deptName_select"> </select> </div> </div> </form> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button> <button type="button" class="btn btn-primary" id="emp_save_btn">保存</button> </div> </div> </div> </div> <!--显示页面--> <div class="container"> <!-- 标题 --> <div class="row"> <div class="col-md-4"> <h1>SSM练手项目-CRUD</h1> </div> </div> <!-- 操作按钮 --> <div class="row"> <div class="col-md-4 col-md-offset-8"> <button class="btn btn-primary" id="emp_add_btn" data-toggle="modal" data-target="#Emp_Add_Modal">新增</button> <button class="btn btn-danger" id="emp_delete_btn">删除</button> </div> </div> <!-- 表格 --> <div class="row"> <div class="col-md-12"> <table class="table table-hover" id="emps_table"> <thead> <tr> <th>#</th> <th>empName</th> <th>email</th> <th>gender</th> <th>deptName</th> <th>Option</th> </tr> </thead> <tbody> </tbody> </table> </div> </div> <!-- 分页信息 --> <div class="row"> <div class="col-md-6" id="page_info"> </div> <div class="col-md-6" id="nav_pagination_info"> </div> </div> </div> <script type="text/javascript"> var totalRecord; $(function(){ //默认去首页 to_page(1); }) function to_page(pageNo) { $.ajax({ url:"${APP_PATH}/emp/list2", data:"pageNo="+pageNo, type:"get", success:function (result) { console.log(result); //1、解析并显示员工数据 build_emps_table(result); //2、解析并显示分页信息 build_page_info(result); //3、解析显示分页条数据 build_page_nav(result); } }); } function build_emps_table(result) { //清空表格 $("#emps_table tbody").empty(); var emps = result.extendInfo.pageInfo.list; $.each(emps, function (index, item) { var empIdTd = $("<td></td>").append(item.empId); var empNameTd = $("<td></td>").append(item.empName); var emailTd = $("<td></td>").append(item.eamil); var genderId = $("<td></td>").append(item.gender=="M"?"男":"女"); var deptNameTd = $("<td></td>").append(item.department.deptName); var editBtn = $("<button></button>").addClass("btn btn-info btn-sm") .append( $("<span></span>").addClass("glyphicon glyphicon-pencil") .append("编辑")); var deleteBtn = $("<button></button>").addClass("btn btn-danger btn-sm") .append( $("<span></span>").addClass("glyphicon glyphicon-trash") .append("删除")); $("<tr></tr>").append(empIdTd) .append(empNameTd) .append(emailTd) .append(genderId) .append(deptNameTd) .append(editBtn) .append(" ") .append(deleteBtn) .appendTo("#emps_table tbody"); }) } function build_page_info(result) { //清空 $("#page_info").empty(); var pageInfo = result.extendInfo.pageInfo; var curPage = pageInfo.pageNum; var pages = pageInfo.pages; var totalPages = pageInfo.total; $("#page_info").append(" 当前第"+curPage+"页,") .append("共有"+ pages +"页,") .append("总共"+ totalPages + "条记录数"); totalRecord = totalPages; } function build_page_nav(result) { //清空 $("#nav_pagination_info").empty(); var nav = $("<nav></nav>"); var ul = $("<tr></tr>").addClass("pagination"); //首页、上一页 var firstPageLi = $("<li></li>").append($("<a></a>").append("首页").attr("href", "#")); var prePageLi = $("<li></li>").append($("<a></a>").append("«")); //首页禁止点击,并且不显示数据 if(result.extendInfo.pageInfo.hasPreviousPage == false){ firstPageLi.addClass("disabled"); prePageLi.addClass("disabled"); }else { //首页,上一页添加事件,显示对应页码数据 firstPageLi.click(function () { to_page(1) }); prePageLi.click(function () { to_page(result.extendInfo.pageInfo.pageNum-1); }); } //末页、下一页 var lastPageLi = $("<li></li>").append($("<a></a>").append("末页").attr("href", "#")); var nextPageLi = $("<li></li>").append($("<a></a>").append("»")); //末页禁止点击,并且不显示数据 if(result.extendInfo.pageInfo.hasNextPage == false){ lastPageLi.addClass("disabled"); nextPageLi.addClass("disabled"); }else{ //末页,下一页添加事件,显示对应页码数据 lastPageLi.click(function () { to_page(result.extendInfo.pageInfo.pages); }); nextPageLi.click(function () { to_page(result.extendInfo.pageInfo.pageNum + 1); }); } ul.append(firstPageLi).append(prePageLi); //1,2,3,4,5页码显示 $.each(result.extendInfo.pageInfo.navigatepageNums, function (index, item) { var numLi = $("<li></li>").append($("<a></a>").append(item)); if(result.extendInfo.pageInfo.pageNum == item){ numLi.addClass("active"); } //点击页码跳转到对应页码并显示对应数据 numLi.click(function(){ to_page(item); }); ul.append(numLi); }) ul.append(nextPageLi).append(lastPageLi); nav.append(ul); $("#nav_pagination_info").append(nav); } /** * 清除样式 */ function reset_form(ele){ $(ele)[0].reset(); //清空表单样式 $(ele).find("*").removeClass("has-error has-success"); $(ele).find(".help-block").text(""); } /** * 点击新增按钮,填写新增员工信息 * 新增之前需要清除样式 */ $("#emp_add_btn").click(function () { //清楚表单样式 reset_form("#Emp_Add_Modal form"); //1 获取部门信息,并显示在下拉框中 getDeptName("#deptName_select"); //2 显示模态框 $('#Emp_Add_Modal').modal({ backdrop:static, keyboard:true }); }); function getDeptName(ele) { $(ele).empty(); $.ajax({ url: "${APP_PATH}/dept/deptList", type: "GET", success: function (result) { console.log(result); //将信息显示到下拉列表中 $.each(result.extendInfo.depts,function () { var optionEle = $("<option></option>").append(this.deptName).attr("value", this.deptId); optionEle.appendTo(ele); }); } }); } /** * 点击保存按钮,保存员工信息 */ $("#emp_save_btn").click(function () { //1 先校验 !validate_add_form()==true的时候说明校验有问题 if(!validate_add_form()){ return false; } //2 看用户名是否重复 if($("#empName").attr("empName_validate") == "error"){ return false; } //3 发送AJAX请求保存员工信息 $.ajax({ url:"${APP_PATH}/emp/save", type: "POST", data:$("#emp_add_form").serialize(), success: function (result) { if(result.code == 100){ alert("保存成功"); //1 关闭模态框 $("#Emp_Add_Modal").modal("hide"); //2、来到最后一页,显示刚才保存的数据 //发送ajax请求显示最后一页数据即可 to_page(totalRecord); }else { console.log(result); //显示错误信息 !=undifned 即不为空,表示有错 if (undefined != result.extendInfo.errorFields.eamil){ show_validate_msg("#email", "error", result.extendInfo.errorFields.eamil) } if (undefined != result.extendInfo.errorFields.empName){ show_validate_msg("#empName", "error", result.extendInfo.errorFields.empName); } } } }); }); /** * change:检测到输入框有改变后就会去验证用户名是否重复: */ //校验用户名是否重复 $("#empName").change(function () { var empName = this.value; $.ajax({ url: "${APP_PATH}/emp/checkUser", data:"empName="+ empName, type:"POST", success: function (result) { if(result.code == 100){ show_validate_msg("#empName", "success", "用户名可用"); $("#emp_save_btn").attr("empName_validate", "success"); }else { //显示后台验证的错误信息 show_validate_msg("#empName", "error", result.extendInfo.validate_error_msg); $("#emp_save_btn").attr("empName_validate", "error"); } } }); }); function show_validate_msg(ele, status, msg) { //清除当前元素的校验状态 $(ele).parent().removeClass("has-error has-success"); $(ele).next("span").text(""); if("success"==status){ $(ele).parent().addClass("has-success"); $(ele).next("span").text(msg); }else if("error"==status){ $(ele).parent().addClass("has-error"); $(ele).next("span").text(msg); } } /** * 检验表格中输入的信息格式是否正确 */ function validate_add_form(){ //验证用户名 var empName = $("#empName").val(); var regName = /(^[a-zA-Z0-9_-]{6,16}$)|(^[\u2E80-\u9FFF]{2,5})/; if (!regName.test(empName)){ // alert("用户名可以是2-5位中文或者6-16位英文和数字的组合"); /* $("#empName").parent().addClass("has-error"); $("#empName").next("span").text("用户名可以是2-5位中文或者6-16位英文和数字的组合");*/ show_validate_msg("#empName", "error", "用户名可以是2-5位中文或者6-16位英文和数字的组合"); return false; }else{ show_validate_msg("#empName", "success", ""); /* $("#empName").parent().addClass("has-success");*/ } //验证邮箱 var email = $("#email").val(); var regEmail = /^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/; if(!regEmail.test(email)){ //alert("邮箱格式不正确!"); /* $("#email").parent().addClass("has-error"); $("#email").next("span").text("邮箱格式不正确!");*/ show_validate_msg("#email", "error", "邮箱格式不正确!"); return false; }else{ /* $("#email").parent().addClass("has-success");*/ show_validate_msg("#email", "success", ""); } return true; } </script> </body> </html>