当属性为空时,不调用Spring boot父版(2.3.0.RELEASE)的异常处理方法。

问题描述 投票:0回答:1

我有一个rest控制器,它有一个requestObject,其中包含3个属性,而且它们是强制性的,我有下面的类,其中包含方法constraintViolationException处理@NotBlank异常。基本上我有下面的类,其中包含方法constraintViolationException来处理@NotBlank异常。

@ControllerAdvice
public class MyExceptionHandler extends ResponseEntityExceptionHandler{
    // @Validate For Validating Path Variables and Request Parameters
    @ExceptionHandler(ConstraintViolationException.class)
    public void constraintViolationException(HttpServletResponse response) throws IOException {
  //TODO - to provide custom error message
        response.sendError(HttpStatus.BAD_REQUEST.value());
    }

}

我的Controller如下图所示。

@RestController
public class MyRestController {



    @PostMapping(value = "/processMyPayment")
    public  ResponseEntity<?> processMyPayment(@Valid MyRequest myRequest ) {

        MyResponse myResponse = new MyResponse();
        return new ResponseEntity<>(myTResponse, HttpStatus.OK);
    }
...

当我添加类MyExceptionHandler并发送null属性时,我的休息控制器应该调用constraintViolationException,因为值是null,但事实并非如此,我得到以下结果。enter image description here

. 然而,当我删除了 "MyExceptionHandler "类的 响应实体ExceptionHandler的扩展。 我得到了整个堆栈跟踪。

"timestamp": "2020-06-05T13:01:47.715+00:00",
"status": 400,
"error": "Bad Request",
"trace": "org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 3 errors\nField error in object 'myRequest' on field 'amount': rejected value [null]; codes [NotBlank.myRequest.amount,NotBlank.amount,NotBlank.java.lang.String,NotBlank]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [myRequest.amount,amount]; arguments []; default message [amount]]; default message [Amount name mandatory]\nField error in object 'myRequest' on field 'accountId': rejected value [null]; codes [NotBlank.myRequest.accountId,NotBlank.accountId,NotBlank.java.lang.String,NotBlank]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [myRequest.accountId,accountId]; arguments []; default message [accountId]]; default message [Account id is mandatory]\nField error in object 'myRequest' on field 'accountName': rejected value [null]; codes [NotBlank.myRequest.accountName,NotBlank.accountName,NotBlank.java.lang.String,NotBlank]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [myRequest.accountName,accountName]; arguments []; default message [accountName]]; default message [Account name mandatory]\r\n\tat org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:164)\r\n\tat org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121)\r\n\tat org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:167)\r\n\tat org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:134)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:879)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793)\r\n\tat org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)\r\n\tat org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)\r\n\tat org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)\r\n\tat org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)\r\n\tat org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)\r\n\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:660)\r\n\tat org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)\r\n\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:741)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n\tat org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n\tat org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n\tat org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n\tat org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:93)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n\tat org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n\tat org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)\r\n\tat org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)\r\n\tat org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)\r\n\tat org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)\r\n\tat org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)\r\n\tat org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)\r\n\tat org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)\r\n\tat org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:373)\r\n\tat org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)\r\n\tat org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)\r\n\tat org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590)\r\n\tat org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)\r\n\tat java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)\r\n\tat java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)\r\n\tat org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\r\n\tat java.base/java.lang.Thread.run(Thread.java:832)\r\n",
"message": "Validation failed for object='myRequest'. Error count: 3",
"errors":[
{"codes":["NotBlank.myRequest.amount", "NotBlank.amount", "NotBlank.java.lang.String", "NotBlank" ],…},
{"codes":["NotBlank.myRequest.accountId", "NotBlank.accountId", "NotBlank.java.lang.String", "NotBlank" ],…},
{"codes":["NotBlank.myRequest.accountName", "NotBlank.accountName", "NotBlank.java.lang.String", "NotBlank" ],…}
],
"path": "/processMyPayment"
}

基本上,我想实现的是,我不提供堆栈跟踪,而只是想添加那些为空的字段,并附带一个错误信息,即这些字段不能为空。

有什么办法可以实现这一点吗,先谢谢了。

java spring-boot spring-restcontroller
1个回答
0
投票

试试这个。

/**
     * Handles javax.validation.ConstraintViolationException. Thrown when @Validated fails.
     *
     * @param ex the ConstraintViolationException
     * @return error
     */
    @ExceptionHandler(javax.validation.ConstraintViolationException.class)
    public ResponseEntity<Object> handleConstraintViolation(
            javax.validation.ConstraintViolationException ex) {
        // list of violations
        // ex.getConstraintViolations();

        // return custom error
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null);
    }

你应该覆盖这个方法 handleMethodArgumentNotValid()ResponseEntityExceptionHandler,就像这样。

/**
     * Handle @see MethodArgumentNotValidException. Triggered when an object fails validation.
     *
     * @param ex      the @see MethodArgumentNotValidException that is thrown when validation fails
     * @param headers   HttpHeaders @see HttpHeaders
     * @param status    HttpStatus  @see HttpStatus
     * @param request   WebRequest @see WebRequest
     * @return ResponseEntity<Object>
     */
    @Override
    protected ResponseEntity<Object> handleMethodArgumentNotValid(
            MethodArgumentNotValidException ex,
            HttpHeaders headers,
            HttpStatus status,
            WebRequest request) {

            // get Binding Result
            Object bindingResult = ex.getBindingResult();
            // get specific field errors
            Object fieldErrors = ex.getBindingResult().getFieldErrors();
            // get error counts
            int errorCount = ex.getBindingResult().getErrorCount();

            // return, you can create custom responses based on fieldErrors and errorCounts as well and send that in the body below.
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(fieldErrors);
    }

当你覆盖上面的这个函数时,你会发现,只要有任何一个 @Valid 验证失败。你可以改变返回类型。

测试后告诉我。你也可以查看一个经过测试的开源项目,以获得自定义的异常处理和响应->https:/github.comAccessGateLabsresponse-builder。

处理自定义异常的特定类的链接-> https:/github.comAccessGateLabsresponse-builderbmastersrcmainjavacomaccessgatelabsossbuilderexceptionsRestExceptionHandler.java。


0
投票

你处理了错误的异常。ConstraintViolationException 是用于entitydomain对象验证的。Spring会抛出一个 MethodArgumentNotValidException 在web层,如果使用 @Valid 控制器的方法参数上。你可以像这样修改你的异常处理程序。

@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<CustomErrorResponse> handle(MethodArgumentNotValidException e) {
    // You could extract default error messages from the exception
    val errors = getErrors(e)
    return ResponseEntity
            .status(HttpStatus.BAD_REQUEST)
            .contentType(MediaType.APPLICATION_JSON)
            .body(CustomErrorResponse.of(errors)));
}

0
投票

最后我发现了这个问题,如果有人遇到这个问题,我把它贴出来。 基本上我必须覆盖以下方法。

    @Override
    protected ResponseEntity<Object> handleBindException(BindException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
//add custom implementation here
            return this.handleExceptionInternal(ex, (Object)null, headers, status, request);
    }
© www.soinside.com 2019 - 2024. All rights reserved.