spring boot 覆盖默认的 REST 异常处理程序

Posted

技术标签:

【中文标题】spring boot 覆盖默认的 REST 异常处理程序【英文标题】:spring boot override default REST exception handler 【发布时间】:2016-06-04 11:44:05 【问题描述】:

我无法覆盖 REST api 中的默认 Spring Boot 错误响应。我有以下代码

@ControllerAdvice
@Controller
class ExceptionHandlerCtrl 

    @ResponseStatus(value=HttpStatus.UNPROCESSABLE_ENTITY, reason="Invalid data")
    @ExceptionHandler(BusinessValidationException.class)
    @ResponseBody
    public ResponseEntity<BusinessValidationErrorVO> handleBusinessValidationException(BusinessValidationException exception)
        BusinessValidationErrorVO vo = new BusinessValidationErrorVO()
        vo.errors = exception.validationException
        vo.msg = exception.message
        def result =  new ResponseEntity<>(vo, HttpStatus.UNPROCESSABLE_ENTITY);
        result

    

然后在我的 REST api 中我抛出这个 BusinessValidationException。这个处理程序被调用(我可以在调试器中看到它)但是我仍然收到默认的 spring boot REST 错误消息。有没有办法覆盖和使用默认值作为后备?带有 groovy 的 Spring Boot 版本 1.3.2。最好的问候

【问题讨论】:

【参考方案1】:

从您的方法中删除 @ResponseStatus。它会产生不良副作用,您不需要它,因为您在 ResponseEntity 中设置了 HttpStatus.UNPROCESSABLE_ENTITY

来自JavaDoc on ResponseStatus

警告:在异常类上使用该注解,或设置该注解的原因属性时,将使用HttpServletResponse.sendError方法。

对于HttpServletResponse.sendError,响应被认为是完整的,不应再写入任何内容。此外,Servlet 容器通常会编写一个 html 错误页面,因此会使用不适合 REST API 的原因。对于这种情况,最好使用ResponseEntity 作为返回类型,并完全避免使用@ResponseStatus

【讨论】:

【参考方案2】:

我建议你阅读这个问题:Spring Boot REST service exception handling

您可以在此处找到一些示例,说明如何结合 ErrorController/ ControllerAdvice 以捕获任何异常。

特别检查这个答案:

https://***.com/a/28903217/379906

您可能应该从方法 handleBusinessValidationException 中删除注释 @ResponseStatus

另一种重写默认错误消息的方法是使用带有注解@RequestMapping("/error") 的控制器。控制器必须实现 ErrorController 接口。

这是我在应用中使用的错误控制器。

@RestController
@RequestMapping("/error")
public class RestErrorController implements ErrorController

    private final ErrorAttributes errorAttributes;

    @Autowired
    public MatemoErrorController(ErrorAttributes errorAttributes) 
        Assert.notNull(errorAttributes, "ErrorAttributes must not be  null");
    this.errorAttributes = errorAttributes;
  

@Override
public String getErrorPath() 
    return "/error";


@RequestMapping
public Map<String, Object> error(HttpServletRequest aRequest) 

    return getErrorAttributes(aRequest, getTraceParameter(aRequest));


private boolean getTraceParameter(HttpServletRequest request) 
    String parameter = request.getParameter("trace");
    if (parameter == null) 
        return false;
    
    return !"false".equals(parameter.toLowerCase());


private Map<String, Object> getErrorAttributes(HttpServletRequest  aRequest, boolean includeStackTrace)

    RequestAttributes requestAttributes = new  ServletRequestAttributes(aRequest);
    return errorAttributes.getErrorAttributes(requestAttributes,  includeStackTrace);
  

【讨论】:

以上是关于spring boot 覆盖默认的 REST 异常处理程序的主要内容,如果未能解决你的问题,请参考以下文章

如何为 Spring Boot Rest 使用自定义异常?

处理自定义转换器抛出的 Spring Boot REST 异常

处理从自定义转换器抛出的Spring Boot REST中的异常

知识点-Spring Boot 统一异常处理汇总

如何使用 power mock 对 Spring Boot Rest 控制器和异常处理程序进行单元测试

Spring Boot REST 多部分请求(文件 + json)抛出 415 Unsupported Media Type 异常