SpringBoot使用HibernateValidator实现参数校验
Created|Updated
|Word Count:896|Post Views:
Hibernate Validator
依赖
Hibernate Validator是Spring Boot集成的参数校验框架;
但从Spring Boot 2.3版本开始默认移除了校验功能,如果想要开启的话需要添加如下依赖。
1 2 3 4
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
|
常用注解
- @Null:被注释的属性必须为null;
- @NotNull:被注释的属性不能为null;
- @AssertTrue:被注释的属性必须为true;
- @AssertFalse:被注释的属性必须为false;
- @Min:被注释的属性必须大于等于其value值;
- @Max:被注释的属性必须小于等于其value值;
- @Size:被注释的属性必须在其min和max值之间;
- @Pattern:被注释的属性必须符合其regexp所定义的正则表达式;
- @NotBlank:被注释的字符串不能为空字符串;
- @NotEmpty:被注释的属性不能为空;
- @Email:被注释的属性必须符合邮箱格式。
- @PastOrPresent:必须是过去或现在的时间
使用注解实现校验
pojo类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| @Data @AllArgsConstructor @NoArgsConstructor public class Account { private int id; @NotNull(message = "用户名不能为空") private String username; @NotNull(message = "密码不能为空") private String password; @NotNull(message = "角色不能为空") private String role; private Date createTime; private boolean enable;
public Account(String username, String password, String role, Date createTime, boolean enable) { this.username = username; this.password = password; this.role = role; this.createTime = createTime; this.enable = enable; } }
|
controller类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @RestController public class AccountController {
@Autowired private JwtUtil jwtUtil; @Autowired AccountService accountService;
@PostMapping("register") public Account register(@Valid @RequestBody Account account) { return accountService.register(account); } }
|
当传入参数不符合参数规范时,会抛出异常。在这个框架中有个默认的异常处理类DefaultHandlerExceptionResolver。
当传入的json中的username为空,异常信息:
2021-09-10 15:40:25.749 WARN 22228 — [nio-8080-exec-2] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public com.example.demo.pojo.Account com.example.demo.controller.AccountController.register(com.example.demo.pojo.Account): [Field error in object ‘account’ on field ‘username’: rejected value [null]; codes [NotNull.account.username,NotNull.username,NotNull.java.lang.String,NotNull]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [account.username,username]; arguments []; default message [username]]; default message [用户名不能为空]] ]
自定义异常处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @RestControllerAdvice @Slf4j public class GlobalExceptionHandler { @ExceptionHandler(MethodArgumentNotValidException.class) public Result<ResultCode> handlerValidationException(MethodArgumentNotValidException e) { log.error("参数校验异常", e); String messages = e.getBindingResult().getAllErrors().stream() .map(ObjectError::getDefaultMessage) .collect(Collectors.joining("\n")); return Result.failure(messages); } }
|
级联校验
1 2 3 4 5 6 7 8 9 10 11 12
| public class Employee{ @Null private Integer id; @NotNull private String name; @Valid private Department department; @Valid private List<Group> groups; }
|
在级联的属性上要加@Valid
在其他地方实现校验
@Valid加在Controller中,抛出的异常是MethodArgumentNotValidException
而加在其他地方,抛出的异常却是ConstraintViolationException
在做全局异常处理的时候要注意区别。
分组校验
例如上面的Employee类,我们想要它在不同的情况下有不同的校验规则,这时就需要用到分组校验
1、创建一个分组类,里面添加一些内部接口
1 2 3 4 5 6 7 8 9 10
| public class ValidationGroups { public interface insertNeed { }
public interface selectNeed { }
public interface updateNeed { } }
|
2、为不同的情况添加不同的分组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class Employee{ @Null(groups = ValidationGroups.insertNeed.class) @NotNull(groups = ValidationGroups.selectNeed.class) private Integer id; @NotNull(groups = ValidationGroups.insertNeed.class,ValidationGroups.selectNeed.class) private String name; @Valid(groups = ValidationGroups.insertNeed.class) private Department department; @Valid(groups = ValidationGroups.insertNeed.class) private List<Group> groups; }
|
3、在需要校验时用@Validated标识需要使用的分组规则
1 2 3 4 5 6 7 8
| @RestController public class AccountController {
@PostMapping("test") public void test(@RequestBody @Validated(ValidationGroups.insertNeed.class) Employee Employee) { ... } }
|