3.3 数据验证
前端传入后端的数据需要进行验证,前端的数据在Web界面中需要进行完全的验证,那么,还需要在后端进行验证吗?答案是需要的,因为很容易绕过前端的验证,如果这样的数据被提交到后端,必然会产生相应的问题,因此,数据验证,除了前端的验证外,还需要在后端进行。
SpringMVC提供了验证参数的机制,一方面,它可以支持JSR-303注解验证,在默认的情况下,SpringBoot会引入关于Hibernate Validator机制来支持JSR-303验证规范;另一方面,也可以自定义验证规则。
3.3.1 JSR-303注解验证
JSR-303验证主要是通过注解的方式进行的,这里在控制器开发的项目中,即上一次的项目中,在com.example.mybatisdemo.entity包下新建一个名称为Student的POJO,然后在其相关的属性上添加注解。
1.首先在pom文件中添加依赖
<!--JSR-303依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
2.常用注解
@Null 被注释的元素必须为null @NotNull 被注释的元素不能为null @AssertTrue 被注释的元素必须为true @AssertFalse 被注释的元素必须为false @Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值 @Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值 @DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值 @DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值 @Size(max,min) 被注释的元素的大小必须在指定的范围内。 @Digits(integer,fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内 @Past 被注释的元素必须是一个过去的日期 @Future 被注释的元素必须是一个将来的日期 @Pattern(value) 被注释的元素必须符合指定的正则表达式。 @Email 被注释的元素必须是电子邮件地址 @Length 被注释的字符串的大小必须在指定的范围内 @NotEmpty 被注释的字符串必须非空 @Range 被注释的元素必须在合适的范围内
3.在Student的类上添加相应的注解
package com.example.mybatisdemo.entity; import org.hibernate.validator.constraints.Range; import org.springframework.format.annotation.DateTimeFormat; import javax.validation.constraints.*; import java.util.Date; public class Student { @NotNull(message = "id不能为空") private Integer id; @Size(min = 2,max = 8,message = "姓名长度要求2到8之间") private String name; @Size(max=30,message = "地址长度不能超过30") private String address; @Email(message = "邮箱格式错误") private String email; @Past(message = "日期错误")//只能是过去的日期 @DateTimeFormat(pattern = "yyyy-MM-dd") private Date birthday; @DecimalMin(value = "0.1")//最小值为0.1 @DecimalMax(value = "100")//最大值为100 private double score; @Range(min = 1,max = 150,message = "年龄必须为1-150之间") private int age; }
4.创建控制器
在com.example.mybatisdemo.controller包下,新建ValidateController类。代码如下:
package com.example.mybatisdemo.controller; import com.example.mybatisdemo.entity.Student; import org.springframework.stereotype.Controller; import org.springframework.validation.Errors; import org.springframework.validation.FieldError; import org.springframework.validation.ObjectError; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import javax.validation.Valid; import java.util.HashMap; import java.util.List; import java.util.Map; @Controller public class ValidateController { //返回前端页面 @RequestMapping(value = "/datacheck/validateview",method = RequestMethod.GET) public String getValidateView(){ return "/datacheck/validateview"; } @RequestMapping(value = "/datacheck/validatedata",method = RequestMethod.POST) @ResponseBody public Map<String,Object> validateData(@Valid @RequestBody Student stu, Errors errors){ Map<String,Object> errMap=new HashMap<>(); //获取错误列表 List<ObjectError> oes=errors.getAllErrors(); for (ObjectError oe : oes) { String key=null; String message=null; if(oe instanceof FieldError){ FieldError fe=(FieldError)oe; key=fe.getField();//获取错误验证字段名 }else{ key=oe.getObjectName();//获取验证对象名称 } message=oe.getDefaultMessage(); errMap.put(key,message); } return errMap; } }
注意:必须在需要验证的参数之前加上注解"@valid",否则不会验证。该注解表示启动验证机制,Spring启用JSR-303验证机制后,会自动将最后的验证结果放入Errors对象中,将数据返回给前端后,前端就可以得到相关验证的信息。
5.创建前端页面
在resources/templates/datacheck目录下,新建validateview.html文件,页面内容如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>数据验证</title> </head> <body> <button id="btn">数据验证</button> <script src="/jquery.js" type="text/javascript"></script> <script> function sendMsg(){ var param={}; param["id"]=1; param["name"]="张三丰"; param["address"]="武当山"; param["email"]="[email protected]"; param["birthday"]="1990-10-21"; param["score"]=98.5; param["age"]=30; var jsondata=JSON.stringify(param); console.log(jsondata); $.ajax({ type:'POST', url:'/datacheck/validatedata', data:jsondata, async:false, contentType:'application/json', success:function(data){ alert("成功"+data); }, error:function(data){ alert("错误"+data); } }) } </script> </body> </html>
如果发送错误的数据,例如,将score更改为9898.9,age修改为300,则返回的结果是:
3.4 模型绑定
模型绑定指的是通过数据模型为视图绑定数据。本实例采用上例数据验证中的模型类Student。
3.4.1 创建控制器
在controller包下的DemoController控制器类中,添加如下代码:
@RequestMapping(value = "/demo/modelbind",method = RequestMethod.GET) public String studentModel(Model model){ Student stu=new Student(); stu.setId(1); stu.setName("张三丰"); stu.setAddress("武当山"); stu.setAge(108); stu.setBirthday(new Date()); stu.setEmail("[email protected]"); stu.setScore(89.5); model.addAttribute("stu",stu); model.addAttribute("msg","Hello"); return "/demo/model1"; }
3.4.2 创建视图页
视图页采用了 前端视图引擎。需要注意的是
<html lang="en" xmlns:th="http://www.thymeleaf.org"> <
代码如下:
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>模型绑定1</title> </head> <body> <table> <tr> <td>编号:</td> <td th:text="${stu.id}"></td> </tr> <tr> <td>姓名:</td> <td th:text="${stu.name}"></td> </tr> <tr> <td>地址:</td> <td th:text="${stu.address}"></td> </tr> <tr> <td>年龄:</td> <td th:text="${stu.age}"></td> </tr> <tr> <td>出生日期:</td> <td th:text="${stu.birthday}"></td> </tr> <tr> <td>电子邮件:</td> <td th:text="${stu.email}"></td> </tr> <tr> <td>武术成绩:</td> <td th:text="${stu.score}"></td> </tr> </table> </body> </html>
启动程序运行结果如下: