@Valid注解使用及扩展
一、@Vaild注解介绍
使用@Vaild注解可以简化入参的校验,配合统一异常实现简单快捷的入参校验,具体使用参照以下
二、@Vaild具体使用
1、引入jar包
如果你是springboot项目,此依赖内已经引入,无需再次引入
1 2 3 4 5
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.0.5.RELEASE</version> </dependency>
|
如果没有,将依赖jar包引入到自己的项目中,maven依赖如下
1 2 3 4 5 6 7 8 9 10
| <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>1.1.0.Final</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>5.3.5.Final</version> </dependency>
|
2、在入参请求类中添加限制注解
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.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.hibernate.validator.constraints.Length; import org.hibernate.validator.constraints.NotBlank; import org.hibernate.validator.constraints.Range;
import javax.validation.constraints.NotNull; import java.io.Serializable;
@Data @NoArgsConstructor @AllArgsConstructor public class UserReq implements Serializable { private Integer id; @NotBlank(message = "用户名不能为空") @Length(message = "用户名最大为{max}个字符", max = 20) private String username; @NotBlank(message = "密码不能为空") @Length(message = "密码长度限制为{min}-{max}", min = 8, max = 16) private String password; @NotNull(message = "性别不能为空") private Byte sex; @Range(message = "年龄范围为{min}-{max}", min = 0, max = 120) private Integer age;
}
|
3、控制器中使用@Vaild
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import com.alibaba.fastjson.JSON; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
@Slf4j @RestController @RequestMapping("/user/post") public class PostController {
@PostMapping("/create") public String createUser(@Valid @RequestBody UserReq req){ log.info(JSON.toJSONString(req)); return "成功"; }
}
|
4、请求进行测试
虽然拦截成功,但错误出参不知道所以然,一头雾水,需进行优化
三、优化出参
1、修改控制器
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
| import com.alibaba.fastjson.JSON; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
@Slf4j @RestController @RequestMapping("/user/post") public class PostController {
@PostMapping("/create") public String createUser(@Valid @RequestBody UserReq req, BindingResult result){ if(result.hasErrors()){ String message = result.getAllErrors().get(0).getDefaultMessage(); log.error(message); return message; } log.info(JSON.toJSONString(req)); return "成功"; }
}
|
2、请求进行测试
四、使用统一异常
1、创建统一异常捕获类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody;
@Slf4j @ControllerAdvice public class MyExceptionHandler { @ResponseBody @ExceptionHandler(Exception.class) public ResultData exceptionHandler(Exception exception){ log.error("统一异常", exception); if(exception instanceof MethodArgumentNotValidException){ MethodArgumentNotValidException ex = (MethodArgumentNotValidException) exception; String message = ex.getBindingResult().getAllErrors().get(0).getDefaultMessage(); return ResultData.getFailResult(message); } return ResultData.getFailResult("服务器繁忙,请稍后再试!"); } }
|
2、此时控制器不需要做额外处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import com.alibaba.fastjson.JSON; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
@Slf4j @RestController @RequestMapping("/user/post") public class PostController {
@PostMapping("/create") public String createUser(@Valid @RequestBody UserReq req){ log.info(JSON.toJSONString(req)); return "成功"; }
}
|
3、请求进行测试
五、验证注解
1、官方的验证注解
验证注解 |
说明 |
@Null |
只能为null |
@NotNull |
不能为null |
@NotEmpty |
不为null、不能为空字符串(字符串长度不为0、集合大小不为0) |
@NotBlank |
不为null、不能为空字符串,不同于@NotEmpty,@NotBlank会去掉空格再判断 |
@AssertFalse |
必须为false |
@AssertTrue |
必须为true |
@DecimalMax(value) |
必须为一个不大于指定值的数字 |
@DecimalMin(value) |
必须为一个不小于指定值的数字 |
@Max(value) |
必须为一个不大于指定值的数字 |
@Min(value) |
必须为一个不小于指定值的数字 |
@Digits(integer,fraction) |
必须为一个小数,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction |
@Future |
必须是一个将来的日期 |
@Past |
必须是一个过去的日期 |
@Pattern(value) |
必须符合指定的正则表达式 |
@Length(max,min) |
字符长度必须在min到max之间 |
@Email |
验证注解的元素值是Email |
2、自定义验证注解
1)定义注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import javax.validation.Constraint; import javax.validation.Payload; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;
@Constraint(validatedBy = {SexConstraintValidator.class}) @Target({ElementType.METHOD, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface SexConstraint { String message() default "性别有误,请确认"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
|
2)定义校验器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext;
public class SexConstraintValidator implements ConstraintValidator<SexConstraint, Byte> { @Override public void initialize(SexConstraint sexConstraint) { System.out.println("初始化信息"); } @Override public boolean isValid(Byte sex, ConstraintValidatorContext constraintValidatorContext) { if(sex==null) return false; if(sex!=0 && sex!=1 && sex!=2) return false; return true; } }
|
3)使用注解
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 com.banmoon.lol.config.annotation.SexConstraint; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.hibernate.validator.constraints.Length; import org.hibernate.validator.constraints.NotBlank; import org.hibernate.validator.constraints.Range;
import java.io.Serializable;
@Data @NoArgsConstructor @AllArgsConstructor public class UserReq implements Serializable { private Integer id; @NotBlank(message = "用户名不能为空") @Length(message = "用户名最大为{max}个字符", max = 20) private String username; @NotBlank(message = "密码不能为空") @Length(message = "密码长度限制为{min}-{max}", min = 8, max = 16) private String password; @SexConstraint private Byte sex; @Range(message = "年龄范围为{min}-{max}", min = 0, max = 120) private Integer age;
}
|
4)请求进行测试