当 Spring Boot 中使用 Hibernate Validator 的 Bean 验证失败时,如何抛出自定义异常?

Posted

技术标签:

【中文标题】当 Spring Boot 中使用 Hibernate Validator 的 Bean 验证失败时,如何抛出自定义异常?【英文标题】:How to Throw a Custom Exception When Bean Validation In Spring Boot with Hibernate Validator Fails? 【发布时间】:2019-11-11 07:00:13 【问题描述】:

我正在使用 Spring Boot 2.0.1,其中包含验证启动器(Hibernate Validation 6.x 附带)并尝试验证方法参数并在我的 Spring 存储库层中返回对象.这个方法基本上有ParamObjReturnObj

@Repository
@Validated // Spring integration of validation
public class MyRepoImpl implements MyRepo 

  @Override
  @Valid
  public ReturnObj myMethod(@Valid ParamObj param) throw CustomException 
    try 
       // makes a call that might throw an exception
     catch (Exception e) 
      throw new CustomException(/*...*/, e);
    

    return returnObj;
  

ParamObjReturnObj 都在它们的某些属性上使用一组简单的 Bean Validation 注释,例如 @Pattern@Min 等。我的问题是,如果使用这些注释,如果 ParamObjReturnObj 验证过程失败,MyRepoImpl#myMethod() 将抛出 javax.validation.ConstraintViolationException

但是,如您所见,myMethod() 的合约要求抛出 CustomException。是的,ConstraintViolationExceptionRuntimeException,但是,现在是 MyRepoImpl#myMethod() 的调用者,例如一个服务层逻辑,除了CustomException之外,还需要捕获这个RuntimeException

原因是,我需要防止所有异常冒出服务层(对于这个特殊的 Spring @Service 我有它调用这个存储库) -- 该服务是通过服务编排调用的一长串服务的一部分,该服务编排构造了一个更大的包含对象。换句话说,这部分(通过MyRepoImpl 获得的结果)被认为是可选,随后,它的失败应该只被记录但不要停止整个过程

因此,我不能利用ControllerAdvice 为整个应用程序捕获ConstraintViolationException

我的目标是,当任一方法参数或返回的验证失败时,仅将 CustomException 扔回给调用者。

这是否可能仅使用注释?我查看了MethodValidationPostProcessor,但不知道我是否可以实现自己的目标来实现这一目标。

附:我能想到的唯一方法是放弃@Valid/@Validated 并以编程方式调用Validator#validate(obj, ...) 以获取try-catch 块内的参数和返回值,捕获约束异常,然后抛出我的CustomException()。但是,我想知道我是否可以避免这种情况,并将这个硬编码验证排除在存储库之外。

【问题讨论】:

【参考方案1】:

因为我一年前不在这里,所以我不会回答,但由于这是一个常见问题,我可以从我与同学的经验中看出,我认为答案可能是@ControllerAdvice,在任何类型的例外情况下都很方便 文档 --> https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/bind/annotation/ControllerAdvice.html

【讨论】:

ControllerAdvice 类仅捕获 ConstraintViolationException。问题是,如何抛出自定义异常而不是为这些验证错误定义一个异常? ControllerAdvice 捕获任何类型的扩展运行时的异常。 是的,这不是这里的问题。请重新阅读全文。

以上是关于当 Spring Boot 中使用 Hibernate Validator 的 Bean 验证失败时,如何抛出自定义异常?的主要内容,如果未能解决你的问题,请参考以下文章

当用户使用 Spring Boot 登录失败时,如何在登录页面中显示错误消息?

当 Spring Boot 中使用 Hibernate Validator 的 Bean 验证失败时,如何抛出自定义异常?

spring boot 中使用redis session

当 logging.config 指向 logfj2 外部配置文件的错误文件位置时,spring-boot 应用程序停止

spring-boot中tomcat的默认连接池?

当 Spring Boot 容器尝试连接 kafka 容器时出现“Broker 可能不可用”错误