CRUD(27):新增-JSR303后端校验

重要的数据都应该加上后端校验,防止用户绕过前端校验提交非法数据。

一、新增逻辑

①在index.jsp页面点击新增;

②弹出新增对话框;

③去数据库查询部门列表,显示在对话框中;

④用户输入数据,并进行校验:

首先输入用户名,这里的输入框绑定了ajax校验。所以输入完成以后,会发送ajax请求校验用户名是否格式正确,是否在数据库中重复。

点击保存后,保存按钮。如果ajax用户名校验失败,返回错误;如果前端校验失败,返回错误。最后发送ajax请求进行jsr303后端校验,校验成功则保存员工,校验失败则返回错误信息。

jquery前端校验,ajax用户名重复校验,重要数据(后端)JSR303校验,唯一约束;

⑤完成保存。

二、要支持JSR303校验,首先导入hiernate validator。


<!-- 
https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator -->

<dependency>

    <groupId>org.hibernate.validator</groupId>

    <artifactId>hibernate-validator</artifactId>

    <version>6.1.5.Final</version>

</dependency>



这个我也之前导入过了。

二、使用JSR303校验,在每一个要校验的字段增加上对应的规则。

在Employee.java中添加:


       @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:请输入正确的邮箱格式,如abc@qq.com")



       private String email;



三、在员工保存的方法中添加这个校验。


       // 保存员工



       @RequestMapping(value = "/emp", method = RequestMethod.POST)



       @ResponseBody



       public Msg saveEmp(@Valid Employee employee, BindingResult result) {







             if (result.hasErrors()) {



                    //显示校验失败的错误信息



                    Map<String,Object> map = new HashMap();



                    List<FieldError> errors = result.getFieldErrors();



                    for(FieldError fieldError:errors) {



                           System.out.println("错误的字段:"+fieldError.getField());



                           System.out.println("错误信息:"+fieldError.getDefaultMessage());



                           map.put(fieldError.getField(),fieldError.getDefaultMessage());



                    }



                    //校验失败返回失败



                    return Msg.fail();



             } else {



                    employeeService.saveEmp(employee);



                    return Msg.success();







             }







       }



四、改写ajax请求






                    //2.发送ajax请求保存员工;



                    $.ajax({



                           url : "${APP_PATH}/emp",



                           type : "POST",



                           data : $("#empAddModal form").serialize(),



                           success : function(result) {



                                 ///alert(result.msg);



                                 if (result.code == 100) {



                                        //关闭模态框



                                        $("#empAddModal").modal('hide');



                                        //来到最后一页显示刚才保存的数据



                                        //发送ajax请求显示最后一页数据



                                        to_page(totalRecord);



                                 } else {



                                        //显示失败信息



                                        console.log(result);



                                 }







                           }



                    });



五、测试一下就发现了一个问题。

已知用户名小杨是存在的:

image.png

然后再输入用户名小杨:

image.png

ajax校验请求返回了用户名重复的失败信息,这里没问题。

然后我们不管它,输入一个错误的邮箱地址,点一下保存:

image.png

这里就不显示ajax校验了,全部显示jquery前端校验的结果。

然后我们把邮箱地址改成正确的,再点一下保存:

image.png

现在jquery完全校验正确了。

但是,我们F12看一下:

image.png

并没有发送保存数据的请求。

再看下代码:

ajax-va="error",所以没保存。

那我们就把这个error改成success,再点一下保存:

对话框消失了!记录也跳到了最后一页,但是没有显示我们新保存的小杨的个人信息。

F12看一下network:

image.png

可以看到这个发送的ajax请求返回的状态是成功,并且我们还发送了pn=1021

但是!!!数据库里面查询到了!!

image.png

六、问题的解决

最开始那个问题很好解决,把用户名校验放在前面,前端校验放在后面就好了,这样就不会出现邮箱出现错误以后,用户名反而校验成功的问题。

至于把error改成success提交,绕过验证的问题——

对不起我也不知道怎么办了,只好在数据库中对用户名添加了一个唯一性约束,这时候保存还是能点保存,但数据无法写入。

image.png

七、源代码

新增功能到这里就差不多了,虽然不知道以后实际运用还会出什么千奇百怪的问题。

这里放一下index.jsp的源代码:


<%@ 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>



<html>



<head>



<meta charset="UTF-8">



<title>员工列表</title>



<!-- 拿到当前项目路径,以/开始,不以/结束 -->



<%



       pageContext.setAttribute("APP_PATH", request.getContextPath());



%>







<!-- 引入jquery -->



<script type="text/javascript"



       src="${APP_PATH }/static/js/jquery-1.12.4.min.js"></script>



<!-- 引入Bootstrap样式 -->



<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>











       <!-- 新增的modal -->



       <div class="modal fade" id="empAddModal" tabindex="-1" role="dialog"



             aria-labelledby="myModalLabel">



             <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">&times;</span>



                                 </button>



                                 <h4 class="modal-title" id="myModalLabel">新增员工</h4>



                           </div>



                           <div class="modal-body">



                                 <form class="form-horizontal">



                                        <div class="form-group">



                                               <label for="empName_add_input" 

class="col-sm-2 control-label">empName</label>



                                               <div class="col-sm-10">



                                                     <input type="text" 

class="form-control" name="empName"



                                                            id="empName_add_input" placeholder="empName"> 
<span



                                                            class="help-block"> 

</span>



                                               </div>



                                        </div>



                                        <div class="form-group">



                                               <label for="email_add_input" 

class="col-sm-2 control-label">email</label>



                                               <div class="col-sm-10">



                                                     <input type="text" 

class="form-control" name="email"



                                                            id="email_add_input" 

placeholder="hello123@qq.com"> <span



                                                            class="help-block"> 

</span>



                                               </div>



                                        </div>







                                        <div class="form-group">



                                               <label for="gender_add_input" 

class="col-sm-2 control-label">性别</label>



                                               <div class="col-sm-10">



                                                     <label 

class="radio-inline"> <input type="radio"



                                                            name="gender" 

id="gender1_add_input" value="m"



                                                            checked="checked"> 

男



                                                     </label> <label 

class="radio-inline"> <input type="radio"



                                                            name="gender" 

id="gender1_add_input" value="f"> 女



                                                     </label>



                                               </div>



                                        </div>







                                        <div class="form-group">



                                               <label class="col-sm-2 

control-label">deptName</label>



                                               <div class="col-sm-4">



                                                     <!-- 部门提交部门ID即可 -->



                                                     <select 

class="form-control" name="dId" id="dept_add_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-12">



                           <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_modal_btn">新增</button>



                           <button class="btn btn-danger">删除</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>gender</th>



                                               <th>email</th>



                                               <th>deptName</th>



                                               <th>操作</th>



                                        </tr>



                                 </thead>



                                 <tbody></tbody>



                           </table>



                    </div>



             </div>







             <!-- 显示分页 -->



             <div class="row">



                    <!-- 分页文字信息 -->



                    <div class="col-md-6" id="page_info_area"></div>



                    <!-- 分页条信息 -->



                    <div class="col-md-6" id="page_nav_area"></div>



             </div>



       </div>







       <script type="text/javascript">



       <!--页面加载完成以后直接发送一个ajax请求,拿到分页数据-->



             var totalRescord;



             $(function() {



                    to_page(1);



             });







             function to_page(pn) {



                    $.ajax({



                           url : "${APP_PATH}/emps",



                           data : "pn=" + pn,



                           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



                    $("#emps_table tbody").empty();







                    var emps = result.extend.pageInfo.list;



                    $.each(emps, function(index, item) {







                           var empIdTd = $("<td></td>").append(item.empId);



                           var empNameTd = $("<td></td>").append(item.empName);



                           var genderTd = $("<td></td>").append(



                                        item.gender == 'm' ? "男" : "女");



                           var emailTd = $("<td></td>").append(item.email);



                           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 delBtn = $("<button></button>").addClass(



                                        "btn btn-danger btn-sm").append(



                                        $("<span></span>")



                                                     .addClass("glyphicon 

glyphicon-trash")).append(



                                        "删除");



                           var btnTd = $("<td></td>").append(editBtn).append(" 

").append(



                                        delBtn);







                           //append方法执行完成以后还是返回原来的元素



                           $("<tr></tr>").append(empIdTd).append(empNameTd).append(



                                        genderTd).append(emailTd).append(deptNameTd).append(



                                        btnTd).appendTo("#emps_table tbody");



                    });



             }







             //显示分页信息



             function build_page_info(result) {



                    //首先清空原来的



                    $("#page_info_area").empty();



                    $("#page_info_area").append(



                                 "当前第" + result.extend.pageInfo.pageNum + "页 

共"



                                               + result.extend.pageInfo.pages + 

"页 共"



                                               + result.extend.pageInfo.total + 

"条记录");



                    totalRecord = result.extend.pageInfo.total;







             }







             //显示分页条  



             function build_page_nav(result) {



                    //首先清空原来的



                    $("#page_nav_area").empty();



                    var ul = $("<ul></ul>").addClass("pagination");



                    var firstPageLi = 

$("<li></li>").append($("<a></a>").append("首页"))



                                 .attr("href", "#");







                    var prePageLi = $("<li></li>").append(



                                 $("<a></a>").append("&laquo;"));







                    if (result.extend.pageInfo.hasPreviousPage == false) {



                           prePageLi.addClass("disabled");



                    } else {



                           prePageLi.click(function() {



                                 to_page(result.extend.pageInfo.pageNum - 1);



                           });



                    }



                    var nextPageLi = $("<li></li>").append(



                                 $("<a></a>").append("&raquo;"));







                    if (result.extend.pageInfo.hasNextPage == false) {



                           nextPageLi.addClass("disabled");



                    } else {



                           nextPageLi.click(function() {



                                 to_page(result.extend.pageInfo.pageNum + 1);



                           });



                    }



                    var lastPageLi = 

$("<li></li>").append($("<a></a>").append("末页"))



                                 .attr("href", "#");







                    firstPageLi.click(function() {



                           to_page("1");



                    });



                    lastPageLi.click(function() {



                           to_page(result.extend.pageInfo.pages);



                    });







                    //添加首页和前一页的显示



                    ul.append(firstPageLi).append(prePageLi);



                    $.each(result.extend.pageInfo.navigatepageNums, 

function(index,



                                 item) {



                           var numLi = 

$("<li></li>").append($("<a></a>").append(item));



                           //页码按钮选中变蓝



                           if (result.extend.pageInfo.pageNum == item) {



                                 numLi.addClass("active");



                           }



                           numLi.click(function() {



                                 to_page(item);



                           });



                           //添加页码显示



                           ul.append(numLi);



                    });



                    //添加下一页和末页的显示



                    ul.append(nextPageLi).append(lastPageLi);







                    var navEle = $("<nav></nav>").append(ul);



                    navEle.appendTo("#page_nav_area");







             }







             //点击新增按钮



             $("#emp_add_modal_btn").click(function() {



                    //表单重置



                    reset_form("#empAddModal form");







                    //发送ajax请求,显示部门信息,出现在下拉列表中



                    getDepts();



                    //弹出模态框



                    $("#empAddModal").modal({



                           backdrop : "static"



                    });



             });







             function getDepts() {



                    $.ajax({



                           url : "${APP_PATH}/depts",



                           type : "GET",



                           success : function(result) {



                                 //显示部门信息在下拉列表中



                                 $.each(result.extend.depts, function() {



                                        var optionEle = 

$("<option></option>").append(



                                                     this.deptName).attr("value", this.deptId);



                                        optionEle.appendTo("#dept_add_select");



                                 });



                           }



                    });



             }







             //定义校验函数



             //校验名字



             function validate_add_form() {



                    //1.拿到校验数据,使用正则表达式进行校验







                    var empName = $("#empName_add_input").val();



                    var regName = 

/(^[a-zA-Z0-9_-]{6,16}$)|(^[\u2E80-\u9FFF]{2,5})/;



                    



                    var email = $("#email_add_input").val();



                    var regEmail = 

/^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/;







                    //校验名字



                    if (!regName.test(empName)) {



                           show_validate_msg("#empName_add_input", "error",



                                        "jquery:用户名可以是2-5位中文、6-16位字母、横杠或下划线");



                           return false;



                    } else {



                           show_validate_msg("#empName_add_input", "success",



                                        "jquey:用户名格式正确!");



                    }







                    //校验邮箱



                    if (!regEmail.test(email)) {



                           show_validate_msg("#email_add_input", "error",



                                        "jquery:请输入正确的邮箱格式,如abc@qq.com");



                           return false;



                    } else {



                           show_validate_msg("#email_add_input", "success",



                                        "jquery:邮箱格式正确!");



                    }



                    return true;



             }







             function reset_form(ele) {



                    //清除表单数据



                    $(ele)[0].reset();



                    //清空表单样式



                    $(ele).find("*").removeClass("has-success has-error");



                    $(ele).find(".help-block").text("");







             }







             function show_validate_msg(ele, status, msg) {



                    //清除校验状态



                    $(ele).parent().removeClass("has-success has-error");



                    if ("success" == status) {



                           $(ele).parent().addClass("has-success");



                           $(ele).next().text(msg);



                    } else if ("error" == status) {



                           $(ele).parent().addClass("has-error");



                           $(ele).next().text(msg);



                    }



             }







             $("#empName_add_input").change(



                           function() {



                                 //发送ajax请求校验用户名是否可用



                                 var empName = this.value;



                                 $.ajax({



                                        url : "${APP_PATH}/checkuser",



                                        data : "empName=" + empName,



                                        type : "POST",



                                        success : function(result) {



                                               if (result.code == 100) {



                                                     show_validate_msg("#empName_add_input",



                                                                   "success", 

"ajax:用户名不重复,可用√");



                                                     $("#emp_save_btn").attr("ajax-va", "success");



                                               } else {



                                                     show_validate_msg("#empName_add_input",



                                                                   "error", 

result.extend.va_msg);



                                                     $("#emp_save_btn").attr("ajax-va", "error");



                                               }



                                        }



                                 });







                           });







             //点击保存按钮



             $("#emp_save_btn").click(function() {



                    //1.模态框中的数据提交给服务器进行保存;







                    //判断用户名校验是否成功



                    if ($(this).attr("ajax-va") == "error") {



                           return false;



                    }



                    ;







                    //对要提交给服务器的数据进行前端校验



                    if (!validate_add_form()) {



                           return false;



                    }



                    ;







                    //2.发送ajax请求保存员工;



                    $.ajax({



                           url : "${APP_PATH}/emp",



                           type : "POST",



                           data : $("#empAddModal form").serialize(),



                           success : function(result) {



                                 ///alert(result.msg);



                                 if (result.code == 100) {



                                        //关闭模态框



                                        $("#empAddModal").modal('hide');



                                        //来到最后一页显示刚才保存的数据



                                        //发送ajax请求显示最后一页数据



                                        to_page(totalRecord);



                                 } else {



                                        //显示失败信息



                                        if (undefined != 

result.extend.errorFields.email) {



                                               alert(result.extend.errorFields.email);



                                        }



                                        if (undefined != 

result.extend.errorFields.empName) {



                                               alert(result.extend.errorFields.empName);



                                        }



                                 }







                           }



                    });







             });



       </script>



</body>



</html>





posted on 2021-02-16 00:22  northwest  阅读(64)  评论(0)    收藏  举报

导航