Use of Spring exception handler

Global exception handling using enhanced Controller
The so-called enhanced Controller is the @ ControllerAdvice annotation. Some annotations of the methods in the class with this annotation will be applied to all controllers, including the @ ExceptionHandler annotation.
So you can write a global exception handling class:

/**
 * Created by 47
 * Global exception handling, which captures all exceptions thrown in the Controller.
 */
@ControllerAdvice
public class GlobalExceptionHandler {
   //Handle custom exceptions
   @ExceptionHandler(SystemException.class) 
   @ResponseBody
   public Object customHandler(SystemException e){
      e.printStackTrace();
      return WebResult.buildResult().status(e.getCode()).msg(e.getMessage());
   }
   //Other unhandled exceptions
   @ExceptionHandler(Exception.class)
   @ResponseBody
   public Object exceptionHandler(Exception e){
      e.printStackTrace();
      return WebResult.buildResult().status(Config.FAIL).msg("System error");
   }
}

According to different Spring versions, the advanced points are as follows:

@ControllerAdvice
public class GlobalExceptionHandler {

    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @ExceptionHandler(Exception.class)
    @ResponseBody
    public Result dbExceptionHandler(Exception e){
        logger.error("GlobalExceptionHandler: {}", e);
        return ResultBuilder.failure(null).msg(e.getMessage()).build();
    }
}

Only two exceptions are handled in this class, but most of the needs have been met. If there are still places that need special handling, you can add the handling methods. The implementation method is the most elegant way I know so far.
In this way, the methods in our current Controller can be very simple. For example, the logic of processing login can be written as follows:

/**
 * Created by 47
 * test
 */
@RestController
@RequestMapping("passport")
public class PassportController {
    PassportService passportService;
        @RequestMapping("login")
    public Object doLogin(HttpSession session, String username, String password){
        User user = passportService.doLogin(username, password);
        session.setAttribute("user", user);
        return WebResult.buildResult().redirectUrl("/student/index");
    }
}

In the doLogin method of passprotService, exceptions such as user name or password errors may be thrown, and then they will be handled by GlobalExceptionHandler, which will directly return the exception information to the front end. Then the front end does not need to care whether exceptions are returned, because these have been defined.
The front-end js code only needs to be written as follows:

//land
AJAX.POST("/passport/login", {
    username:name,
    password:psw
})

The process in which an exception flows is:
For example, the doLogin method throws a custom exception with the code of FAIL and the message of user name or password error. Since this exception is not caught in the controller method, it will throw the exception to the GlobalExceptionHandler, and then the GlobalExceptionHandler will return the status code and prompt information to the front end through WebResult. The front end will prompt the user "user name or password error" through the default processing function. For such an interaction, we don't need to write the logic of exception handling at all.

So far, the code has been much simpler and the reusability has been greatly improved.

Tags: Spring

Posted by roel_v on Wed, 11 May 2022 02:39:57 +0300