1. Introduction

Uniform exception handling is important for applications. Today we’ll take a look at how Spring does uniform Rest exception handling. We’ll also briefly compare them against each other.

2. @Controller combines with @ExceptionHandler

Declare a method in the controller and mark it with the @ExceptionHandler annotation:

@Controller @RequestMapping("/test") public class TestController { @RequestMapping("/err") @ResponseBody public Object demo1(){ int i = 1 / 0; return new Date(); } @ExceptionHandler({RuntimeException.class}) public ModelAndView fix(Exception ex){ System.out.println(ex.getMessage()); return new ModelAndView("error",new ModelMap("ex",ex.getMessage())); }}Copy the code

Advantages:

  • The priority is the highest.
  • @ExceptionHandlerMultiple method return value types are supported for the tag. It could be a view, it could be a viewjsonAnd so on.

Disadvantages:

  • aControllerIn the@ExceptionHandlerException types on annotations must not appear the same, otherwise the runtime throws exceptions.
  • You need to explicitly declare the type of exception to handle.
  • The scope is only thatControllerIt’s not really a global exception. If you want it to work globally you have to put it in the parent class of all your controllers.

3. @ControllerAdvice combined with @ExceptionHandler

This is an improved version of 2. It implements global exception handling by defining the @ControllerAdvice class and marking the @ExceptionHandler method:

@ControllerAdvice public class TestController { @ExceptionHandler({RuntimeException.class}) public ModelAndView fix(Exception ex){ System.out.println(ex.getMessage()); return new ModelAndView("error",new ModelMap("ex",ex.getMessage())); }}Copy the code

Advantages:

  • Global exception handling.
  • Complete control over the body of the response as well as the status code
  • Multiple exceptions are mapped to the same method to handle together, and it takes full advantage of the updated Restful ResponseEntity response

Disadvantages:

  • aControllerIn the@ExceptionHandlerException types on annotations must not appear the same, otherwise the runtime throws exceptions.
  • You need to explicitly declare the type of exception to handle.

In general, you are advised to use this method to handle exceptions. For the most part, it’s compatible.

4. HandlerExceptionResolver interface

Implement HandlerExceptionResolver interface, here we inherit its abstract AbstractHandlerExceptionResolver:

@Component public class RestResponseStatusExceptionResolver extends AbstractHandlerExceptionResolver { @Override protected ModelAndView doResolveException( HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { try { if (ex instanceof IllegalArgumentException) { return handleIllegalArgument((IllegalArgumentException) ex, response, handler); } //todo more exception } catch (Exception handlerException) { //todo } return null; } private ModelAndView handleIllegalArgument(IllegalArgumentException ex, HttpServletResponse response) throws IOException { response.sendError(HttpServletResponse.SC_CONFLICT); String accept = request.getHeader(HttpHeaders.ACCEPT); //todo more response return new ModelAndView(); }}Copy the code

Advantages:

  • This is a global exception handler.
  • This way global exception handling returnsJSP,velocityThe template view is convenient.
  • Multiple formats of responses are supported, although the overridden method returnsModelAndViewBut because the parameters haveHttpServletResponseWe can use it to customize the response results. For example, if the client asks for inputapplication / json, so in case of an error case, we want to make sure that we return aapplication / jsonEncoded response.

Disadvantages:

  • We need to work with low-levelHttpServletResponseInteraction is the only way to achieve the various forms of response body.
  • The priority is low

5. Exception handling in Spring Boot

If you’re using Spring Boot. We can also do it in a unique way. The advantage is that low-level apis are shielded, but the disadvantage is also obvious, unable to catch specific exceptions.

5.1 implementation ErrorController

Spring Boot, by default, provides a /error mapping to handle all errors, registering the global Whitelabel error Page in the Servlet container and returning it to the client. By implementing the ErrorController interface and registering as a Bean. No more examples here. See BasicErrorController.

5.2 addErrorAttributes

We can also add a Bean of type ErrorAttributes to replace the default exception handling.

@Component public class MyCustomErrorAttributes extends DefaultErrorAttributes { @Override public Map<String, Object> getErrorAttributes( WebRequest webRequest, boolean includeStackTrace) { Map<String, Object> errorAttributes = super.getErrorAttributes(webRequest, includeStackTrace); errorAttributes.put("locale", webRequest.getLocale() .toString()); errorAttributes.remove("error"); //todo your business return errorAttributes; }}Copy the code

5.3 Inheriting base Class BasicErrorController

Spring Boot automatic configuration also provides the BasicErrorController interface exception handling base class, the default is to handle text/ HTML request errors, you can inherit this base class to customize more request types. Add a public method and specify the processing type using the Produce attribute of the @RequestMapping annotation.

 @Component
 public class MyErrorController extends BasicErrorController {
  
     public MyErrorController(ErrorAttributes errorAttributes) {
         super(errorAttributes, new ErrorProperties());
     }
  
     @RequestMapping(produces = MediaType.APPLICATION_XML_VALUE)
     public ResponseEntity<Map<String, Object>> xmlError(HttpServletRequest request) {
          
     //todo your business
  
     }
 }Copy the code

6. Spring 5 ResponseStatusException

In addition, in Spring 5 you can do this by throwing ResponseStatusException.

Benefits:

  • More convenient to use
  • One type, multiple status codes: One exception type can result in many different responses. This reduces tight coupling compared to @ExceptionHandler
  • We won’t have to create as many custom exception classes
  • Because exceptions can be created programmatically, you have better control over exception handling

Disadvantages:

  • Without a common approach to exception handling, it is more difficult to enforce certain application-wide conventions
  • There can be a lot of duplicate code.

7. To summarize

We summarized and analyzed the pros and cons of common and uncommon Spring methods for handling exceptions. I’m sure you can find a solution that suits you. If useful to you please help point a praise, your encouragement, my motivation!

Follow our public id: Felordcn for more information

Personal blog: https://felord.cn