在启动 Spring Boot 应用程序时获取为 MethodArgumentNotValidException 映射的不明确的 @ExceptionHandler 方法

Posted

技术标签:

【中文标题】在启动 Spring Boot 应用程序时获取为 MethodArgumentNotValidException 映射的不明确的 @ExceptionHandler 方法【英文标题】:Getting Ambiguous @ExceptionHandler method mapped for MethodArgumentNotValidException while startup of spring boot application 【发布时间】:2019-01-30 04:46:07 【问题描述】:

我已经为我的一个 spring 控制器编写了自定义异常处理程序类,以验证来自请求参数的电子邮件属性是否具有正确的格式。所以创建了一个扩展ResponseEntityExceptionHandler 类的新类,并用@ExceptionHandler 编写了一个方法。

但是在 Spring Boot 应用程序启动期间,我遇到了正在停止运行我的项目的异常。有人可以帮我解决这个问题吗?

服务器启动时出现异常:

org.springframework.beans.factory.BeanCreationException:在类路径资源 [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class] 中定义名称为“handlerExceptionResolver”的 bean 创建错误:通过工厂进行 Bean 实例化方法失败; 嵌套异常是 org.springframework.beans.BeanInstantiationException:无法实例化 [org.springframework.web.servlet.HandlerExceptionResolver]:工厂方法“handlerExceptionResolver”抛出异常; 嵌套异常是 java.lang.IllegalStateException: Ambiguous @ExceptionHandler method mapped for [class org.springframework.web.bind.MethodArgumentNotValidException]: public com.TestVO com.handler.exception.TestExceptionHandler.methodArgumentNotValidException(org.springframework.web.bind .MethodArgumentNotValidException), public final org.springframework.http.ResponseEntity org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler.handleException(java.lang.Exception,org.springframework.web.context.request.WebRequest) 抛出java.lang.Exception

处理MethodArgumentNotValidException的自定义类:

@ControllerAdvice
public class ExceptionHandler extends ResponseEntityExceptionHandler 

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public ErrorVO processValidationError(MethodArgumentNotValidException ex) 
        BindingResult result = ex.getBindingResult();
        List<FieldError> fieldErrors = result.getFieldErrors();
        FieldError fieldError = fieldErrors.get(0);
        ErrorVO dto = new ErrorVO(fieldError.getDefaultMessage());
        return dto;
    

【问题讨论】:

【参考方案1】:

歧义是因为您在两个类中都有相同的方法 - @ExceptionHandler - ResponseEntityExceptionHandler、MethodArgumentNotValidException。您需要编写如下覆盖的方法来解决此问题 -

   @Override
   protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex,
                 HttpHeaders headers, HttpStatus status, WebRequest request) 
          String errorMessage = ex.getBindingResult().getFieldErrors().get(0).getDefaultMessage();
          List<String> validationList = ex.getBindingResult().getFieldErrors().stream().map(fieldError->fieldError.getDefaultMessage()).collect(Collectors.toList());
          LOGGER.info("Validation error list : "+validationList);
          ApiErrorVO apiErrorVO = new ApiErrorVO(errorMessage);
          apiErrorVO.setErrorList(validationList);
          return new ResponseEntity<>(apiErrorVO, status);
   

【讨论】:

我的反应很好,但为什么不只是:@Override protected ResponseEntity&lt;Object&gt; handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) List&lt;String&gt; validationList = ex.getBindingResult().getFieldErrors() .stream() .map(fieldError -&gt; fieldError.getDefaultMessage()) .collect(Collectors.toList()); return new ResponseEntity&lt;&gt;(validationList, status); 【参考方案2】:

您在这里遇到的问题是意料之中的。您实际上是在扩展 Spring ResponseEntityExceptionHandler,默认情况下它已经在自己的 @ExceptionHandler 注释中包含了 MethodArgumentNotValidException 的声明。

您可以从课程的源代码轻松检查这一点:

https://github.com/spring-projects/spring-framework/blob/master/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseEntityExceptionHandler.java

这就是您在日志中看到此错误的原因:

java.lang.IllegalStateException: Ambiguous @ExceptionHandler method mapped for [class org.springframework.web.bind.MethodArgumentNotValidException]

基于以上所有内容,您应该删除自己的异常处理方法并覆盖其中的方法。

【讨论】:

【参考方案3】:

Spring 有一个内置的ResponseEntityExceptionHandler 用于MethodArgumentNotValidException。所以你有两个处理同一个异常的处理程序,这是不允许的。

您可以尝试覆盖ResponseEntityExceptionHandler.handleMethodArgumentNotValid()

【讨论】:

以上是关于在启动 Spring Boot 应用程序时获取为 MethodArgumentNotValidException 映射的不明确的 @ExceptionHandler 方法的主要内容,如果未能解决你的问题,请参考以下文章

当配置设置为另一个时,Idea + Spring Boot + Tomcat 在端口 8080 上启动

使用 JPA 和 mysql 启动在 Spring Boot 中创建的应用程序时出错

Spring boot - 在启动时禁用 Liquibase

如何在 Spring Boot 启动时为反应式 r2dbc 驱动程序运行 flyway 迁移

Spring Boot 在命令行指定主类启动程序

从 IntelliJ 社区版启动 Spring Boot 应用程序