spring 引导应用程序启动时获取映射到 MethodArgumentNotValidException 的不明确的 @ExceptionHandler 方法
Getting Ambiguous @ExceptionHandler method mapped for MethodArgumentNotValidException while startup of spring boot application
我已经为我的 spring 控制器之一编写了自定义异常处理程序 class,以验证请求参数中的电子邮件属性是否采用正确的格式。因此创建了一个新的 class 扩展了 ResponseEntityExceptionHandler
class 并用 @ExceptionHandler
.
编写了一个方法
但是在 spring 引导应用程序启动期间,我遇到了以下异常,该异常正在停止 运行 我的项目。有人可以帮我解决这个问题吗?
服务器启动时出现异常:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'handlerExceptionResolver' defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]: Bean instantiation via factory method failed;
nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.servlet.HandlerExceptionResolver]: Factory method 'handlerExceptionResolver' threw exception;
nested exception is 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) throws java.lang.Exception}
自定义 Class 处理 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;
}
}
Spring 为 MethodArgumentNotValidException
内置了 ResponseEntityExceptionHandler
。因此,对于同一个异常,您有两个处理程序,这是不允许的。
您可以尝试覆盖 ResponseEntityExceptionHandler.handleMethodArgumentNotValid()
。
您在这里遇到的问题是可以预料的。您正在有效地扩展 Spring ResponseEntityExceptionHandler
,默认情况下它已经在其自己的 @ExceptionHandler
注释中包含 MethodArgumentNotValidException
的声明。
您可以从 class 的来源轻松查看:
这就是您在日志中看到这条错误的原因:
java.lang.IllegalStateException: Ambiguous @ExceptionHandler method mapped for [class org.springframework.web.bind.MethodArgumentNotValidException]
基于以上所有内容,您应该删除自己的异常处理程序方法并覆盖其中的方法。
歧义是因为您在 类 - ResponseEntityExceptionHandler、MethodArgumentNotValidException 中有相同的方法 - @ExceptionHandler。您需要按如下方式编写重写方法来解决此问题 -
@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);
}
我已经为我的 spring 控制器之一编写了自定义异常处理程序 class,以验证请求参数中的电子邮件属性是否采用正确的格式。因此创建了一个新的 class 扩展了 ResponseEntityExceptionHandler
class 并用 @ExceptionHandler
.
但是在 spring 引导应用程序启动期间,我遇到了以下异常,该异常正在停止 运行 我的项目。有人可以帮我解决这个问题吗?
服务器启动时出现异常:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'handlerExceptionResolver' defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]: Bean instantiation via factory method failed;
nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.servlet.HandlerExceptionResolver]: Factory method 'handlerExceptionResolver' threw exception;
nested exception is 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) throws java.lang.Exception}
自定义 Class 处理 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;
}
}
Spring 为 MethodArgumentNotValidException
内置了 ResponseEntityExceptionHandler
。因此,对于同一个异常,您有两个处理程序,这是不允许的。
您可以尝试覆盖 ResponseEntityExceptionHandler.handleMethodArgumentNotValid()
。
您在这里遇到的问题是可以预料的。您正在有效地扩展 Spring ResponseEntityExceptionHandler
,默认情况下它已经在其自己的 @ExceptionHandler
注释中包含 MethodArgumentNotValidException
的声明。
您可以从 class 的来源轻松查看:
这就是您在日志中看到这条错误的原因:
java.lang.IllegalStateException: Ambiguous @ExceptionHandler method mapped for [class org.springframework.web.bind.MethodArgumentNotValidException]
基于以上所有内容,您应该删除自己的异常处理程序方法并覆盖其中的方法。
歧义是因为您在 类 - ResponseEntityExceptionHandler、MethodArgumentNotValidException 中有相同的方法 - @ExceptionHandler。您需要按如下方式编写重写方法来解决此问题 -
@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);
}