相关依赖
如果开发普通 Java 程序的的话,你需要可能需要像下面这样依赖:
<dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>6.0.9.Final</version> </dependency> <dependency> <groupId>javax.el</groupId> <artifactId>javax.el-api</artifactId> <version>3.0.0</version> </dependency> <dependency> <groupId>org.glassfish.web</groupId> <artifactId>javax.el</artifactId> <version>2.2.6</version> </dependency>
实体类
package com.test.valid.entity; import javax.validation.constraints.Email; import javax.validation.constraints.NotNull; import javax.validation.constraints.Pattern; import javax.validation.constraints.Size; public class Person { @NotNull(message = "id字段不能为空") private String id; @Size(max = 20) @NotNull(message = "name字段不能为空") private String name; @Pattern(regexp = "((^Man$|^Woman$|^UGM$))",message = "sex字段只能是Man、Woman、UGM") @NotNull(message = "sex字段不能为空") private String sex; @Email(message = "email格式不正确") @NotNull(message = "email不能为空") private String email; public Person() { } public Person(String id, String name, String sex, String email) { this.id = id; this.name = name; this.sex = sex; this.email = email; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } }
JSR提供的校验注解:
@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(regex=,flag=)
被注释的元素必须符合指定的正则表达式
Hibernate Validator提供的校验注解:
@NotBlank(message =)
验证字符串非null,且长度必须大于0@Email
被注释的元素必须是电子邮箱地址@Length(min=,max=)
被注释的字符串的大小必须在指定的范围内@NotEmpty
被注释的字符串的必须非空@Range(min=,max=,message=)
被注释的元素必须在合适的范围内
验证Controller的输入
验证请求体(RequestBody)
我们在需要验证的参数上加上了@Valid
注解,如果验证失败,它将抛出MethodArgumentNotValidException
。默认情况下,Spring会将此异常转换为HTTP Status 400(错误请求)。
1 package com.test.valid.controller; 2 3 import com.test.valid.entity.Person; 4 import org.springframework.http.ResponseEntity; 5 import org.springframework.validation.annotation.Validated; 6 import org.springframework.web.bind.annotation.*; 7 8 import javax.validation.Valid; 9 import javax.validation.constraints.Max; 10 11 @Validated 12 @RestController 13 @RequestMapping("/valid") 14 public class PersonController { 15 16 @PostMapping("/person") 17 public ResponseEntity<Person> getPerson(@Valid Person person) { 18 return ResponseEntity.ok().body(person); 19 } 20 21 @GetMapping("/person/{id}") 22 public ResponseEntity<Integer> getPersonByID(@Valid @PathVariable("id") @Max(value = 5,message = "超过 id 的范围了") Integer id) { 23 return ResponseEntity.ok().body(id); 24 } 25 }
测试验证:
{ "timestamp": "2019-10-25T03:05:15.018+0000", "status": 400, "error": "Bad Request", "errors": [ { "codes": [ "Email.person.email", "Email.email", "Email.java.lang.String", "Email" ], "arguments": [ { "codes": [ "person.email", "email" ], "arguments": null, "defaultMessage": "email", "code": "email" }, [], { "defaultMessage": ".*", "codes": [ ".*" ], "arguments": null } ], "defaultMessage": "email格式不正确", "objectName": "person", "field": "email", "rejectedValue": "123.com", "bindingFailure": false, "code": "Email" } ], "message": "Validation failed for object='person'. Error count: 1", "path": "/valid/person" }
验证请求参数(Path Variables 和 Request Parameters)
controller:
一定一定不要忘记在类上加上 Validated
注解了,这个参数可以告诉 Spring 去校验方法参数。
如上面的代码。
验证 Service 中的方法
我们还可以验证任何Spring组件的输入,而不是验证控制器级别的输入,我们可以使用@Validated
和@Valid
注释的组合来实现这一需求。
一定一定不要忘记在类上加上 Validated
注解了,这个参数可以告诉 Spring 去校验方法参数。
自定义 Validator
package com.test.valid; import javax.validation.Constraint; import javax.validation.Payload; import java.lang.annotation.*; @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = RegionValidator.class) @Documented public @interface Region { String message() default "Region 值不在可选范围内"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
package com.test.valid; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import java.util.HashSet; public class RegionValidator implements ConstraintValidator<Region, String> { public void initialize(Region constraint) { } public boolean isValid(String obj, ConstraintValidatorContext context) { HashSet<Object> regions = new HashSet<>(); regions.add("China"); regions.add("China-Taiwan"); regions.add("China-HongKong"); return regions.contains(obj); } }
@Region private String region;
{ "timestamp": "2019-10-25T03:20:28.459+0000", "status": 400, "error": "Bad Request", "errors": [ { "codes": [ "Region.person.region", "Region.region", "Region.java.lang.String", "Region" ], "arguments": [ { "codes": [ "person.region", "region" ], "arguments": null, "defaultMessage": "region", "code": "region" } ], "defaultMessage": "Region 值不在可选范围内", "objectName": "person", "field": "region", "rejectedValue": "China-shanghai", "bindingFailure": false, "code": "Region" } ], "message": "Validation failed for object='person'. Error count: 1", "path": "/valid/person" }