【问题标题】:Springboot exception handler doesn't catch exceptionSpringboot异常处理程序不捕获异常
【发布时间】:2017-05-02 15:51:28
【问题描述】:

在 Spring boot 和 rest 应用程序中,我配置了一个异常处理程序,如下所示。如果在请求使其停止服务后抛出异常,它工作正常。

Rest api 期望 Content-Type 为“application/json”,如果我不将该 content-type 标头发送到 api,异常处理程序不会捕获异常。它在日志中打印以下信息:

DEBUG [o.s.w.s.DispatcherServlet] DispatcherServlet with name 'dispatcherServlet' processing PUT request for [/app/v1.0/customers/customer/zones/zoneName.]
DEBUG [o.s.w.s.m.m.a.RequestMappingHandlerMapping] Looking up handler method for path /app/v1.0/customers/customer/zones/zoneName.
DEBUG [o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver] Resolving exception from handler [null]: org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'text/plain' not supported
DEBUG [o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver] Invoking @ExceptionHandler method: public final org.springframework.http.ResponseEntity<java.lang.Object> org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler.handleException(java.lang.Exception,org.springframework.web.context.request.WebRequest)
DEBUG [o.s.w.s.DispatcherServlet] Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling
DEBUG [o.s.w.s.DispatcherServlet] Successfully completed request

这是异常处理程序类:

@ControllerAdvice
@RestController  
public class ServiceExceptionHandler extends ResponseEntityExceptionHandler
{

    @ExceptionHandler(Exception.class)  
    public final ResponseEntity<java.lang.Object> handleException(Throwable ex,WebRequest req)
    {
        ErrorResponse errorResponse = null;
        if (ex instanceof ApiException)
        {
            errorResponse = new ErrorResponse((ApiException) ex);
        }
        else
        {
            logger.error(ex);
            errorResponse = new ErrorResponse();
            errorResponse.setCode(HttpCodes.HTTP_CODE_500);
            errorResponse.setError(ex.getMessage());
        }
        return new ResponseEntity<Object>(errorResponse,
                HttpStatus.valueOf(errorResponse.getCode()));

    }
    protected ResponseEntity<Object> handleNoHandlerFoundException(NoHandlerFoundException ex,
            HttpHeaders headers, HttpStatus status, WebRequest request)
    {
        Map<String, String> responseBody = new HashMap<String, String>();
        responseBody.put("path", request.getContextPath());
        responseBody.put("message",
                "The URL you have reached is not in service at this time (404).");
        return new ResponseEntity<Object>(responseBody, HttpStatus.NOT_FOUND);
    }
}

【问题讨论】:

    标签: java rest spring-boot


    【解决方案1】:

    您的类只会捕获从控制器内部引发的错误。您看到的错误发生在调用控制器之前,因为 Spring 找不到控制器来处理请求。

    DEBUG [o.s.w.s.m.m.a.RequestMappingHandlerMapping] Looking up handler method for path /app/v1.0/customers/customer/zones/zoneName.
    DEBUG [o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver] Resolving exception from handler [null]: org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'text/plain' not supported
    

    注意处理程序为空。

    您还需要实现HandlerExceptionResolver 来处理该类型的异常:http://docs.spring.io/spring/docs/3.1.x/spring-framework-reference/html/mvc.html#mvc-exceptionhandlers

    更多详情请见Spring exception handler outside controller

    【讨论】:

    • 谢谢亚当。这为找到可行的解决方案提供了非常好的指导,但我花了一段时间来修复它。看起来 spring 不喜欢两个异常处理程序。我有 ExceptionHandlerExceptionResolver 和 ResponseEntityExceptionHandler,因此异常总是去 ResponseEntityExceptionHandler。我删除了 ResponseEntity 一个,只保留了全局 ExceptionHandlerExceptionResolver,它就像一个魅力。
    【解决方案2】:

    这是最终的解决方案:

    @ControllerAdvice  
    public class SpringExceptionHandler extends ExceptionHandlerExceptionResolver
    {
        @ExceptionHandler(org.springframework.web.HttpMediaTypeNotSupportedException.class)
        public ResponseEntity<Object> handleControllerException(HttpMediaTypeNotSupportedException ex, WebRequest req)
        {
            ErrorResponse errorResponse = null;
            ex.printStackTrace();
            errorResponse = new ErrorResponse();
            errorResponse.setCode(HttpCodes.HTTP_CODE_INTERNAL_ERROR);
            errorResponse.setError(ex.getMessage());
            return new ResponseEntity<Object>(errorResponse,
                HttpStatus.valueOf(errorResponse.getCode()));
        }
    }
    

    现在我需要进行一些更改以使其适用于所有异常,包括抛出的控制器,但这是以后的事情。 (感谢亚当)。

    重要提示:如果同时存在全局处理程序和实体处理程序,spring 会忽略全局处理程序。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-07
      • 1970-01-01
      • 1970-01-01
      • 2018-05-30
      • 2010-12-11
      • 2011-08-17
      • 2013-01-07
      • 2014-09-02
      相关资源
      最近更新 更多