前言
在设计Restful 风格API时,如何进行错误响应,也是一个重要的环节。我在实践中发现,如果可以统一封装错误响应,那么会给调用者带来很大的便利。下面就来说说使用Spring Boot框架时,如何进行统一的错误响应。
在Spring Boot项目中有3种级别的异常处理:
- 全局的错误处理
- Controller的错误处理
- 具体方法中的try/catch处理
为了演示如何使用上面的方式进行错误处理,我们假定拥有三个类
- BaseException 其它自定义异常类的父类
- CustomException1 继承自BaseException
- CustomException2 继承自BaseException
我们会创建以下几种方法,来触发不同的异常
- ex1() throws BaseException
- ex2() throws CustomException1
- ex3() throws CustomException2
- ex4() throws NullPointerException
- ex5() throws NumberFormatException
接着我们来看如何使用上面提到的处理流程来处理不同的异常。
我们创建一个类,用 **@ControllerAdvice **和 @RestController修饰。 这表明本类可以返回一个Rest的响应。
@ControllerAdvice 表明本类会进行应用全局的异常处理。
@RestController 表明本类是一个Controller
使用 @ExceptionHandler 注解 定义需要捕获的异常类. (基类异常会捕获派生类异常)
用可以通过使用 @ResponseStatus 注解来修改响应的返回状态。
** HomeController.class **
<pre>
package com.ekiras.controller;
import com.ekiras.exception.BaseException;
import com.ekiras.exception.CustomException1;
import com.ekiras.exception.CustomException2;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
-
@author ekansh
-
@since 19/2/16
*/
@RestController
@RequestMapping({"","/"})
public class HomeController {@RequestMapping("/ex1")
public String ex1(){
// 被全局的异常捕获方法 handleBaseException 捕获
throw new BaseException("Base Exception");
}@RequestMapping("/ex2")
public String ex2(){
// 被全局的异常捕获方法 handleCustomException1 捕获
throw new CustomException1();
}@RequestMapping("/ex3")
public String ex3(){
// 被全局的异常捕获方法 handleBaseException 捕获
throw new CustomException2();
}@RequestMapping("/ex4")
public String ex4(){
// 被全局的异常捕获方法 handleBaseException 捕获
throw new NullPointerException("null pointer exception");
}@RequestMapping("/ex5")
public String ex5(){
// 被Controller级的异常捕获方法 nfeHandler 捕获
throw new NumberFormatException("number format exception");
}/**
- This method will handle all the Number Format Exceptions that arise within this controller.
- */
@ExceptionHandler(value = NumberFormatException.class)
public String nfeHandler(NumberFormatException e){
return e.getMessage();
}
}
</pre>
GlobalExceptionHandler.class
<pre>
package com.ekiras.handler.exception;
import com.ekiras.exception.BaseException;
import com.ekiras.exception.CustomException1;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
/**
-
@author ekansh
-
@since 19/2/16
*/
@ControllerAdvice
@RestController
public class GlobalExceptionHandler {@ExceptionHandler(value = CustomException1.class)
public String handleCustomException1(CustomException1 e){
return e.getMessage();
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(value = BaseException.class)
public String handleBaseException(BaseException e){
return e.getMessage();
}
@ExceptionHandler(value = Exception.class)
public String handleException(Exception e){return e.getMessage();}
}
</pre>
结论:
-
handleCustomException1(CustomException1 e)
会捕获所有来自CustomException1的异常。 -
handleBaseException(BaseException e)
会捕获所有来自BaseException and CustomException2的异常。 - **handleException(Exception e) :: **
会捕获所有派生自Exception 类的异常 - 如果有更接近异常类的异常处理方法,那么异常由其优先捕获,否则继续向上查找。
- 我们可以使用全局的异常处理流程来捕获异常进行统一格式的错误响应。
参考
http://www.ekiras.com/2016/02/how-to-do-exception-handling-in-springboot-rest-application.html
网友评论