java springboot 数据校验 @Validated 与 @Valid 区别

4 篇文章 0 订阅
3 篇文章 0 订阅

@Validated 与 @Valid 区别

  • Spring Validation验证框架对参数的验证机制提供了@Validated(Spring的JSR-303规范,是标准JSR-303的一个变种),Javax提供了@Valid(标准JSR-303规范),配合BindingResult可以直接提供参数验证结果。
  • @Valid 属于Javax.validation包下,是jdk给提供的,是使用Hibernate validation的时候使用(java的JSR303声明了@Valid这类接口,而Hibernate-validator对其进行了实现)
  • @Validated 是org.springframework.validation.annotation包下的,是spring提供的,是只用Spring validator校验机制使用

在检验Controller的入参是否符合规范时,使用@Validated或者@Valid在基本验证功能上没有太多区别。但是在分组、注解地方、嵌套验证等功能上两个有所不同:

首先导入POM

        <!--   @Validated  字段校验     -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        
        <!-- @Valid  字段校验 -->
        <dependency>
            <groupId>org.hibernate.validator</groupId>
            <artifactId>hibernate-validator</artifactId>
            <!-- 6.2.0.Final -->
            <version>${hibernate-validator.version}</version>
        </dependency>

1.分组

  • @Validated:提供了一个分组功能,可以在入参验证时,根据不同的分组采用不同的验证机制

    @Validated会有分组的概念,后面默认是有一个Default.class,当你的@Validated后面没有加任何校验分组信息的时候默认会加Default分组,而对于被校验的对象的属性字段,如果你在属性的校验标签里面没有指定分组会添加到默认分组Default里面。所以如果你的对象里面的每个属性都指定了分组信息,而接口上面并没有添加分组信息会出现@Validated“失效的情况”,实际是因为它校验的是Default分组,而没有字段属于Default分组。上述校验不管加不加@ReqeustBody都能完成校验,但是都不能完成嵌套的校验

  • @Valid : 作为标准的JSR-303规范,还没有吸收分组的功能

    @Valid 由于不支持分组,所以对于所以校验标签里面添加了groups字段的都不会校验会跳过。 @Valid 加不加@RequestBody 基本校验会进行,嵌套校验需要在嵌套的对象上面加@Valid则可以进行嵌套校验,由于没有分组的概念,对于不同情况校验字段不同则需要在业务逻辑里面判断。

2.注解地方

  • @Validated:用在类型、方法和方法参数上。但不能用于成员属性
  • @Valid:可以用在方法、构造函数、方法参数和成员属性上(所以可以用@Valid实现嵌套验证)

3.常用方法

@Validated -------------------------------------------------------------------------------------------------- @Valid
在这里插入图片描述在这里插入图片描述

在这里插入图片描述

4.使用方式

1.参数级调用 @Validated @Valid

@Validated 和 @Valid 都能用, 可以入参BindingResult获取参数校验结果

		// Controller 示例
		import org.apache.ibatis.annotations.Insert;
		import org.springframework.validation.annotation.Validated;
		//bindingResult 是判定参数是否判定成功的返回类,直接入参即可
		public ResultData save(@Valid User user,BindingResult bindingResult){
		}
	
		//Entity 示例
		public class User{
			@NotNull(message = "用户名不能为空")
		    private String userName;
	    }

2.方法级调用 @Validated @Valid

@Validated 和 @Valid 都能用

	public interface UserService{
		@Valid
		Object getOne(@NotNull(message = "id不能为null") @Max(value = Integer.MAX_VALUE)Integer id);
	}

	public class UserServiceImpl extends UserService{
		@Override
		public 	Object getOne(Integer id){
			return null;
		}
	}

3.属性级调用 @Valid

@Valid 可用
@Validated 不可用

		public class User{
		    @Valid
		    @NotNull(message = "mcn对象不能为空")
		    private Mcn mcn;
	    }
	
		public class Mcn{
			@NotNull(message = "mcn名称不能为空")
		    private String mcnName;
		}

		public Object save(UserDTO userDTO){
			@Valid
			User user = JsonUtils.beanToBean(userDTO,User.class);
		}

4.类级调用 @Validated @Valid

@Validated 和 @Valid 都能用

@Valid
@Validated
public interface User {
}

5.构造函数级调用 @Valid

@Valid 可用

	public class User{
		private String name;
		@Valid
	    public User(@NotNull(message = "id不能为null") String name){
			this.name = name;
	    }
	}

5.异常

如果入参参数校验失败,并且没有 BindingResult ,则会抛出 ConstraintViolationException 异常,可以进行全局异常处理,可以参考: https://blog.csdn.net/qiwunongqingyin/article/details/127112297

@Component
@ControllerAdvice
@Order(0)
public class CommonExceptionHandler {
    /**
     * 字段校验错误
     * form表单提交bean错误
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(BindException.class)
    @ResponseBody
    @ResponseStatus(HttpStatus.OK)
    public ResultData handleBindException(BindException exception) {
        log.error("入参字段绑定错误: ", exception);
        List<FieldError> fieldErrors = exception.getBindingResult().getFieldErrors();
        String errorMessage = fieldErrors.stream().map(FieldError::getDefaultMessage).collect(Collectors.joining("\n"));
        return ResultData.error("100002", errorMessage);
    }

    /**
     * 字段校验错误
     * 请求体绑定到java bean上,且校验参数失败时抛出 MethodArgumentNotValidException
     * 关键词 : @Valid 、 @RequestBody、Java bean 、表单(Content-Type: application/json、Content-Type: application/xml)
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    @ResponseStatus(HttpStatus.OK)
    public ResultData handleMethodArgumentNotValidException(MethodArgumentNotValidException exception) {
        log.error("入参字段校验错误: ", exception);
        List<FieldError> fieldErrors = exception.getBindingResult().getFieldErrors();
        String errorMessage = fieldErrors.stream().map(FieldError::getDefaultMessage).collect(Collectors.joining("\n"));
        return ResultData.error("100002", errorMessage);
    }

    /**
     * 字段校验错误
     * 普通参数(非 java bean)校验出错时抛出
     * 关键词 : @Validated 、 非Java bean
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseBody
    @ResponseStatus(HttpStatus.OK)
    public ResultData handleConstraintViolationException(ConstraintViolationException exception) {
        log.error("方法字段校验错误: ", exception);
        return ResultData.error("100002", exception.getMessage());
    }
}

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值