spring boot 全局異常處理及自定義異常類


全局異常處理:

在處理controller層拋出的自定義異常時,可以實現@ControllerAdvice注解捕獲,配合@ExceptionHandler來增強所有的@requestMapping方法。
@ExceptionHandler:統一處理某一類異常,從而能夠減少代碼重復率和復雜度
該注解作用對象為方法,並且在運行時有效,value()可以指定異常類。異常參數:包括一般的異常或特定的異常(即自定義異常),如果注解沒有指定異常類,會默認進行映射。

@ControllerAdvice:異常集中處理,更好的使業務邏輯與異常處理剝離開

例如:@ExceptionHandler(Exception.class)  用來捕獲@requestMapping的方法中所有拋出的exception。

代碼:

@ControllerAdvice
public class GlobalDefultExceptionHandler {
//聲明要捕獲的異常
@ExceptionHandler(Exception.class)
@ResponseBody
public String defultExcepitonHandler(HttpServletRequest request,Exception e) {
    return “error”;
}
}
這樣,全局異常處理類完畢。可以添加自己的邏輯。

 

然后還有一個問題,有的時候,我們需要業務邏輯時拋出自定義異常,這個時候需要自定義業務異常類。

定義class:BusinessException ,使他繼承於RuntimeException.

說明:因為某些業務需要進行業務回滾。但spring的事務只針對RuntimeException的進行回滾操作。所以需要回滾就要繼承RuntimeException。

public class BusinessException extends RuntimeException{

}
然后,現在來稍微完善一下這個類。

當我們拋出一個業務異常,一般需要錯誤碼和錯誤信息。有助於我們來定位問題。

所以如下:

1.首先定義一個枚舉類型,把錯誤碼及錯誤信息,組裝起來統一管理。

定義一個業務異常的枚舉。

public enum ResultEnum {

CODE_200("200", ""),
CODE_400("400", "錯誤的請求參數"),
CODE_401("401", "沒有登錄"),
//CODE_402("402", "用戶名或密碼錯誤"),
CODE_403("403", "沒有權限"),
//CODE_404("404", "用戶不存在"),
CODE_405("405", "用戶被凍結"),
//CODE_406("406", "信息重復"),
CODE_500("500", "內部服務器錯誤");

private Integer code;
private String msg;

ResultEnum(Integer code,String msg) {
this.code = code;
this.msg = msg;
}

public Integer getCode() {
return code;
}

public String getMsg() {
return msg;
}
}
2.然后定義一個業務異常。

public class BusinessException extends RuntimeException{

private static final long serialVersionUID = 1L;

private Integer code; //錯誤碼

public BusinessException() {}

public BusinessException(ResultEnum resultEnum) {
super(resultEnum.getMsg());
this.code = resultEnum.getCode();
}

public Integer getCode() {
return code;
}

public void setCode(Integer code) {
this.code = code;
}
}
3.定義一個全局異常處理類:

@ControllerAdvice
public class GlobalDefultExceptionHandler {

 

 

// 根據特定的異常返回指定的 HTTP 狀態碼400
@ResponseStatus(value=HttpStatus.BAD_REQUEST) // 400
@ExceptionHandler(ConstraintViolationException.class)
public ModelAndView handleValidationException(ConstraintViolationException e) {
logger.error(e.getMessage(),e);
Set<ConstraintViolation<?>> errors = e.getConstraintViolations();
return ResultUtil.error(ResultEnum.CODE_400,errors.toString());
}

// 捕捉shiro的異常
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(ShiroException.class)
public ModelAndView handleShiroException(HttpServletResponse resp,HttpServletRequest req,ShiroException e) {
logger.error(e.getMessage(),e);
Object errorMassage = req.getAttribute("error"); //取出shiro異常massage
if(errorMassage !=null) { //返回jwt過濾器異常.(這里只是替換錯誤Massage而已)
return getRedirect(
ResultUtil.error(ResultEnum.CODE_401,errors.toString()));
 }
return ResultUtil.error(ResultEnum.CODE_401,errors.toString());
}

// 捕捉UnauthorizedException
@ResponseStatus(HttpStatus.UNAUTHORIZED)
@ExceptionHandler(UnauthorizedException.class)
public ModelAndView handleUnauthorizedException(HttpServletResponse resp,HttpServletRequest req,UnauthorizedException e) {
logger.error(e.getMessage(),e);
return ResultUtil.error(ResultEnum.CODE_403,errors.toString());
}

//聲明要捕獲的異常(自定義異常和Exception)
@ExceptionHandler(Exception.class)
@ResponseBody
public <T> Result<?> defultExcepitonHandler(HttpServletRequest request,Exception e) {
e.printStackTrace();
if(e instanceof BusinessException) {
Log.error(this.getClass(),"業務異常:"+e.getMessage());
BusinessException businessException = (BusinessException)e;
return ResultUtil.error(businessException.getCode(), businessException.getMessage());
}
//未知錯誤
return ResultUtil.error(-1, "系統異常:\\n"+e);
}

}
判斷這個是否是業務異常。和系統異常就可以分開處理了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM