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

时间:2016-02-10 18:30:55

标签: java spring spring-mvc exception-handling

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

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

4 个答案:

答案 0 :(得分:24)

@ExceptionHandler

if( isset( $_GET['sid'] ) ) $client_sid = $_GET['sid']; if( session_id() == null ) session_start(); if( session_id() != $client_sid ) { // noID or wrongID, redirect to mainindex ignore_user_abort(true); header( "HTTP/1.1 403 Forbidden" ); header("Connection: close", true); exit; } else { // get data if( isset( $_GET['data'] ) ) { $data = $_GET['data']; } else if( isset( $_POST['data'] ) ) { $data = $_POST['data']; } else { $data = null; } // do stuff with data // return data as json $resp[0]['data'] = $data; print_r( json_encode( $resp ) ); } works at the Controller level and it is only active for that particular Controller, not globally for the entire application.

HandlerExceptionResolver

This will resolve any exception thrown by the application. It is used to resolve standard Spring exceptions to their corresponding HTTP Status Codes. It does not have control over the body of the response, means it does not set anything to the body of the Response.It does map the status code on the response but the body is null.

@ControllerAdvice

@ExceptionHandler used for global error handling in the Spring MVC application.It also has full control over the body of the response and the status code.

答案 1 :(得分:11)

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

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

答案 2 :(得分:3)

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

@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意味着可以在此处理任何导致任何控制器类的异常。它可以存在于任何包装中      在同一个项目中。

@RestController
@ControllerAdvice
public class GlobalJavaExceptionHandler extends ResponseEntityExceptionHandler{

    @ExceptionHandler(Exception.class)
    public ResponseEntity handleDiffControllerExceptions(){
        return new ResponseEntity(null,HttpStatus.INTERNAL_SERVER_ERROR);
    }

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

答案 3 :(得分:1)

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

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

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

现在来到HandlerExceptionResolver - 这是一个更低级别的界面。 Spring提供了2个实现:

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

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

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

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