ResponseStatusException类

时间:2019-01-08 16:49:35

标签: java spring controller frameworks

我项目中的所有控制器都从一个使用@ExceptionHandler批注的基本控制器扩展而来。看起来我当前正在使用的东西比春天引入的处理异常的新方法要老一些,我试图通过用最新的ExceptionHandler类替换我的ResponseStatusException注释来更新我的项目。

有关正确执行此操作的任何提示吗?

1 个答案:

答案 0 :(得分:1)

在深入研究ResponseStatusException之前,让我们快速看一下 @ResponseStatus 批注。该注释是在Spring 3中引入的,用于将HTTP状态代码应用于HTTP响应。

我们可以使用@ResponseStatus批注设置HTTP响应中的状态和原因:

@ResponseStatus(code = HttpStatus.NOT_FOUND, reason = "Actor Not Found")
public class ActorNotFoundException extends Exception {
    // ...
}

如果在处理HTTP请求时抛出此异常,则响应将包含此批注中指定的HTTP状态。

@ResponseStatus方法的一个缺点是,它与异常会产生紧密耦合。在我们的示例中,所有类型为ActorNotFoundException的异常都将在响应中生成相同的错误消息和状态代码。

ResponseStatusException

ResponseStatusException是@ResponseStatus的编程替代方案,并且是用于将状态代码应用于HTTP响应的异常的基类。这是RuntimeException,因此不需要在方法签名中明确添加。

Spring提供了3个构造函数来生成ResponseStatusException:

ResponseStatusException(HttpStatus status)
ResponseStatusException(HttpStatus status, java.lang.String reason)
ResponseStatusException(
  HttpStatus status, 
  java.lang.String reason, 
  java.lang.Throwable cause
)

ResponseStatusException,构造函数参数:

  • 状态-将HTTP状态设置为HTTP响应
  • 原因–一条消息,说明设置为HTTP响应的异常
  • 原因– ResponseStatusException的可抛出原因

注意:在Spring中,HandlerExceptionResolver拦截并处理任何引发的但未由Controller处理的异常。

其中一个处理程序ResponseStatusExceptionResolver查找由@ResponseStatus注释的任何ResponseStatusException或未捕获的异常,然后提取HTTP状态代码和原因,并将其包括在HTTP响应中。

ResponseStatusException好处

ResponseStatusException用法的好处不多:

  • 首先,可以分别处理相同类型的异常,并且可以在响应中设置不同的状态代码,从而减少紧密耦合
  • 第二,它避免了不必要的额外异常类的创建
  • 最后,它提供了对异常处理的更多控制,因为可以通过编程方式创建异常

Spring 5引入了ResponseStatusException类。我们可以创建一个提供HttpStatus并提供原因和原因的实例:

@GetMapping("/actor/{id}")
public String getActorName(@PathVariable("id") int id) {
    try {
        return actorService.getActor(id);
    } catch (ActorNotFoundException ex) {
        throw new ResponseStatusException(
        HttpStatus.NOT_FOUND, "Actor Not Found", ex);
    }
}

使用ResponseStatusException有什么好处?

  • 出色的原型制作:我们可以相当快地实现基本解决方案
  • 一种类型,多种状态代码:一种异常类型可以导致多种不同的响应。与@ExceptionHandler相比,这减少了紧密耦合
  • 我们无需创建那么多自定义异常类
  • 由于可以通过编程方式创建异常,因此可以更好地控制异常处理

那权衡又如何呢?

  • 没有统一的异常处理方式:强制执行某些应用程序范围的约定,而不是提供全局方法的@ControllerAdvice
  • 代码复制:我们可能会发现自己在多个控制器中复制代码

我们还应该注意,可以在一个应用程序中组合不同的方法。

例如,我们可以全局实现@ControllerAdvice,也可以局部实现ResponseStatusExceptions。但是,我们需要注意:如果可以通过多种方式处理相同的异常,我们可能会注意到一些令人惊讶的行为。一种可能的约定是始终以一种方式处理一种特定类型的异常。