@ControllerAdvice优于@ExceptionHandler或HandlerExceptionResolver处理exception的优点是什么?

Spring 3.2引入了@ControllerAdvice注释来处理Spring MVC应用程序中的exception。 但在此版本之前,Spring使用@ExceptionHandlerHandlerExceptionResolver来处理Spring MVC应用程序中的exception。 那么为什么Spring 3.2引入了@ControllerAdvice注释来处理exception呢? 我坚信Spring 3.2引入了@ControllerAdvice注释来解决 @ExceptionHandlerHandlerExceptionResolver 的局限性,或者使exception处理更加强大

任何人都可以解释@ControllerAdvice优于@ExceptionHandlerHandlerExceptionResolver处理exception的优势吗?

@ExceptionHandler

@ExceptionHandlerController级别工作 ,它仅对该特定Controller有效,而不是整个应用程序的全局。

HandlerExceptionResolver

这将解决应用程序抛出的任何exception。 它用于将标准Springexception解析为其相应的HTTP状态代码 。 它无法控制响应的主体,意味着它不会对Response的主体设置任何内容。它会在响应中映射状态代码,但正文为null

@ControllerAdvice

@ControllerAdvice用于Spring MVC应用程序中的全局error handling。它还可以完全控制响应主体和状态代码。

@ExceptionHandler是控制器的本地:只有来自此控制器的exception才会路由到他的@ExceptionHandler

@ControllerAdvice是全局的:您可以使用集中的方式来处理exception,绑定等,它适用于所有已定义的控制器。

区别在于:如果我需要配置exception处理代码,那么我需要在我的项目中使用@ExceptionHandler注释,它可以在两个diff.ways中使用:1)使用注释并在同一个控制器中处理exception在每个控制器类中。 例如:

 @RestController public class WSExposingController{ @GetMapping("/getAllDetails/{/id}") public UserDetails myMethod(@PathVariable int id){ UserDetails user = UserDetailsService.getUser(id); return user; } //To handle the exceptions which are resulting from this controller, I can declare an exceptionHandler specifically in the same class @ExceptionHandler(Exception.class) public ResponseEntity handlerSameControllerExceptions(){ return new ResponseEntity(null,HttpStatus.INTERNAL_SERVER_ERROR); } 

}

2)如果我创建一个扩展ResponseEntityExceptionHandler(SpringBoot类)的新类,并且如果我使用@ControllerAdvice注释它,则该类变为globalexceptionhandler,这意味着可以在此处处理导致任何控制器类的任何exception。 它可以存在于同一项目的任何包中。

 @RestController @ControllerAdvice public class GlobalJavaExceptionHandler extends ResponseEntityExceptionHandler{ @ExceptionHandler(Exception.class) public ResponseEntity handleDiffControllerExceptions(){ return new ResponseEntity(null,HttpStatus.INTERNAL_SERVER_ERROR); } 

如果两者都存在于代码中,那么本地优先于全局代码。 理想情况下,第二个选项是更好的选项,因为我们不需要在每个控制器类中添加代码,而这个带有@ControllerAdvice的类可以是一个一站式解决方案,用于因从代码控制器开始到代码的代码而产生的所有exception代码的长度。

@ExceptionHandler可以在本地级别或全局级别使用。 本地级别意味着在控制器本身内使用此注释来仅处理该控制器内的exception。 该控制器抛出的所有错误都将被@ExceptionHandler捕获。 但这意味着如果在不同的控制器中存在类似的exception,则必须在本地再次在该控制器中重写相应的代码。

为了防止每个控制器重复这种类型的exception处理,我们可以在另一个名为@ControllerAdvice的注释的帮助下在全局级别编写@ExceptionHanlder。

@ControllerAdvice不是特定于exception处理的,它还用于在全局级别处理属性,validation或格式化程序绑定。 exception处理上下文中的@ControllerAdvice只是使用@Exceptionhandler注释在全局级别进行exception处理的另一种方法。

现在来到HandlerExceptionResolver – 这是一个更低级别的接口。 Spring提供了2个实现:

  • ResponseStatusExceptionResolver:这支持@ResponseStatus注释的支持
  • ExceptionHandlerExceptionResolver:它支持@ExceptionHandler注释

示例:因此,当您想要处理exception并选择exception处理策略时,您需要考虑在通过注释使用本地或全局exception处理之间进行选择。 您需要如何提供HTTP状态代码,如何将其包装在@Response实体中,如何重定向到处理程序页面,通过flash属性传送数据或获取参数等等。或者可以跳过注释并使用SimpleMappingExceptionResolver并开始将特定exception映射到error handling程序页面URL

在这里,我们不会考虑在此阶段使用HandlerExceptionResolver的较低级别,因为我们正在处理更高级别的实现并基于这些选项构建策略。

使用上面的上下文来回答您的查询 – @ControllerAdvice没有引入exception处理,它是一种可以利用@ExceptionHandler全局处理exception的机制。 HandlerExceptionResolver是一个接口,其实现有助于支持@ResponseStatus和@Exceptionhandler注释。 除非您想要处理与MVC系统相关的exception,因为Spring框架不提供任何适当的exception处理。 因此,如果您需要处理;与错误的@Requestmapping等相关的问题,这些问题不会被控制器捕获,因为它甚至无法在第一个位置到达它,那么HandlerExceptionResolver的实现将是有用的