大家好,欢迎来到IT知识分享网。
一、@Valid使用背景
在编写接口的时候,通常会进行参数的校验,一般方法就是if语句
的疯狂叠加,逻辑上是可以的,没什么问题,但是代码这样就很乱,感觉一团一样,而且不同的地方有些相似的校验还得重写,如下。
@PostMapping("/user") public String addUserInfo(@RequestBody User user) {
if (user.getName() == null || "".equals(user.getName()) {
...... } else if(user.getSex() == null || "".equals(user.getSex())) {
...... } }
二、@Valid 作用
- @Valid 的主要作用是用于数据效验,主要用法是:
- 在实体中的属性上,添加不同的注解(如下)来完成不同的校验。
- 在接口类中的接收数据参数中添加 @Valid 注解。
- 实体注解详解:
@NotEmpty
:元素值不为null且不为空(字符串长度不为0、集合大小不为0)@NotBlank
:验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的空格。@Null
:只能为null@NotNull
:不为null@Email
:验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式@AssertFalse
:必须为false@AssertTrue
:必须为true@DecimalMax(value)
:不大于指定值的数字DecimalMin(value)
:不小于指定值的数字@Digits(integer,fraction)
:一个小数,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction@Max(value)
:不大于指定值的数字@Min(value)
:不小于指定值的数字@Future
:必须是一个将来的日期(不包含现在)@FutureOrPresent
:必须是一个将来的日期(包含现在)@Past
:必须是一个过去的日期(不包含现在)@PastOrPresent
:必须是一个过去的日期(包含现在)@Pattern(value)
:符合指定的正则表达式@Size(max,min)
:限定字符长度在min到max之间@Positive
:数值是否是正数@PositiveOrZero
:数值是否是正数和0@Negative
:数值是否是负数@NegativeOrZero
:数值是否是负数和0
注意
- 实体类验证只是针对该实体,如果 该实体 存在 成员变量 为 实体类 ,则需要在该成员变量(假设你需要验证该实体内的变量)上加
@Valid 注解
。 - @Valid 对 Get 请求中接收的平面参数请求无效。
二、@Valid 用法(导错包不生效)
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
此包下的
import javax.validation.constraints
2.1、实体属性添加
1.单个实体
public class User {
@NotBlank(message = "用户名不为空") private String username; @NotBlank(message = "密码不为空") private String password; }
2.嵌套实体
public class User {
@NotBlank(message = "用户名不为空") private String username; @NotBlank(message = "密码不为空") private String password; @Valid //不加此注解,则不会校验 @NotNull(message = "用户住址不能为空") private Address address; }
public class Address {
@NotBlank(message = "地址详情不能为空") private String info; }
2.2、接口添加
@PostMapping("/user") public void addUserInfo(@RequestBody @Valid User user) {
}
2.3、全局异常捕获
@RestControllerAdvice @Order(Ordered.HIGHEST_PRECEDENCE)//最高优先级,防止有其他的全局异常捕获导致这个无法捕获 public class ExceptionAdvice {
@ExceptionHandler(value = {
MethodArgumentNotValidException.class}) public R handleValidException(MethodArgumentNotValidException m){
Map<String,String> errorMsg = m.getBindingResult.getFieldErrors().stream().collect(Collectors.toMap(FieldError::getField,FieldError::getDefaultMessage,(k1,k2) -> k1)); return R.FAILED("数据异常").setData(errorMsg); } }
三、分组
分组是在实体类验证中常用的一种技术,它允许你根据不同的场景对验证规则进行分组,从而在不同的情况下应用不同的验证规则。
@AllArgsConstructor @NoArgsConstructor @Data @Builder public class UserCopyVo {
@NotEmpty(groups = update.class, message = 'id不能为空') private String id; @NotEmpty() private String userName; private String avatar;//头像 public UserCopyVo(UserEntity user) {
this.userName = user.getUserName(); this.id = user.getUuid(); this.avatar = user.getAvatar(); } / * 设置分组 */ public interface add extends Default {
} public interface update extends Default {
} }
@ApiOperation(value = 'test', notes = 'test action') @PostMapping('/test') public String test(@Validated(UserCopyVo.update.class) @RequestBody UserCopyVo u) {
System.out.println(u); return 'success0000'; }
四、@Valid拓展
有的时候,我们发现@Valid
的一些注解无法满足我们的特殊开发需求,那就需要对其注解进行拓展了。
要拓展@Valid注解,可以按照以下步骤进行操作:
4.1、创建一个自定义的注解
用@Constraint
注解来定义这个自定义注解,并指定一个自定义的校验器类。
@Target({
ElementType.FIELD, ElementType.PARAMETER }) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = AnnotateValidator.class) public @interface Annotate{
String message() default "Invalid value"; Class<?>[] groups() default {
}; Class<? extends Payload>[] payload() default {
}; }
4.2、创建一个自定义的校验器类
创建自定义校验器类实现ConstraintValidator
接口,并重写initialize
和isValid
方法。
public class AnnotateValidator implements ConstraintValidator<Annotate, String> {
@Override public void initialize(Annotate annotation) {
// 初始化校验器,可以空着 } @Override public boolean isValid(String value, ConstraintValidatorContext context) {
// 执行自己的校验逻辑,返回布尔值即可 return value != null && value.startsWith("custom"); } }
CustomValidator
校验器类实现了ConstraintValidator<CustomValid, String>
接口,其中CustomValid
是自定义注解的类型,String
是要校验的值的类型。
4.3、测试
在需要校验的字段或方法参数上使用自定义的注解。
public class Test{
@CustomValid(message = "参数格式不对") private String customField; }
public class MyController {
@PostMapping("/myEndpoint") public void myEndpoint(@Valid @RequestBody Test myTest) {
// ... } }
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/135340.html