第22-31集
第22集 实现点击实现点击模态框的保存按钮,实现将数据提交给服务器保存
-
1,实现点击模态框的保存按钮,实现将数据提交给服务器保存
-
2,发送ajax请求保存员工
-
URI:的定义
- /emp/{id} GET 查询员工
- /emp POST 保存员工
- /emp/{id} PUT 修改员工
- /emp/{id} DELETE 删除员工
-
//点击模态框的保存按钮实现 $("#save_add_btn").click(function () { // 1,实现点击模态框的保存按钮,实现将表单中的数据提交给服务器保存 //2,发送ajax请求保存员工 // alert($("#empAddBtnModal form").serialize()); $.ajax({ url:"${APP_PATH}/emp", type:"POST", data:$("#empAddBtnModal form").serialize(), success:function (result) { // alert(result.msg); //保存员工成功,但是遗留两个问题 //1,关闭模态框 $('#empAddBtnModal').modal('hide'); //2,来到最后一页,显示刚才保存的数据 //发送ajax来到最后一页即可,两种方式:1,赋予一个较大的数,2,赋予它总记录数 to_page(totalRecord); //totalRecord: 定义的全局变量,用来记录总记录数 } }); });
第23集 表单信息的校验
-
使用正则表达式对表单数据进行验证
-
//表单校验 function validata_add_form(){ //要拿到表单数据要使用正则表达式 var empName = $("#input_add_empName").val(); var regName = /(^[a-zA-Z0-9_-]{6,16}$)|(^[\u2E80-\u9FFF]{2,5})/; if(!regName.test(empName)){ alert("用户名可以是2-5位汉字或者6-16位字母和数字") } //校验邮箱 var email = $("#input_add_email").val(); var regEmail = /^[a-z\d]+(\.[a-z\d]+)*@([\da-z](-[\da-z])?)+(\.{1,2}[a-z]+)+$/; if (!regEmail.test(email)){ alert("邮箱格式不正确!") } return false; }
-
剩余问题:提示信息是弹窗格式,不太美观
第24集 校验信息的显示优化
-
使用bootstrap 的css 来优化
-
Bootstrap 对表单控件的校验状态,如 error、warning 和 success 状态,都定义了样式。使用时,添加
.has-warning
、.has-error
或.has-success
类到这些控件的父元素即可。任何包含在此元素之内的.control-label
、.form-control
和.help-block
元素都将接受这些校验状态的样式。 -
//表单校验 function validata_add_form(){ //要拿到表单数据要使用正则表达式 var empName = $("#input_add_empName").val(); var regName = /(^[a-zA-Z0-9_-]{6,16}$)|(^[\u2E80-\u9FFF]{2,5})/; if(!regName.test(empName)){ //如果第一次是输入的信息是错误的话,第二次再输入正确格式会显示两个class并存,所以每次校验之前先清除固有的class //错误信息的弹窗 // alert("用户名可以是2-5位汉字或者6-16位字母和数字的组合"); // $("#input_add_empName").parent().addClass("has-success"); // $("#input_add_empName").next("span").text("用户名可以是2-5位汉字或者6-16位字母和数字的组合"); show_validata_msg("#input_add_empName","error","用户名可以是2-5位汉字或者6-16位字母和数字的组合"); return false; }else { show_validata_msg("#input_add_empName","success",""); } //校验邮箱 var email = $("#input_add_email").val(); var regEmail = /^[a-z\d]+(\.[a-z\d]+)*@([\da-z](-[\da-z])?)+(\.{1,2}[a-z]+)+$/; if (!regEmail.test(email)){ // alert("邮箱格式不正确!"); show_validata_msg("#input_add_email","error","邮箱格式不正确"); return false; }else{ show_validata_msg("#input_add_email","success",""); } return true; } //校验状态 //ele,status,msg: 分别是参数,状态,和提示信息 function show_validata_msg(ele,status,msg) { //如果第一次是输入的信息是错误的话,第二次再输入正确格式会显示两个class并存,所以每次校验之前先清除固有的class //清除当前元素的校验状态 $(ele).parent().removeClass("has-success has-error"); $(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); } }
- 注意点就是,当条件不满足时返回false,当两个条件同时满足时才返回true
第25集 ajax 校验用户名是否重复
-
首先是校验用户名是否重复的验证
- 1,新增一个方法(function)
- 2,在Controller中写一个请求
- 3,在实现类中实现
-
实现表单数据的清除,即表单重置,避免数据重复保存钻跳过验证的漏洞
-
//新增一个ajax校验用户名是否重复 $("#input_add_empName").change(function () { //发送ajax请求校验是否可用 var empName = this.value; //这里的value :代表的就是 input_add_empName 这个输入框的值 $.ajax({ url:"${APP_PATH}/checkUser", data:"empName="+empName, type:"POST", success:function (result) { if(result.code==100){ show_validata_msg("#input_add_empName","success","用户名可用"); //attr("ajax-va","success"): 给保存按钮自定义一个属性 $("#save_add_btn").attr("ajax-va","success"); }else{ show_validata_msg("#input_add_empName","error","用户名不可用"); $("#save_add_btn").attr("ajax-va","error"); } } }) }); //点击模态框的保存按钮实现,点击保存,实现保存 $("#save_add_btn").click(function () { // 1,实现点击模态框的保存按钮,实现将表单中的数据提交给服务器保存 //1.1 增加表单信息校验 if(!validata_add_form()) { return false; } //1.2 判断之前的ajax用户名验证是否成功 if($(this).attr("ajax-va")=="error"){ return false; } //2,发送ajax请求保存员工 // alert($("#empAddBtnModal form").serialize()); $.ajax({ url:"${APP_PATH}/emp", type:"POST", data:$("#empAddBtnModal form").serialize(), //serialize: 序列化表格中的内容为字符串 success:function (result) { // alert(result.msg); //保存员工成功,但是遗留两个问题 //1,关闭模态框 $('#empAddBtnModal').modal('hide'); //2,来到最后一页,显示刚才保存的数据 //发送ajax来到最后一页即可,两种方式:1,赋予一个较大的数,2,赋予它总记录数 to_page(totalRecord); //totalRecord: 定义的全局变量,用来记录总记录数 } }); });
第26集 ajax用户名重复校验优化
-
1,是前端验证和后台验证的冲突
-
解决:在后台验证中,在数据库验证之前加入与前端逻辑相同的验证
-
@RequestMapping("/checkUser") @ResponseBody public Msg checkUser(@RequestParam("empName") String empName){ //先判断用户名是否合法的表达式 String regex = "(^[a-zA-Z0-9_-]{6,16}$)|(^[\\u2E80-\\u9FFF]{2,5})"; if(!empName.matches(regex)){ return Msg.fail().add("va_value","用户名可以是6-16位字母和数字的组合或者2-5位汉字!!!"); } //数据库验证 Boolean b = employeeServiceImpl.checkUser(empName); if (b){ return Msg.success(); }else{ return Msg.fail().add("va_value","用户名可以是6-16位字母和数字的组合或者2-5位汉字!!!"); } }
-
-
2,是表单样式的残留
-
解决:使用removeClass
-
或者使用 find
-
//表单样式及其内容的清除 function remove_form(ele){ $(ele)[0].reset(); //清空表单样式 find("*")清除所有的 ;find(".help-block") :清除提示信息span $(ele).find("*").removeClass("has-error has-success"); $(ele).find(".help-block").text(""); } //这里是点击新增按钮弹出模态框 $("#emp_add_btn_modal").click(function () { //清除表单数据,即表单重置(完全重置,包括表单的内容和样式) // $("#empAddBtnModal form")[0].reset(); remove_form("#empAddBtnModal form"); //getDepts :得到下拉框部门的信息 getDepts(); $("#empAddBtnModal").modal({ //发送ajax请求,查出部门信息,显示在下拉列表中 //弹出模态框 backdrop:"static" }); });
-
第27集 JSR303 数据校验
-
完整的校验(jquery 前端校验,ajax用户名重复校验,(重点数据)后端校验,数据库唯一性约束)
-
使用JSR303数据校验 hibernate-validator
-
<!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator --> <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>6.0.16.Final</version> </dependency>
-
JSR303的使用
-
@RequestMapping(value = "/emp",method = RequestMethod.POST) @ResponseBody public Msg saveEmp(@Valid Employee employee, BindingResult result){ if(result.hasErrors()){ //校验失败,应该返回失败,在模态框中显示校验失败的错误信息 Map<String,Object> map = new HashMap<String, Object>(); 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{ employeeServiceImpl.saveEmp(employee); return Msg.success(); } }
-
关键字注解:@Valid
-
@Pattern(regexp = "(^[a-zA-Z0-9_-]{6,16}$)|(^[\\u2E80-\\u9FFF]{2,5})", message = "用户名可以是6-16位字母和数字的组合或者2-5位汉字!!!") private String empName; private String gender; //注意点:"\" 在js和java中的意义略有不同 @Email(regexp = "^[a-z\\d]+(\\.[a-z\\d]+)*@([\\da-z](-[\\da-z])?)+(\\.{1,2}[a-z]+)+$", message = "邮箱格式不正确!!!") private String email;
-
关键字注解:@Pattern @Email
-
注意点:"" 在js和java中的意义略有不同
-
第28集 实现修改员工信息
-
逻辑: 首先就是点击修改按钮,然后获取到员工信息,然后修改完成之后是实现保存
-
1,为修改按钮添加一个点击事件
-
/*更新员工信息*/ //1,绑定点击事件,由于click 是在按钮创建之前就绑定了,所以会绑定不上 //2,所以可以在按钮创建的时候绑定,但是带来的问题就是耦合高 //3,绑定点击.live(),但是新版的jquery 中删除了这个方法,可以用on() 来代替 $(document).on("click",".edit_btn",function (){ // alert("edit"); //1,点击修改弹出模态框 $("#empUpdateBtnModal").modal({ backdrop:"static" }); //2,查出员工信息,显示员工信息 getEmp($(this).attr("edit-id")); //3,查询部门信息,显示部门信息 getDepts("#select_Update_dept"); });
-
2,获取对应的数据
-
第29集 显示员工信息
-
上一集只是实现了点击编辑按钮弹出模态框
-
接着实现获取员工数据和部门数据
-
//得到员工信息 function getEmp(id) { $.ajax({ url:"${APP_PATH}/emp/"+id, type:"GET", success:function (result) { // console.log(result); var empData = result.extend.emp; $("#static_Update_empName").text(empData.empName); $("#input_Update_email").val(empData.email); $("#empUpdateBtnModal input[name=gender]").val([empData.gender]); $("#empUpdateBtnModal select").val([empData.dId]); } }) }
-
遇到的问题 : 员工信息的性别(gender)和 部门信息获取总是偶尔失效 ,暂时没有解决
-
将要更新的员工数据:Employee(empId=2024, empName=null, gender=F, [email protected], dId=2, department=null)
第30 31集 实现点击更新按钮实现更新
-
首先考虑的是根据id更新,将模态框获得的id赋值给更新按钮
-
然后需要注意的就是之前我们规定的RestFul风格
-
POST与PUT请求
-
不支持直接发送PUT,需要配置HttpPutFormContentFilter
-
<!-- 3、使用Rest风格的URI,将页面普通的post请求转为指定的delete或者put请求 --> <filter> <filter-name>HiddenHttpMethodFilter</filter-name> <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class> </filter> <filter-mapping> <filter-name>HiddenHttpMethodFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter> <filter-name>HttpPutFormContentFilter</filter-name> <filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class> </filter> <filter-mapping> <filter-name>HttpPutFormContentFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
-
但是这个视频是17年的,现在2021年了,在web.xml中HttpPutFormContentFilter是显示过时的状态,但是还是会有效果
-
实际就是使用ajax发送put请求时候,肯定遇到过后端数据无法被接受到的405错误。
-
基本思路是从request中获取request,getInputStream()的流 inputMessage
然后将流中的数据封装到Map中 MultiValueMap 最后将数据重新封装到request对象中去,完成put数据的封装
实现Toncat的Request不满足的PUT请求类似数据封装层对象这一点操作。
-
官方文档介绍使用这个新的过滤器,并且支持DELETE方法
-
<!-- 3、使用Rest风格的URI,将页面普通的post请求转为指定的delete或者put请求 --> <filter> <filter-name>HiddenHttpMethodFilter</filter-name> <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class> </filter> <filter-mapping> <filter-name>HiddenHttpMethodFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!--<filter>--> <!--<filter-name>HttpPutFormContentFilter</filter-name>--> <!--<filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class>--> <!--</filter>--> <!--<filter-mapping>--> <!--<filter-name>HttpPutFormContentFilter</filter-name>--> <!--<url-pattern>/*</url-pattern>--> <!--</filter-mapping>--> <filter> <filter-name>FormContentFilter</filter-name> <filter-class>org.springframework.web.filter.FormContentFilter</filter-class> </filter> <filter-mapping> <filter-name>FormContentFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
-
最后之前的性别和部门信息获取有问题还是没有解决