@ExceptionHandler
使用@ExceptionHandler注解可以在攔截當前類中方法拋出的異常,如下面例子中
@RestController
@RequestMapping("/user")
public class UserController {
@GetMapping("/throwException")
public String throwException(){
//拋出一個異常
int a = 1/0;
return "abcd";
}
@ExceptionHandler(value = Exception.class)
@ResponseBody
public String handleException(){
return "handle";
}
}
使用get請求中訪問 localhost:8080/user/throwException可以得到如下信息
handle
@ControllerAdvice
看了上面的例子诚些,我們會想 假如有多個controller都會拋出異常飞傀,難道要在每個controller中都寫一個這樣的方法進行異常捕獲嗎?可不可以將ExceptionHandler配置成全局的異常捕獲诬烹,方法很簡單只需要新建一個類在上面添加@ControllerAdvice注解然后將異常攔截方法添加到其中即可
@ControllerAdvice
public class ExceptionHandleAdvice {
@ExceptionHandler(value = Exception.class)
@ResponseBody
public String handleException(){
return "global handle";
}
}
使用全局異常處理返回統(tǒng)一的錯誤信息
在日常工作中開發(fā)API的時候往往需要返回詳細統(tǒng)一的錯誤信息給前端小伙伴方便前端進行錯誤信息的處理和展示(當然你也可以一個接口一個格式砸烦,不怕被打的話( ̄ ̄"))。在這樣的情況如何優(yōu)雅得進行異常處理就變得很重要了绞吁。一下是個人對異常處理的一些意見幢痘,分享給小伙伴參考,有不同意見的小伙伴可以交流家破。
通常我們會通過code表示具體的錯誤類型颜说、message給出錯誤的信息购岗。因此我們可以得到以及基本的錯誤信息模板如下方
{
"code": 404,
"message": "No message available",
"path": "/u",
"timestamp": "2020-02-17T14:20:48.049+0000",
}
定義錯誤信息枚舉
將錯誤信息定義成枚舉可以幫助我們管理code避免相同的錯誤返回不一樣的code值或者不同的錯誤返回了同一個code门粪。
public enum ErrorEnum {
USER_NOT_FOUND_ERROR(1000,"用戶不存在");
ErrorEnum(int code, String message){
this.code = code;
this.message =message;
}
}
定義返回錯誤信息實體類
public class ErrorResponse {
private int code;
private String message;
private LocalDateTime timestamp;
private String path;
public ErrorResponse() {
}
//利用一個靜態(tài)工廠方法快速創(chuàng)建實例
public static ErrorResponse build(ErrorEnum errorEnum,String path){
ErrorResponse errorResponse = new ErrorResponse();
errorResponse.setCode(errorEnum.getCode());
errorResponse.setMessage(errorEnum.getMessage());
errorResponse.setPath(path);
errorResponse.setTimestamp(LocalDateTime.now());
return errorResponse;
}
}
創(chuàng)建基礎異常類
創(chuàng)建一個基礎的異常喊积,讓我們的全局ExceptionHandler攔截這個異常。
public abstract class BaseException extends RuntimeException {
private ErrorEnum error;
public BaseException(ErrorEnum error) {
this.error = error;
}
public ErrorEnum getError() {
return error;
}
public void setError(ErrorEnum error) {
this.error = error;
}
}
創(chuàng)建ControllerAdvice
使用@ControllerAdvice創(chuàng)建全局異常攔截器并攔截我們上面定義好的基礎異常類玄妈,在方法內部進行錯誤信息的返回乾吻。
@ControllerAdvice
public class ExceptionHandleAdvice {
@ExceptionHandler(value = BaseException.class)
//以寫入到response的body方式返回
@ResponseBody
public ErrorResponse handleException(BaseException e, HttpServletRequest request){
return ErrorResponse.build(e.getError(),request.getRequestURI());
}
}
使用
在完成了上面的工作之后,終于到了我們使用的時候拟蜻,在我們使用的時候我們通常都會拋出更加具體的異常绎签、下面我們以獲取用戶信息為例子,當查找不到用戶的時候我們會拋出UserNotFoundException
public class UserNotFoundException extends BaseException {
public UserNotFoundException() {
super(ErrorEnum.USER_NOT_FOUND_ERROR);
}
}
@RestController
@RequestMapping("/user")
public class UserController {
private UserDAO userDAO;
public UserController(UserDAO userDAO) {
this.userDAO = userDAO;
}
@GetMapping("/{userId}")
public User getUserById(@PathVariable("userId") String userId) {
User user = this.userDAO.getUserById(userId);
if (user == null) {
throw new UserNotFoundException();
}
return user;
}
}
快打開你的瀏覽器輸入熟悉的localhost:8080/user/123457酝锅,然后
{
"code": 1000,
"message": "用戶不存在",
"timestamp": "2020-02-17T23:03:46.6924162",
"path": "/user/1234567"
}
以后我們只需要創(chuàng)建和拋出BaseException的子類就可以完成對異常信息的統(tǒng)一格式返回诡必,再也不用擔心被前端小伙伴打了。
最后
以上的代碼只是個人的一種實現屈张,有所不足請小伙伴們給出建議擒权。
如果對你有一點幫助給個start鼓勵一下唄(′?ω?`)。