[Go] springboot Summary of exception handling in RESTful applications

Source: Internet
Author: User
Tags getmessage

[From] 1190000006749441

Summary of exception Handling in Springboot RESTful application YongshunPublished on August 29, 2016
    • Praise | 6   Collection | the
    • 8.8k views
The difference between @ControllerAdvice and @ExceptionHandler
    • Exceptionhandler, method annotations, for Controller level. Exceptionhandler annotations Define an exception handler for a controler.

    • Controlleradvice, class annotations, acting on the entire Spring project. The Controlleradvice annotation defines a global exception handler.

需要注意的是, ExceptionHandler 的优先级比 ControllerAdvice 高, 即 Controller 抛出的异常如果既可以让 ExceptionHandler 标注的方法处理, 又可以让 ControllerAdvice 标注的类中的方法处理, 则优先让 ExceptionHandler 标注的方法处理.

Handling Exceptions in a Controller

To conveniently display the Controller exception handling method, I created a project Springbootrestfulerrorhandler, whose source code can be found in my Github:github.com/yongshun.
The directory structure of the Springbootrestfulerrorhandler project is as follows:

First we define three custom exceptions:
Baseexception:

class BaseException extends Exception { public BaseException(String message) { super(message); }}

MyException1:

class MyException1 extends BaseException { public MyException1(String message) { super(message); }}

MyException2:

class MyException2 extends BaseException { public MyException2(String message) { super(message); }}

We then throw these exceptions in the Democontroller:

@RestControllerPublicClassDemocontroller {Private Logger Logger = Loggerfactory.getlogger ("Globalexceptionhandler");@RequestMapping ("/ex1")PublicObjectThrowbaseexception()Throws Exception {ThrowNew Baseexception ("This is baseexception."); }@RequestMapping ("/ex2")PublicObjectThrowMyException1()Throws Exception {ThrowNew MyException1 ("This is MyException1."); }@RequestMapping ("/ex3")PublicObjectThrowMyException2()Throws Exception {ThrowNew MyException2 ("This is MyException1."); }@RequestMapping ("/ex4")PublicObjectThrowioexception()Throws Exception {ThrowNew IOException ("This is IOException."); }@RequestMapping ("/ex5")PublicObjectthrownullpointerexception ()  Throws Exception {throw new nullpointerexception ( "This is nullpointerexception.");  @ExceptionHandler (nullpointerexception.class) public string controllerexceptionhandler ( HttpServletRequest req, Exception e) {logger. Error ( "---controllerexception Handler---Host {} invokes URL {} ERROR: {}", Req.getremotehost (), Req.getrequesturl (), E.getmessage ()); return e.getMessage (); }} 
    • /ex1: Throw baseexception

    • /ex2: Throw MyException1

    • /ex3: Throw MyException2

    • /EX4: Throw IOException

    • /EX5: Throw NullPointerException

When Democontroller throws an uncaught exception, we capture and process it in Globalexceptionhandler:
Globalexceptionhandler:

@RestController@ControllerAdvicePublicClassGlobalexceptionhandler {Private Logger Logger = Loggerfactory.getlogger ("Globalexceptionhandler");@ExceptionHandler (value = baseexception.class)@ResponseBodyPublicObjectBaseerrorhandler(HttpServletRequest req, Exception e)Throws Exception {logger.Error"---baseexception Handler---Host {} invokes URL {} ERROR: {}", Req.getremotehost (), Req.getrequesturl (), E.getmessage ()) ;return E.getMessage();} @ExceptionHandler (value = exception.class) @ResponseBody public Object Defaulterrorhandler( HttpServletRequest req, Exception e) throws Exception {logger.  Error ("---defaultexception Handler---Host {} invokes URL {} ERROR: {}", Req.getremotehost (), Req.getrequesturl (), E . GetMessage ()); return E.getMessage();}}              

We see that the Globalexceptionhandler class has two annotations:

    • Restcontroller, indicates that Globalexceptionhandler is a restful Controller that returns a reply in a restful form.

    • Controlleradvice, which indicates that Globalexceptionhandler is a global exception handler.

In Globalexceptionhandler, we used the exceptionhandler annotation to annotate two methods:

    • Exceptionhandler (value = Baseexception.class): Represents baseerrorhandler handling baseexception exception and its child exception.

    • Exceptionhandler (value = Exception.class): Indicates that Defaulterrorhandler handles the Exception exception and the child exception it is using.

要注意的是, 和 try...catch 语句块, 异常处理的顺序也是从具体到一般, 即如果 baseErrorHandler 可以处理此异常, 则调用此方法来处理异常, 反之使用 defaultErrorHandler 来处理异常.

Now that we've implemented the Controller's exception handling, let's test it out next.
These links are accessed separately in the browser, with the following results:
/EX1:

/EX2:

/EX3:

/EX4:

/EX5:

It can be seen that/ex1,/ex2,/ex3 throw exceptions are handled by Globalexceptionhandler.baseerrorhandler; The IOException exception thrown by/ex4 is handled by Globalexceptionhandler.defaulterrorhandler. But why is the nullpointerexception exception thrown by/ex5 not Defaulterrorhandler, but handled by Controllerexceptionhandler ? Looking back to the difference between @ControllerAdvice and @ExceptionHandler This in the section, we know why: because we use in the Democontroller The Exceptionhandler annotation defines a Controller-level exception handler that has a higher priority than the global exception handler, so Spring discovers Controllerexceptionhandler can handle nullpointerexception exceptions, call this method instead of calling the global Defaulterrorhandler method.

Handling 404 Errors Spring MVC

Springboot provides a global handler to handle all HTTP errors by default and maps it to /error. When an HTTP error occurs, such as a 404 error, the internal mechanism of Springboot redirects the page to/error.
For example, there is a default Springboot 404 Exception page.

This page is really ugly, can we customize an exception page? Of course, and Springboot also gave us a hint: this application have no explicit mapping for/error, so you is seeing this as a Fallbac K.
So we can implement a /error mapping Controller.

PublicClassHttperrorhandlerImplementsErrorcontroller {PrivateFinalstatic String Error_path ="/error";/** * Supports the HTML Error View * *@param request *@return */@RequestMapping (value = error_path, produces ="Text/html")Public StringErrorHtml(HttpServletRequest request) {Return "404";} /** * Supports other formats like JSON, XML * *  @param request * 
                           
                             @return */
                             @RequestMapping (value = Error_path)  @ResponseBody public Object error (HttpServletRequest request) { "404";} /** * Returns the path of the error page. *  @return the error path */ @Override public String geterrorpath () {return ERROR_PATH;}}  
                            

According to the above code we see that in order to implement the custom 404 page, we implemented the Errorcontroller interface:

public interface ErrorController {    String getErrorPath();}

There is only one method for this interface, and when an HTTP error occurs, Springboot redirects the page to the page returned by the Geterrorpath method. This allows us to implement a custom error page.

RESTful API

Providing a custom "/error" page is naturally not a problem for Spring MVC services, but if our service is a RESTful service, it will not work.
When the user calls a non-existent RESTful API, we want to record the exception access and return a JSON that represents the error to the client, how can this be implemented?
It is natural to think that we can handle the 404 error code using the same set of handling exceptions.
Well, let's try this idea to see if it works.

Strangely, when we randomly enter a path in the browser, the code does not execute into the exception handling logic, but instead returns an HTML page to us, and what about that?
原来 Spring Boot 中, 当用户访问了一个不存在的链接时, Spring 默认会将页面重定向到 **/error** 上, 而不会抛出异常.
In that case, let's just tell Spring Boot that when a 404 error occurs, an exception is thrown. Add two configurations in Application.properties:

spring.mvc.throw-exception-if-no-handler-found=truespring.resources.add-mappings=false

In the above configuration, the first Spring.mvc.throw-exception-if-no-handler-found tells Springboot to throw an exception directly when a 404 error occurs. The second spring.resources.add-mappings tells Springboot not to map the resource files in our project. These two configurations are exactly what RESTful services need.
After adding these two configurations, let's try again:

As you can see, it is now indeed handled in the Defaulterrorhandler.

This article was published by Yongshun in a personal blog, using the Attribution-NonCommercial-Share 3.0 Chinese mainland license agreement in the same way.
Non-commercial reprint please indicate the author and source. For commercial reprint please contact the author himself
Email: [Email protected]
This article is entitled: Summary of Exception Handling in Springboot RESTful application
This article links to: 1190000006749441

[Go] springboot Summary of exception handling in RESTful applications

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.