Spring Boot如何为ConstraintViolationException编写多场景差异化异常处理器
错误原因
你为同一个javax.validation.ConstraintViolationException异常类型注册了两个@ExceptionHandler处理方法,Spring MVC的异常解析器无法区分不同的触发场景,因此启动时会抛出歧义映射错误,这是Spring的原生设计限制,不允许同一异常类型对应多个同优先级的处理方法。
解决方案
只保留一个ConstraintViolationException的处理方法,在方法内部解析校验异常的具体违反规则,判断是@Email格式校验失败还是@Size长度校验失败,再返回对应的自定义响应即可。
代码调整示例
import javax.validation.ConstraintViolation; import javax.validation.constraints.Email; import javax.validation.constraints.Size; import java.lang.annotation.Annotation; @ExceptionHandler(ConstraintViolationException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public ExceptionResponse handleConstraintViolationException(ConstraintViolationException exception) { ExceptionResponse exceptionResponse = new ExceptionResponse(); // 遍历所有校验失败项,可根据需求取第一个或者汇总所有错误 for (ConstraintViolation<?> violation : exception.getConstraintViolations()) { // 获取触发校验失败的注解类型 Class<? extends Annotation> annotationType = violation.getConstraintDescriptor().getAnnotation().annotationType(); if (annotationType == Email.class) { // 邮箱格式错误 exceptionResponse.setMessage(Message.WRONG_FORMAT.getMessage()); exceptionResponse.setCode(551); break; } else if (annotationType == Size.class) { // 长度校验失败 exceptionResponse.setMessage(Message.PASSWORD_MUST_NOT_BE_SHORT.getMessage()); exceptionResponse.setCode(550); break; } // 可自行扩展其他校验注解的判断逻辑 } return exceptionResponse; }
可选扩展逻辑
- 如果同一个字段绑定了多个校验规则,可以通过
violation.getPropertyPath().toString()获取校验失败的字段名,结合注解类型做更精准的判断 - 如果需要返回所有校验失败的错误信息,可以遍历所有
ConstraintViolation收集信息后统一返回
内容的提问来源于stack exchange,提问作者iwritecomeinmymind
相关产品推荐
相关产品推荐

