在真实的开发中,我们经常会遇到需要对数据进行校验的业务,那么本篇文章对此进行总结。暂时总结三种方法,大家可以根据需要选择使用。
一、Java Bean Validation 验证 【校验处理】一、Java Bean Validation验证
二、SpringBoot Validate 统一处理 【校验处理】二、SpringBoot Validate 统一处理
三、Spring Validation 校验处理 【校验处理】三、Spring Validation 校验处理
本篇文章采用第三种Spring Validation的验证方式。话不多说,直接上代码。
1. 背景
Java API规范(JSR303)定义了Bean校验的标准validation-api,但没有提供实现。hibernate validation是对这个规范的实现,并增加了校验注解如@Email、@Length等。Spring Validation是对hibernate validation的二次封装,用于支持spring mvc参数自动校验。
如果校验失败,会抛出MethodArgumentNotValidException异常,Spring默认会将其转为400(Bad Request)请求。
2. 依赖
<!--引入依赖--> <!--如果spring-boot版本小于2.3.x,spring-boot-starter-web会自动传入hibernate-validator依赖。--> <!--如果spring-boot版本大于2.3.x,则需要手动引入依赖 --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>6.0.1.Final</version> </dependency>
3. 校验处理
3.1 简单处理
3.1.1 代码实现
@Data public class Test { @Length(min = 1,max = 5,message = "姓名长度应该在1-5之间") private String name; @Range(min = 1,max = 100,message = "年龄应该在1-100之间") private Integer age; } @ApiOperation("测试") @PostMapping("/test") public R test(@RequestBody @Valid Test test){ return R.ok(); } @ApiOperation("测试") @PostMapping("/test") public R test(@RequestBody @Validated Test test){ return R.ok(); } { "name":"张三张三张三", "age":"0" }
3.1.2 效果
3.1.3 注意
-
分组:
@Validated:提供了一个分组功能,可以在入参验证时,根据不同的分组采用不同的验证机制,这个网上也有资料,不详述。
@Valid:作为标准JSR-303规范,还没有吸收分组的功能。
-
注解位置:
@Validated:可以用在类型、方法和方法参数上。但是不能用在成员属性(字段)上
@Valid:可以用在方法、构造函数、方法参数和成员属性(字段)上
-
嵌套验证:
@Valid //嵌套验证必须使用@Valid
private List< Student> student;
-
3.2 嵌套校验
嵌套校验一定要在要校验的对象类型的属性/list上使用@Valid注解:
3.2.1 代码实现
@Data public class Test { @Length(min = 1,max = 5,message = "姓名长度应该在1-5之间") private String name; @Range(min = 1,max = 100,message = "年龄应该在1-100之间") private Integer age; @Valid private Test2 test; @Valid private List<Test2> test2; } @Data public class Test2 { @Max(value = 1) private Integer sex; @Length(min = 0,max = 2) private String jobname; } @ApiOperation("测试") @PostMapping("/test") public R test(@RequestBody @Validated Test test){ return R.ok(); } { "name":"张三张三张三", "age":"0", "test":{ "sex":"11", "jobname":"李四李四李四" }, "test2":[{ "sex":"222", "jobname":"王五王五王五王五" },{ "sex":"3333", "jobname":"赵六赵六赵六赵六" }] }
3.2.2 结果
3.3 分组校验
在实际项目中,可能多个方法需要使用同一个DTO类来接收参数,而不同方法的校验规则很可能是不一样的。这个时候,简单地在DTO类的字段上加约束注解无法解决这个问题。因此,spring-validation支持了分组校验的功能,专门用来解决这类问题。
3.3.1 代码实现
//这里定义四种规则 public class GroupValidator { public interface Arules{} public interface Brules{} public interface Crules{} public interface Drules{} } //实体类属性注解上加上分组标志 @Data public class Test { @Length(min = 1,max = 5,groups = {GroupValidator.Arules.class, GroupValidator.Brules.class}) private String name; @Range(min = 1,max = 100,groups = {GroupValidator.Crules.class, GroupValidator.Drules.class}) private Integer age; } //参数列表里指定要校验的分组 @PostMapping("/test") public R test(@RequestBody @Validated(GroupValidator.Arules.class) Test test){ return R.ok(); } //json { "name":"张三张三张三", "age":"0" }
3.3.2 结果
3.4 自定义校验
3.4.1 代码实现
//首先自定义一个注解 @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER}) @Retention(RUNTIME) @Documented @Constraint(validatedBy = {TestValidator.class}) public @interface TestAnnotation { // 默认错误消息 String message() default "此值只能为1"; // 分组 Class<?>[] groups() default {}; // 负载 Class<? extends Payload>[] payload() default {}; } //对这个注解写验证的逻辑 public class TestValidator implements ConstraintValidator<TestAnnotation, String> { @Override public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) { if(!"1".equals(s)){ return false; }else{ return true; } } } //实体类中使用这个注解 @Data public class Test { //@Length(min = 1,max = 5) @TestAnnotation private String name; @Range(min = 1,max = 100) private Integer age; } //验证 @PostMapping("/test") public R test(@RequestBody @Validated Test test){ return R.ok(); } //传入json { "name":"张三张三张三", "age":"0" }
3.4.2 结果
持续更新!!!