项目中经常需要对请求参数进行校验。不仅麻烦,冗长的 if 判断语句使代码显得十分臃肿。本文介绍使用 @Valid
注解方式配置校验,直接定义在字段处,方便又简洁。 javax.validation.Valid
底层是通过AOP技术,对请求拦截,若请求参数不满足要求,则直接抛出异常,统一处理后响应给前端。
用法
引入依赖
@Valid
相关注解主要涉及到hibernate-validator
和 validation-api
两个依赖。springboot项目只要引入 spring-boot-starter-web
依赖即可,hibernate-validator
和 validation-api
依赖已经包含在内
1 2 3 4
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
|
具体依赖关系如下:
![](/image/image-20220801164730115.png)
标示要校验的参数
例如要对userVO对象做参数校验,则在userVO前加上 javax.validation.Valid
注解,表示开启对该参数校验
1 2 3 4 5 6 7 8 9 10
| import javax.validation.Valid;
@RestController public class ValidController {
@PostMapping(value = "/ice/check", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) public CommonResponse checkUser(@RequestBody @Valid UserVO userVO){ return new CommonResponse("200", "OK"); } }
|
配置字段校验
@Valid
只是表示开启校验,还需要在具体字段上加上校验内容。
相关注解都在org.hibernate.validator.constraints
和 javax.validation.constraints
包下。如@NotBlank
表示对应字段不能为空。其中参数message
表示异常信息,不填则使用默认异常信息。
如果需要对成员变量内部的字段进行校验(如education内的字段),则除了要在Education内配置注解,还要在education上加上@Valid
,形成递归校验
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| import lombok.Data;
import org.hibernate.validator.constraints.Email; import org.hibernate.validator.constraints.NotBlank;
import javax.validation.constraints.Max; import javax.validation.constraints.Min; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size;
@Data public class UserVO {
@NotBlank(message = "姓名不能为空") private String name;
@NotNull(message = "年龄不能为空") @Max(value = 35, message = "年龄不超过45") @Min(value = 23, message = "年龄不低于18") private Integer age;
@NotBlank(message = "密码不能为空") @Size(min = 8, max = 12, message = "密码长度要在8-12之间") private String password;
@Email @NotBlank(message = "邮箱不能为空") private String email; @Valid private Education education; }
|
常用注解说明
注解 |
作用 |
属于包 |
Email |
校验邮箱格式 |
org.hibernate.validator.constraints |
NotBlank |
字符串不能为空或不填 |
org.hibernate.validator.constraints |
Max |
整型最大不超过 |
javax.validation.constraints |
Min |
整型最小不超过 |
javax.validation.constraints |
NotNull |
整型不能为null |
javax.validation.constraints |
Size |
字符串长度 |
javax.validation.constraints |
全局异常处理
都配置好后,解析到不满足要求的字段,会抛出 MethodArgumentNotValidException
异常。还需要统一处理,响应给前端。
创建 CommonExceptionHandler
类,用@RestControllerAdvice
注解标注,表示这是一个处理全局控制器的配置类。
![@RestControllerAdvice包含@ResponseBody和@ControllerAdvice](/image/image-20220823174713599.png)
![@ControllerAdvice本质上是一个@Component](/image/image-20220823174913637.png)
在方法上用 @ExceptionHandler
注解标注,并指定要处理的异常。应用启动后,这些方法会被作用在@REquestMapping
注解的方法上(即接口方法)。
配置代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| import org.springframework.context.support.DefaultMessageSourceResolvable; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice public class CommonExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity<CommonResponse> methodArgumentNotValidHandler(MethodArgumentNotValidException e) { String message = e.getBindingResult().getAllErrors().stream() .map(DefaultMessageSourceResolvable::getDefaultMessage) .collect(Collectors.joining(",")); CommonResponse resp = new CommonResponse(); resp.setResultCode("-1"); resp.setReturnMessage(message); resp.setData(new HashMap<>()); return new ResponseEntity<>(resp, HttpStatus.OK); } }
|
验证
![接口成功返回了参数异常信息](/image/image-20220803103256086.png)