简介
项目中只要在Java Bean上放一些校验注解,就可以实现校验支持,杜绝通篇 if else 参数判断,而且这个校验是支持group的概念的,对于不同的group生效的校验不一样。这个很有用,因为对于增删改查等不同的操作,需要执行的校验本来就是不一样的。
常用注解解析:
-
@AssertFalse
可以为null,如果不为null的话必须为false -
@AssertTrue
可以为null,如果不为null的话必须为true -
@DecimalMax
设置不能超过最大值 -
@DecimalMin
设置不能超过最小值 -
@Digits
设置必须是数字且数字整数的位数和小数的位数必须在指定范围内 -
@Future
日期必须在当前日期的未来 -
@Past
日期必须在当前日期的过去 -
@Max
最大不得超过此最大值 -
@Min
最大不得小于此最小值 -
@NotNull
不能为null,可以是空 -
@Null
必须为null -
@Pattern
必须满足指定的正则表达式 -
@Size
集合、数组、map等的size()值必须在指定范围内 -
@Email
必须是email格式 -
@Length
长度必须在指定范围内 -
@NotBlank
字符串不能为null,字符串trim()后也不能等于“” -
@NotEmpty
不能为null,集合、数组、map等size()不能为0;字符串trim()后可以等于“” -
@Range
值必须在指定范围内 -
@URL
必须是一个URL
1. 依赖
pom.xml
<!-- Validation校验参数 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- hutool工具包 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.22</version>
</dependency>
2. 普通校验
- 我们在需要校验的Controller类上加
@Validated
IndexController
@RestController
@Validated
@Slf4j
public class IndexController {
@GetMapping("/test1")
public ResponseResult<String> test1(@NotBlank(message = "用户名不能为空") String name,
@NotNull(message = "用户名id不能为空") Long userId) {
log.info("参数为:{},{}", name, userId);
return ResponseResult.ok();
}
}
3. 实体校验
- 在实体中添加限制注解
@Data
@Accessors(chain = true)
public class UserVo {
@NotBlank(message = "用户名称不能为空")
private String name;
@NotNull(message = "编号不能为空")
@Max(value = 999, message = "编号需小于1000")
@Min(value = 0, message = "编号需大于0")
private Integer number;
@NotNull(message = "邮箱不能为空")
private String email;
@Length(message = "手机号不合法")
private String phone;
}
IndexController
- 在参数实体前加
@Validated
@RestController
@Validated
@Slf4j
public class IndexController {
@GetMapping("/test1")
public ResponseResult<String> test1(@NotBlank(message = "用户名不能为空") String name,
@NotNull(message = "用户名id不能为空") Long userId) {
log.info("参数为:{},{}", name, userId);
return ResponseResult.ok();
}
@GetMapping("/test2")
public ResponseResult<String> test2(@Validated UserVo userVo) {
log.info("参数为:{}", JSON.toJSONString(userVo));
return ResponseResult.ok();
}
}
4. 异常捕获
- 定义统一响应体
@Data
@Accessors(chain = true)
public class ResponseResult<T> implements Serializable {
private static final long serialVersionUID = -1L;
private Integer code;
private String message;
private T data;
public ResponseResult(Integer code, String message, T data) {
super();
this.code = code;
this.message = message;
this.data = data;
}
private static <T> ResponseResult<T> build(Integer code, String message, T data) {
return new ResponseResult<>(code, message, data);
}
public static <T> ResponseResult<T> ok() {
return new ResponseResult<>(RespCode.OK.code, RespCode.OK.message, null);
}
public static <T> ResponseResult<T> ok(T data) {
return build(RespCode.OK.code, RespCode.OK.message, data);
}
private static <T> ResponseResult<T> ok(String message) {
return build(RespCode.OK.code, message, null);
}
public static <T> ResponseResult<T> fail() {
return fail(RespCode.ERROR.message);
}
public static <T> ResponseResult<T> fail(String message) {
return fail(RespCode.ERROR, message);
}
public static <T> ResponseResult<T> fail(RespCode respCode) {
return build(respCode.code, respCode.message, null);
}
public static <T> ResponseResult<T> fail(RespCode respCode, String message) {
return build(respCode.code, message, null);
}
public enum RespCode {
/**
* 业务码
*/
OK(20000, "请求成功"),
MY_ERROR(20433, "自定义异常"),
UNAUTHORIZED(20401, "未授权"),
LOGIN_FAIL(20402, "账号或密码错误"),
ERROR(20400, "未知异常");
RespCode(int code, String message) {
this.code = code;
this.message = message;
}
private final int code;
private final String message;
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
}
}
- 全局异常捕获
/**
* 描述:全局统一异常处理
*
* @author ding
*/
@Slf4j
@RestControllerAdvice
public class ExceptionHandlerAdvice {
/**
* 参数验证异常
*/
@ExceptionHandler(value = {BindException.class})
public ResponseResult<String> handleMethodArgumentNotValidException(BindException e) {
e.printStackTrace();
String errorMsg = Objects.requireNonNull(e.getBindingResult().getFieldError()).getDefaultMessage();
if (!StrUtil.isBlank(errorMsg)) {
return ResponseResult.fail(errorMsg);
}
return ResponseResult.fail(e.getMessage());
}
/**
* Validation参数异常
*/
@ExceptionHandler(value = {ValidationException.class})
public ResponseResult<String> constraintViolationException(ValidationException e) {
e.printStackTrace();
if (e instanceof ConstraintViolationException) {
ConstraintViolationException err = (ConstraintViolationException) e;
ConstraintViolation<?> constraintViolation = err.getConstraintViolations().stream().findFirst().get();
String messageTemplate = constraintViolation.getMessageTemplate();
if (!StrUtil.isBlank(messageTemplate)) {
return ResponseResult.fail(messageTemplate);
}
}
return ResponseResult.fail(e.getMessage());
}
/**
* 异常处理
*/
@ExceptionHandler(value = Exception.class)
public ResponseResult<String> defaultException(Exception e) {
e.printStackTrace();
if (e instanceof NullPointerException) {
return ResponseResult.fail("空指针异常");
}
if (e instanceof HttpRequestMethodNotSupportedException) {
return ResponseResult.fail(e.getMessage());
}
return ResponseResult.fail();
}
}
5. 实战效果
-
访问接口
test1
-
访问接口
test2
6. 源码分享
- Springboot、SpringCloud各种常用框架使用案例,完善的文档,致力于让开发者快速搭建基础环境并让应用跑起来,并提供丰富的使用示例供使用者参考,快速上手。
- 项目源码github地址
- 项目源码国内gitee地址