未调用 ResponseEntityExceptionHandler 的覆盖的 handleMethodArgumentNotValid 方法

Posted

技术标签:

【中文标题】未调用 ResponseEntityExceptionHandler 的覆盖的 handleMethodArgumentNotValid 方法【英文标题】:overridden handleMethodArgumentNotValid method of ResponseEntityExceptionHandler not called 【发布时间】:2019-07-24 17:29:08 【问题描述】:

我正在尝试为我的 Spring Boot Rest 服务提供一个自定义验证器和一个 ExceptionHandler,当我添加 ExceptionHandler 时,验证错误不会发送到 UI。所以我试图覆盖handleMethodArgumentNotValid 方法,但这也不起作用。有人可以对此提供一些见解吗?

这就是我在控制器中配置验证类的方式 -

package services.rest.controller;

import java.io.IOException;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import lombok.extern.slf4j.Slf4j;
import services.rest.model.TestInput;
import services.rest.validator.DataValidator;

@RestController
@RequestMapping("/test")
@Slf4j
public class RestResource 

    @Autowired
    private DataValidator validator;

    @PostMapping("/create")
    public String create(@Valid final TestInput input) throws IOException 
        log.debug(input.toString());
        return "Success";
    

    @InitBinder()
    public void init(final WebDataBinder binder) 
        binder.addValidators(validator);
    


这是我的 ExceptionHandler 代码 -

package services.rest.exceptionhandler;

import java.util.ArrayList;
import java.util.List;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

@SuppressWarnings( "unchecked", "rawtypes" )
@ControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler 

    @ExceptionHandler(Exception.class)
    public final ResponseEntity<Object> handleAllExceptions(final Exception ex, final WebRequest request) 
        System.out.println("All exceptions Method getting executed!!!!");

        final List<String> details = new ArrayList<>();
        details.add(ex.getLocalizedMessage());
        return new ResponseEntity("Server Error", HttpStatus.INTERNAL_SERVER_ERROR);
    

    @Override
    protected ResponseEntity<Object> handleMethodArgumentNotValid(final MethodArgumentNotValidException ex,
            final HttpHeaders headers, final HttpStatus status, final WebRequest request) 
        System.out.println("Validation Error Method getting executed!!!!");
        final List<String> details = new ArrayList<>();
        for (final ObjectError error : ex.getBindingResult().getAllErrors()) 
            details.add(error.getDefaultMessage());
        
        return new ResponseEntity("Validation Error", HttpStatus.BAD_REQUEST);
    

最初没有覆盖“handleMethodArgumentNotValid”方法。现在也覆盖它之后,它不起作用

【问题讨论】:

大家有什么帮助吗? 你找到解决办法了吗? 我测试过,它正在工作。也许我的DataValidator 和你的不一样。可以分享DataValidator代码吗? 您应该在输入参数中添加@RequestBody 注释。 @RequestBody @Valid final TestInput input。否则,input 将为空 【参考方案1】:

您是否检查了堆栈跟踪,可能引发了 ConstraintViolation 异常,而不是 MethodArgumentNotValid 异常。 Spring 没有为此提供任何默认处理程序。

【讨论】:

【参考方案2】:

我测试了您的示例,并且似乎可以正常工作。如果您也发布TestInputDataValidator 将会很有帮助。

不起作用并不能准确说明发生了什么,我猜你刚刚收到了 400 状态码。如果是这种情况,可能只是因为之前触发了验证,但您没有覆盖 ResponseEntity&lt;Object&gt; handleBindException(final BindException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request)

【讨论】:

【参考方案3】:

以下方法对我有用:

import java.util.ArrayList;
import java.util.List;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;

@Order(Ordered.HIGHEST_PRECEDENCE)
@ControllerAdvice
public class GlobalExceptionHandler 

    @ExceptionHandler(Exception.class)
    public ResponseEntity<Object> handleAllExceptions(final Exception ex, final WebRequest request) 
        System.out.println("All exceptions Method getting executed!!!!");

        final List<String> details = new ArrayList<>();
        details.add(ex.getLocalizedMessage());
        return new ResponseEntity("Server Error", HttpStatus.INTERNAL_SERVER_ERROR);
    

    @ExceptionHandler(MissingServletRequestParameterException.class)
    protected ResponseEntity<Object> handleMethodArgumentNotValid(final Exception ex, final WebRequest request) 
        System.out.println("Validation Error Method getting executed!!!!");
        final List<String> details = new ArrayList<>();
        details.add(ex.getLocalizedMessage());
        return new ResponseEntity("Validation Error", HttpStatus.BAD_REQUEST);
    

基本上我所做的是:

未从 ResponseEntityExceptionHandler 类扩展。 输入@Order(Ordered.HIGHEST_PRECEDENCE)。 为异常 MissingServletRequestParameterException 创建一个处理程序。

希望对你有帮助

【讨论】:

【参考方案4】:

在 App 类的 @ComponentScan 中定义您的异常处理程序包。

@SpringBootApplication
@ComponentScan(basePackages =  "services.rest.exceptionhandler" )
public class App 

    public static void main(String[] args) 
        SpringApplication.run(App.class, args);
    


【讨论】:

以上是关于未调用 ResponseEntityExceptionHandler 的覆盖的 handleMethodArgumentNotValid 方法的主要内容,如果未能解决你的问题,请参考以下文章

numberOfRowsInSection 已调用但 cellForRowAt 未调用

调用 textFieldShouldBeginEditing,未调用 textFieldDidBeginEditing

JQuery:未捕获的类型错误:无法读取未定义的属性“调用”

调用结果未使用

C# Web Api 调用未从 jquery 调用

未调用 cellForRowAtIndexPath 但调用 numberOfRowsInSection