【问题标题】:Catching a ArithmeticException in RestController in SpringBoot 2.0.4.RELEASE在 SpringBoot 2.0.4.RELEASE 的 RestController 中捕获 ArithmeticException
【发布时间】:2019-02-06 07:15:01
【问题描述】:

我有一个基本的 SpringBoot 2.0.4.RELEASE 应用程序。使用 Spring Initializer、JPA、嵌入式 Tomcat、Thymeleaf 模板引擎,并打包为可执行 JAR 文件。

我创建了这个类来管理异常:

@ControllerAdvice
@RestControllerAdvice
public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {

    public RestResponseEntityExceptionHandler() {
        super();
    }


    // 500

    @ExceptionHandler({ NullPointerException.class, IllegalArgumentException.class, IllegalStateException.class, RuntimeException.class })
    /*500*/
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public BodyBuilder handleInternal(final RuntimeException ex, final WebRequest request) {
        logger.error("500 Status Code", ex);

        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

方法处理 RuntimeException 和 ArithmeticException 扩展 RuntimeException。

为了测试它,我创建了这个方法;

GetMapping(path = "/getUsers", consumes = "application/json", produces = "application/json")
public ResponseEntity<List<User>> testErrors(HttpServletRequest request) {

    double ss = 3 /0;

    return ResponseEntity.ok(userService.findAll());

}

预计只会返回HttpStatus.INTERNAL_SERVER_ERROR,但它会返回"

{"timestamp":"2018-08-31T09:21:21.717+0000","status":500,"error":"Internal Server Error","message":"/ by zero","trace":"java.lang.ArithmeticException: / by zero\n\tat ...

用这个方法

 @ExceptionHandler({ NullPointerException.class, IllegalArgumentException.class, IllegalStateException.class, RuntimeException.class })
    /*500*/
    public BodyBuilder handleInternal(final RuntimeException ex, final WebRequest request) {
        logger.error("500 Status Code", ex);
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR);
    }

我有完整的跟踪:{"timestamp":"2018-09-03T07:04:58.803+0000","status":500,"error":"Internal Server Error","message":"/ by zero","trace":"java.lang.ArithmeticException: / by zero\n\tat

有了这个,我在控制台中看不到任何带有 curl 的东西:

 @ExceptionHandler({ NullPointerException.class, IllegalArgumentException.class, IllegalStateException.class, RuntimeException.class })
    /*500*/
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public void handleInternal(final RuntimeException ex, final WebRequest request) {
        logger.error("500 Status Code", ex);

    }

还有另一个,控制台中也没有:

@ExceptionHandler({ NullPointerException.class, IllegalArgumentException.class, IllegalStateException.class, RuntimeException.class })
    /*500*/
    public ResponseEntity<Object> handleInternal(final RuntimeException ex, final WebRequest request) {
        logger.error("500 Status Code", ex);


        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();

    }

【问题讨论】:

    标签: java rest spring-mvc spring-boot


    【解决方案1】:

    用这个

    @RestControllerAdvice//insted of @ControllerAdvice
    public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {    
       @ExceptionHandler(value = { Exception.class, RuntimeException.class })
        @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
        public BodyBuilder handleInternal(final RuntimeException ex, final WebRequest request) {
            logger.error("500 Status Code", ex);
    
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }
    

    【讨论】:

    • 很遗憾,这并不能解决问题。
    【解决方案2】:

    试试这个:

    @ExceptionHandler({NullPointerException.class, IllegalArgumentException.class, IllegalStateException.class, RuntimeException.class})
    /* 500 */
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public void handleInternal(final RuntimeException ex, final WebRequest request) {
        logger.error("500 Status Code", ex);
    
    }
    

    【讨论】:

      【解决方案3】:

      也许piradian 没有具体指出,但问题似乎是你的handleInternal 方法的返回类型。在您提供的代码中,返回类型为BodyBuilder,您返回ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) 返回的值。实际上,正如BodyBuilder 的名字所暗示的,它代表了Builder pattern 的一个实现。在这种情况下,您实际上应该做的是:

      return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
      

      并将方法的返回类型更改为ResponseEntityResponseEntity&lt;Object&gt;(在你的情况下主体是空的,所以没有太大区别)。

      但是,考虑到您的示例中没有返回正文,并且您的方法已经用 @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) 注释,您所能做的就是将返回类型更改为 void 并且不返回任何内容 - 这正是piradian 建议什么。这应该也可以。

      【讨论】:

      • @Poger 你完全正确。但是正如您所写:“考虑到您的示例中没有返回正文,并且您已经使用@ResponseStatus 注释了您的方法”返回一个值是多余的(注释已经明确地表达了需要)并且很少混乱(例如问题出现了- 如果注释响应状态与返回的不同,会发生什么?)。
      • 我完全同意这一点。我想做的只是一步一步地分析案例,以便解释问题的实际原因以及如何逐步修复和改进代码。也许我应该更加强调同时使用注释和返回ResponseEntity 可能不是一个好主意。好点。
      • 我可以使用邮递员看到 HttpStatus.INTERNAL_SERVER_ERROR,而不是 curls
      猜你喜欢
      • 2019-03-25
      • 1970-01-01
      • 2019-02-21
      • 2021-12-22
      • 2016-10-27
      • 2020-01-19
      • 2019-01-31
      • 2018-11-04
      • 2014-12-24
      相关资源
      最近更新 更多