【问题标题】:Return JSON on uncaught exceptions in Spring controllers在 Spring 控制器中返回 JSON 未捕获的异常
【发布时间】:2016-10-29 23:16:45
【问题描述】:

我有一个带有 @RestController 注释的 Spring 控制器,它正在返回 JSON。我还有一个用@ControllerAdvice 注释的类,其中@ExceptionHandlers 与一些自定义异常相关。我正在使用 Tomcat 来提供这个 RESTful API。我希望捕获任何非自定义异常,例如来自 3rd 方库或 NullPointerException 的异常,并返回状态为 500 - 内部服务器错误作为 JSON 并带有消息而不是显示错误的 HTML 页面。

如果我在控制器建议中使用@ExceptionHandler(Exception.class),它将接管所有 Spring 异常,例如 MissingPathVariableException.class,这并不理想。我尝试过扩展 Spring 的 ResponseEntityExceptionHandler,但是这个类没有用 @ResponseBody 注释所以不返回 JSON。

  1. 如何在 Spring RESTful API 中为未捕获的和未知的异常(您无法计划的异常)返回 JSON,而不影响 Spring 的内部?
  2. 如何才能完全关闭返回 HTML 并确保无论请求是否有异常都只有 JSON 响应?

【问题讨论】:

    标签: java json spring-mvc exception-handling spring-restcontroller


    【解决方案1】:

    要在未捕获的异常上返回 JSON,您可以使用以下代码:

    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.RestController;
    
    @ControllerAdvice  
    @RestController
    public class GlobalExceptionHandler {
    
        private class JsonResponse {
            String message;
    
            public JsonResponse() {
            }
    
            public JsonResponse(String message) {
                super();
                this.message = message;
            }
    
            public String getMessage() {
                return message;
            }
    
            public void setMessage(String message) {
                this.message = message;
            }       
        }
    
        @ExceptionHandler(value = Exception.class)  
        public ResponseEntity<JsonResponse> handleException(Exception e) {
            return new ResponseEntity<JsonResponse>(new JsonResponse(e.getMessage()), HttpStatus.BAD_REQUEST);
        }
    
    }
    

    抛出异常时的 JSON 结果:

    {
        "message": "Something wrong!"
    }
    

    您可以使用此link 了解有关 Spring 异常处理的更多详细信息(附代码示例)。

    【讨论】:

    • 我们如何为 Spring 3.1.4 实现类似的类?
    • 这个话题可以帮到你:stackoverflow.com/questions/6742324/…
    • 这段代码吞噬了我所有 api 中的所有 HTTPStatus 代码,直到我用 @ExceptionHandler(value = Exception.class) public ResponseEntity&lt;JsonResponse&gt; handleException(Exception e) { HttpStatus status = HttpStatus.BAD_REQUEST; ResponseStatus resp = AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class); if (resp != null) { status = resp.code(); } return new ResponseEntity&lt;&gt;(new JsonResponse(e.getMessage()), status); } 替换了胆量
    【解决方案2】:

    HttpEntity 表示一个 HTTP 请求或响应,由 headers 和 body 组成。

    // Only talks about body & headers, but doesn't talk about status code
    public HttpEntity(T body, MultiValueMap<String,String> headers)
    

    ResponseEntity 扩展了 HttpEntity,但也添加了一个 Http 状态码。

    // i.e ResponseEntity = HttpEntity + StatusCode
    public ResponseEntity(T body, MultiValueMap<String,String> headers, HttpStatus statusCode)
    

    因此用于完全配置 HTTP 响应。

    如果您查看 ResponseEntity 的构造函数,您会看到第一个参数为 body,即您可以传递您的对象的确切位置当异常到达时想要作为 http 响应的主体

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-12-20
      • 2016-10-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-23
      • 1970-01-01
      相关资源
      最近更新 更多