@NotEmpty\@NotBlank等注解用在字符串属性上提示[The annotation XXX is disallowed for this data type]的问题解决方案.

@NotNull、@NotBlack等校验注解的诡异问题总结

问题再现

背景

公司新成立了一个项目,但在已有项目的支持下引入了一批原始的依赖,就这样,坑来了…

复现

  1. 通过Maven工具引入java注解相关依赖.
    仅展示与@NotNull和@NotBlank相关的依赖,方便后续作说明.
<!--注解校验类-->
<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <!--<version>2.0.1.Final</version>-->
</dependency>

<!--以下注解校验实现类-->
 <dependency>
     <groupId>org.hibernate</groupId>
     <artifactId>hibernate-validator</artifactId>
     <version>5.2.1.Final</version>
 </dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator-annotation-processor</artifactId>
    <version>5.2.1.Final</version>
</dependency>
<!--以上注解校验实现类-->
  1. 代码实现(涉及公司机密,因此仅展示Demo)

2.1 请求Request

import javax.validation.constraints.Min;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;


//校验实体类
@Data
public class SSS {

    @NotEmpty(message = "名称不能为空!")
    private String name;

    @NotNull(message = "年龄不能为空!")
    @Min(message = "年龄不能小于123岁!", value = 123)
    private Integer age;

}

2.2 请求Controller


@RestController
@RequestMapping("/test")
public class InfoController {

  @PostMapping("/demo")
  public String ss( @Valid @RequestBody SSS request) {
   
      System.out.println(request.toString());
      return "测试成功";
  }
}

错误提示

  1. java: The annotation @NotEmpty is disallowed for this data type.
    在这里插入图片描述

解决

查找问题过程

通过错误提示[is disallowed for this data type.]对代码的全局搜索后,发现【hibernate-validator】依赖的【ValidationProcessorMessages.properties】中存在【NOT_SUPPORTED_TYPE=The annotation @{0} is disallowed for this data type.】,再通过引用方式点击进入【TypeCheck.java】类中才发现该依赖会对属性在编译时期就进行类型匹配的校验,且其并未完全参照@NotEmpty等注解的支持形式进行类型判断,因此会提示该错误;
例:@NotEmpty与本注解会支持下列属性

CharSequence (length of character sequence is evaluated)
Collection (collection size is evaluated)
Map (map size is evaluated)
Array (array length is evaluated)

上述描述如图 1.1、1.2所示.
在这里插入图片描述
图1.1 ValidationProcessorMessages.properties部分消息展示

在这里插入图片描述
图1.2 TypeCheck.java校验逻辑

解决方案

既然原有的【hibernate-validator】并不满足@NotEmpty和@NotBlank等方式编译期校验,即可以再寻找替换的方案;而Spring提供的【spring-boot-starter-validation】依赖经测试可以满足,原因很简单,就是它实现了上述注解的适用范围.直接使用【spring-boot-starter-validation】替换maven依赖的【hibernate-validator】和【hibernate-validator-annotation-processor】即可。
替换依赖如下

		<dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-validation</artifactId>
              <version>2.3.4.RELEASE</version>
         </dependency>

这样即可解决题目中出现的错误了

PS

1.其实springboot的校验实现基类都是以【HibernateValidatorFactory.java】进行校验逻辑对象的调用,无非是笔者最先引入的依赖多了一个TypeCheck的校验罢了。

2.附上笔者亲测的@NotEmpty这一系列的注解最终的处理方式。

1.通过BindingResult进行校验结果处理;(其实可以使用切面进行处理,至于实现就靠各位了.)

	@PostMapping("/test")
    public String ss( @RequestAttribute SSS request, BindingResult rs ) {
    	//此处处理校验结果.
        if(rs.hasErrors()){
        	//每次仅取一次校验结果返回.
            return  rs.getFieldError().getDefaultMessage();
        }

        System.out.println(request.toString());
        return "dafds";
    }

2.通过@Valid注解抛出校验异常,再用@RestControllerAdvice结合@ExceptionHandler进行统一异常处理,Demo如下.

	@PostMapping("/test")
    public String ss(@Valid @RequestAttribute SSS request) {
    	//此处处理校验结果.
        if(rs.hasErrors()){
        	//每次仅取一次校验结果返回.
            return  rs.getFieldError().getDefaultMessage();
        }

        System.out.println(request.toString());
        return "dafds";
    }
	
	//统一异常处理类
@RestControllerAdvice
public class BaseExceptionHandler {

    /**
     * 业务手动异常
     */
    @ExceptionHandler(value = Exception.class)
    public String exceptionRest(Exception e) {
        return  e.getMessage();
    }

先就这样吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值