赵走x博客
网站访问量:151834
首页
书籍
软件
工具
古诗词
搜索
登录
32、使用MyBatis注解实现数据库操作
31、MyBaties使用XML配置文件实现数据库操作
30、Spring Boot构建MyBatis应用程序
29、MyBatis简介
28、实战:实现JdbcTemplate多数据源
27、使用JdbcTemplate操作数据库
26、JdbcTemplate入门
25、实战:实现Web API版本控制
24、使用Swagger生成Web API文档
23、Thymeleaf页面布局
22、Thymeleaf内置对象、内嵌变量
21、Thymeleaf内联
20、Thymeleaf语法
19、Thymeleaf表达式
18、Thymeleaf入门
17、全局异常处理
16、实战:实现优雅的数据返回
15、跳转指定页面
14、Spring Boot静态资源
13、Spring Boot数据转换配置
12、跨域访问
11、Web配置
10、过滤器
9、拦截器
8、数据验证
7、参数传递
6、URL映射
5、@ResponseBody
4、@RequestMapping
3、@Controller和@RestController
2、Web项目结构
1、spring-boot-starter-web介绍
8、数据验证
资源编号:551770
热度:104
8、数据验证
对于应用系统而言,任何客户端传入的数据都不是绝对安全有效的,这就要求我们在服务端接收到数据时也对数据的有效性进行验证,以确保传入的数据安全正确。接下来介绍Spring Boot是如何实现数据验证的。 4.4.1 Hibernate Validator简介 数据校验是Web开发中的重要部分,也是必须要考虑和面对的事情。应用系统必须通过某种手段来确保输入的数据从语义上来讲是正确的。 目前数据校验的规范、组件非常多,有JSR-303/JSR-349、Hibernate Validator、Spring Validation。下面就来捋一捋它们之间的关系。 JSR(Java Specification Request)规范是Java EE 6中的一项子规范,也叫作Bean Validation。它指定了一整套基于bean的验证API,通过标注给对象属性添加约束条件。 Hibernate Validator是对JSR规范的实现,并增加了一些其他校验注解,如@Email、@Length、@Range等。 Spring Validation是Spring为了给开发者提供便捷,对Hibernate Validator进行了二次封装。 同时,Spring Validation在SpringMVC模块中添加了自动校验,并将校验信息封装进了特定的类中。 所以,JSR定义了数据验证规范,而Hibernate Validator则是基于JSR规范,实现了各种数据验证的注解以及一些附加的约束注解。Spring Validation则是对Hibernate Validator的封装整合。 JSR和Hibernate Validator中的常用注解如表4-2所示。  表4-2中包含了Hibernate Validator实现的JSR-303定义的验证注解和Hibernate Validator自己定义的验证注解,同时也支持自定义约束注解。所有的注解都包含code和message这两个属性。 Message定义数据校验不通过时的错误提示信息。 code定义错误的类型。 Spring Boot是从Spring发展而来的,所以自然支持Hibernate Validator和Spring Validation两种方式,默认使用的是Hibernate Validator组件。 # 二、数据校验 使用Hibernate Validator校验数据需要定义一个接收的数据模型,使用注解的形式描述字段校验的规则。下面以User对象为例演示如何使用Hibernate Validator校验数据。 ### 1. JavaBean参数校验 Post请求参数较多时,可以在对应的数据模型(Java Bean)中进行数据校验,通过注解来指定字段校验的规则。 下面以具体的实例来进行演示。 首先,创建Java Bean实体类: ``` public class User { @NotBlank(message = "姓名不允许为空!") @Length(min = 2,max = 10,message = "姓名长度错误,姓名长度2-10!") private String name; @NotNull(message = "年龄不能为空!") @Min(18) private int age; @NotBlank(message = "地址不能为空!") private String address; @Pattern(regexp = "^((13[0-9])|(14[5,7,9])|(15([0-3]|[5-9]))|(166)|(17[0,1,3,5,6,7,8])|(18[0-9])|(19[8|9]))\\d{8}$", message = "手机号格式错误") private String phone; @Email(message = "邮箱格式错误") private String email; // 省略get和set方法 } ``` 在上面的示例中,每个注解中的属性message是数据校验不通过时要给出的提示信息,如@Email(message="邮件格式错误"),当邮件格式校验不通过时,提示邮件格式错误。 然后,添加数据校验方法: ``` @PostMapping(path = "/check") public String check(@RequestBody @Valid User user, BindingResult result) { String name = user.getName(); if(result.hasErrors()) { List
list = result.getAllErrors(); for (ObjectError error : list) { System.out.println(error.getCode()+ "-" + error.getDefaultMessage()); } } return name; } ``` 在上面的示例中,在@RequestBody注解后面添加了@Valid注解,然后在后面添加了BindingResult返回验证结果,BindingResult是验证不通过时的结果集合。 注意,BindingResult必须跟在被校验参数之后,若被校验参数之后没有BindingResult对象,则会抛出BindException。 最后,运行验证。 启动项目,在postman中请求/user/check接口,后台输出了数据验证的结果: ``` Length-密码长度错误,密码长度6-20! Min-最小不能小于18 Length-姓名长度错误,姓名长度2-10! ``` 通过上面的输出可以看到,应用系统对传入的数据进行了校验,同时也返回了对应的数据校验结果。 ### 2. URL参数校验 一般GET请求都是在URL中传入参数。对于这种情况,可以直接通过注解来指定参数的校验规则。下面通过实例进行演示。 ``` @Validated public class UserController { @RequestMapping("/query") public String query(@Length(min = 2, max = 10, message = "姓名长度错误,姓名长度2-10!") @RequestParam(name = "name", required = true) String name, @Min(value = 1, message = "年龄最小只能1") @Max(value = 99, message = "年龄最大只能99") @RequestParam(name = "age", required = true) int age){ System.out.println(name + "," + age); return name + "," + age; } } ``` 在上面的示例中,使用@Range、@Min、@Max等注解对URL中传入的参数进行校验。需要注意的是,使用@Valid注解是无效的,需要在方法所在的控制器上添加@Validated注解来使得验证生效。 ### 3. JavaBean对象级联校验 对于JavaBean对象中的普通属性字段,我们可以直接使用注解进行数据校验,那如果是关联对象呢?其实也很简单,在属性上添加@Valid注解就可以作为属性对象的内部属性进行验证(验证User对象,可以验证UserDetail的字段)。示例代码如下: ``` public class User { @Size(min = 3,max = 5,message = "list的Size在[3,5]") private List
list; @NotNull @Valid private Demo3 demo3; } public class UserDetail { @Length(min = 5, max = 17, message = "length长度在[5,17]之间") private String extField; } ``` 在上面的示例中,在属性上添加@Valid就可以对User中的关联对象UserDetail的字段进行数据校验。 ### 4. 分组校验 在不同情况下,可能对JavaBean对象的数据校验规则有所不同,有时需要根据数据状态对JavaBean中的某些属性字段进行单独验证。这时就可以使用分组校验功能,即根据状态启用一组约束。Hibernate Validator的注解提供了groups参数,用于指定分组,如果没有指定groups参数,则默认属于javax.validation.groups.Default分组。 下面通过示例演示分组校验。 首先,创建分组GroupA和GroupB,示例代码如下: ``` public interface GroupA { } public interface GroupB { } ``` 在上面的示例中,我们定义了GroupA和GroupB两个接口作为两个校验规则的分组。 然后,创建实体类Person,并在相关的字段中定义校验分组规则,示例代码如下: ``` public class User { @NotBlank(message = "userId不能为空",groups = {GroupA.class}) /**用户id*/ private Integer userId; @NotBlank(message = "用户名不能为空",groups = {GroupA.class}) /**用户id*/ private String name; @Length(min = 30,max = 40,message = "必须在[30,40]",groups = {GroupB.class}) @Length(min = 20,max = 30,message = "必须在[20,30]",groups = {GroupA.class}) /**用户名*/ private int age; } ``` 在上面的示例中,userName字段定义了GroupA和GroupB两个分组校验规则。GroupA的校验规则为年龄在20~30,GroupB的校验规则为年龄在30~40。 最后,使用校验分组: ``` @RequestMapping("/save") public String save(@RequestBody @Validated({GroupA.class,Default.class}) Person person, BindingResult result){ System.out.println(JSON.toJSONString(result.getAllErrors())); return "success"; } ``` 在上面的示例中,在@Validated注解中增加了{GroupA.class,Default.class}参数,表示对于定义了分组校验的字段使用GroupA校验规则,其他字段使用默认规则。4.4.3 自定义校验Hibernate Validator支持自定义校验规则。通过自定义校验规则,可以实现一些复杂、特殊的数据验证功能。下面通过示例演示如何创建和使用自定义验证规则。 # 三、自定义校验 Hibernate Validator支持自定义校验规则。通过自定义校验规则,可以实现一些复杂、特殊的数据验证功能。下面通过示例演示如何创建和使用自定义验证规则。 ### 1. 声明一个自定义校验注解 首先,定义新的校验注解@CustomAgeValidator,示例代码如下: ``` @Min(value = 18,message = "年龄最小不能小于18") @Max(value = 120,message = "年龄最大不能超过120") @Constraint(validatedBy = {}) //不指定校验器 @Documented @Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface CustomAgeValidator { String message() default "年龄大小必须大于18并且小于120"; Class>[] groups() default {}; Class extends Payload>[] payload() default {}; } ``` 在上面的示例中,我们创建了CustomAgeValidator自定义注解,用于自定义年龄的数据校验规则。 ### 2. 使用自定义校验注解 创建自定义校验注解CustomAgeValidator之后,在User的age属性上使用自定义组合注解,示例代码如下: ``` @public class User { @NotBlank(message = "姓名不允许为空!") @Length(min = 2,max = 10,message = "姓名长度错误,姓名长度2-10!") private String name; @CustomAgeValidator private int age; @NotBlank(message = "地址不能为空!") private String address; @Pattern(regexp = "^((13[0-9])|(14[5,7,9])|(15([0-3]|[5-9]))|(166)|(17[0,1,3,5,6,7,8])|(18[0-9])|(19[8|9]))\\d{8}$", message = "手机号格式错误") private String phone; @Email(message = "邮箱格式错误") private String email; // 省略get和set } ``` 在上面的示例中,我们在需要做特殊校验的age字段上添加@CustomAgeValidator自定义注解,这样age字段就会使用我们自定义的校验规则。