Java Springboot异常处理程序没有';捕捉不到异常

Java Springboot异常处理程序没有';捕捉不到异常,java,rest,spring-boot,Java,Rest,Spring Boot,在SpringBoot和rest应用程序中,我配置了一个异常处理程序,如下所示。若在请求将异常发送到rest服务后引发异常,则可以正常工作 RESTAPI要求内容类型为“application/json”,如果我不将该内容类型头发送给api,异常处理程序将不会捕获异常。它在日志中打印以下信息: DEBUG [o.s.w.s.DispatcherServlet] DispatcherServlet with name 'dispatcherServlet' processing PUT reque

在SpringBoot和rest应用程序中,我配置了一个异常处理程序,如下所示。若在请求将异常发送到rest服务后引发异常,则可以正常工作

RESTAPI要求内容类型为“application/json”,如果我不将该内容类型头发送给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
DEBUG[o.s.w.s.DispatcherServlet]名为“DispatcherServlet”的DispatcherServlet正在处理[/app/v1.0/customers/customer/zones/zoneName]的PUT请求。]
调试[o.s.w.s.m.m.a.RequestMappingHandlerMapping]查找路径/app/v1.0/customers/customer/zones/zoneName的处理程序方法。
调试[o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver]从处理程序解析异常[null]:org.springframework.web.HttpMediaTypeNotSupportedException:不支持内容类型“text/plain”
调试[o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver]调用@ExceptionHandler方法:public final org.springframework.http.ResponseEntity org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler.handleException(java.lang.Exception,org.springframework.web.context.request.WebRequest)
调试[o.s.w.s.DispatcherServlet]返回给名为“DispatcherServlet”的DispatcherServlet的Null ModelAndView:假设HandlerAdapter已完成请求处理
调试[o.s.w.s.DispatcherServlet]已成功完成请求
以下是异常处理程序类:

@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);
    }
}
@ControllerAdvice
@RestController
公共类ServiceExceptionHandler扩展了ResponseEntityExceptionHandler
{
@ExceptionHandler(Exception.class)
公共最终响应性处理例外(可丢弃的ex、WebRequest请求)
{
ErrorResponse ErrorResponse=null;
如果(例如ApiException的实例)
{
errorResponse=新的errorResponse((ApiException)ex);
}
其他的
{
记录器错误(ex);
errorResponse=新的errorResponse();
errorResponse.setCode(HttpCodes.HTTP_CODE_500);
errorResponse.setError(例如getMessage());
}
返回新的ResponseEntity(errorResponse,
HttpStatus.valueOf(errorResponse.getCode());
}
受保护的响应handleNoHandlerFoundException(NoHandlerFoundException ex,
HttpHeaders标头、HttpStatus状态、WebRequest请求)
{
Map responseBody=newhashmap();
put(“path”,request.getContextPath());
responseBody.put(“消息”,
“您所访问的URL目前不在服务中(404)。”;
返回新的ResponseEntity(responseBody,HttpStatus.NOT_FOUND);
}
}

您的类将只捕获从控制器中引发的错误。您看到的错误发生在调用控制器之前,因为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
请注意,处理程序为null

您还需要实现一个
HandlerExceptionResolver
来处理该类型的异常:

有关更多详细信息,请参阅。

以下是最终解决方案:

@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()));
    }
}
@ControllerAdvice
公共类SpringExceptionHandler扩展ExceptionHandlerExceptionResolver
{
@ExceptionHandler(org.springframework.web.HttpMediaTypeNotSupportedException.class)
公共响应HandleController异常(HttpMediaTypeNotSupportedException例外,WebRequest请求)
{
ErrorResponse ErrorResponse=null;
例如printStackTrace();
errorResponse=新的errorResponse();
errorResponse.setCode(HttpCodes.HTTP\u代码\u内部错误);
errorResponse.setError(例如getMessage());
返回新的ResponseEntity(errorResponse,
HttpStatus.valueOf(errorResponse.getCode());
}
}
现在,我需要做一些更改,使其适用于所有异常,包括抛出的控制器,但这是以后的工作。(谢谢亚当)


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

谢谢你,亚当。这为找到一个有效的解决方案提供了很好的指导,但我花了一段时间来修复它。看起来spring不喜欢两个异常处理程序。我有ExceptionHandlerExceptionResolver和ResponseEntityExceptionHandler,因此,异常总是会转到ResponseEntityExceptionHandler。我删除了ResponseEntity one,只保留了global ExceptionHandlerExceptionResolver,它工作起来很有魅力。