SpringBoot項目優(yōu)雅的全局異常處理方式(全網最新)
前言
在日常項目開發(fā)中,異常是常見的,但是如何更高效的處理好異常信息,讓我們能快速定位到BUG,是很重要的,不僅能夠提高我們的開發(fā)效率,還能讓你代碼看上去更舒服,SpringBoot的項目已經對有一定的異常處理了,但是對于我們開發(fā)者而言可能就不太合適了,因此我們需要對這些異常進行統(tǒng)一的捕獲并處理。
一、全局異常處理方式一
SpringBoot中,@ControllerAdvice 即可開啟全局異常處理,使用該注解表示開啟了全局異常的捕獲,我們只需在自定義一個方法使用@ExceptionHandler注解然后定義捕獲異常的類型即可對這些捕獲的異常進行統(tǒng)一的處理。
1.1 自定義全局異常類
/**
* @description: 自定義異常處理
* @author: DT
* @date: 2021/4/19 21:17
* @version: v1.0
*/
@ControllerAdvice
public class MyExceptionHandler {
@ExceptionHandler(value =Exception.class)
@ResponseBody
public String exceptionHandler(Exception e){
System.out.println("全局異常捕獲>>>:"+e);
return "全局異常捕獲,錯誤原因>>>"+e.getMessage();
}
}
1.2 手動拋出異常
@GetMapping("/getById/{userId}")
public CommonResult<User> getById(@PathVariable Integer userId){
// 手動拋出異常
int a = 10/0;
return CommonResult.success(userService.getById(userId));
}
1.3 測試打印


很顯然這樣的用戶體驗效果是極差的,雖然這種能夠讓我們知道異常的原因,但是在很多的情況下來說,可能還是不夠人性化,不符合我們的要求。
二、全局異常處理方式二
2.1 定義基礎接口類
/**
* @description: 服務接口類
* @author: DT
* @date: 2021/4/19 21:39
*/
public interface BaseErrorInfoInterface {
/**
* 錯誤碼
* @return
*/
String getResultCode();
/**
* 錯誤描述
* @return
*/
String getResultMsg();
}
2.2 定義枚舉類
/**
* @description: 異常處理枚舉類
* @author: DT
* @date: 2021/4/19 21:41
* @version: v1.0
*/
public enum ExceptionEnum implements BaseErrorInfoInterface{
// 數據操作錯誤定義
SUCCESS("2000", "成功!"),
BODY_NOT_MATCH("4000","請求的數據格式不符!"),
SIGNATURE_NOT_MATCH("4001","請求的數字簽名不匹配!"),
NOT_FOUND("4004", "未找到該資源!"),
INTERNAL_SERVER_ERROR("5000", "服務器內部錯誤!"),
SERVER_BUSY("5003","服務器正忙,請稍后再試!");
/**
* 錯誤碼
*/
private final String resultCode;
/**
* 錯誤描述
*/
private final String resultMsg;
ExceptionEnum(String resultCode, String resultMsg) {
this.resultCode = resultCode;
this.resultMsg = resultMsg;
}
@Override
public String getResultCode() {
return resultCode;
}
@Override
public String getResultMsg() {
return resultMsg;
}
}
2.3 自定義異常類
/**
* @description: 自定義異常類
* @author: DT
* @date: 2021/4/19 21:44
* @version: v1.0
*/
public class BizException extends RuntimeException{
private static final long serialVersionUID = 1L;
/**
* 錯誤碼
*/
protected String errorCode;
/**
* 錯誤信息
*/
protected String errorMsg;
public BizException() {
super();
}
public BizException(BaseErrorInfoInterface errorInfoInterface) {
super(errorInfoInterface.getResultCode());
this.errorCode = errorInfoInterface.getResultCode();
this.errorMsg = errorInfoInterface.getResultMsg();
}
public BizException(BaseErrorInfoInterface errorInfoInterface, Throwable cause) {
super(errorInfoInterface.getResultCode(), cause);
this.errorCode = errorInfoInterface.getResultCode();
this.errorMsg = errorInfoInterface.getResultMsg();
}
public BizException(String errorMsg) {
super(errorMsg);
this.errorMsg = errorMsg;
}
public BizException(String errorCode, String errorMsg) {
super(errorCode);
this.errorCode = errorCode;
this.errorMsg = errorMsg;
}
public BizException(String errorCode, String errorMsg, Throwable cause) {
super(errorCode, cause);
this.errorCode = errorCode;
this.errorMsg = errorMsg;
}
public String getErrorCode() {
return errorCode;
}
public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
}
public String getErrorMsg() {
return errorMsg;
}
public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
}
@Override
public Throwable fillInStackTrace() {
return this;
}
}
2.4 自定義數據傳輸
/**
* @description: 自定義數據傳輸
* @author: DT
* @date: 2021/4/19 21:47
* @version: v1.0
*/
public class ResultResponse {
/**
* 響應代碼
*/
private String code;
/**
* 響應消息
*/
private String message;
/**
* 響應結果
*/
private Object result;
public ResultResponse() {
}
public ResultResponse(BaseErrorInfoInterface errorInfo) {
this.code = errorInfo.getResultCode();
this.message = errorInfo.getResultMsg();
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Object getResult() {
return result;
}
public void setResult(Object result) {
this.result = result;
}
/**
* 成功
*
* @return
*/
public static ResultResponse success() {
return success(null);
}
/**
* 成功
* @param data
* @return
*/
public static ResultResponse success(Object data) {
ResultResponse rb = new ResultResponse();
rb.setCode(ExceptionEnum.SUCCESS.getResultCode());
rb.setMessage(ExceptionEnum.SUCCESS.getResultMsg());
rb.setResult(data);
return rb;
}
/**
* 失敗
*/
public static ResultResponse error(BaseErrorInfoInterface errorInfo) {
ResultResponse rb = new ResultResponse();
rb.setCode(errorInfo.getResultCode());
rb.setMessage(errorInfo.getResultMsg());
rb.setResult(null);
return rb;
}
/**
* 失敗
*/
public static ResultResponse error(String code, String message) {
ResultResponse rb = new ResultResponse();
rb.setCode(code);
rb.setMessage(message);
rb.setResult(null);
return rb;
}
/**
* 失敗
*/
public static ResultResponse error( String message) {
ResultResponse rb = new ResultResponse();
rb.setCode("-1");
rb.setMessage(message);
rb.setResult(null);
return rb;
}
@Override
public String toString() {
return JSONObject.toJSONString(this);
}
}
2.5 自定義全局異常處理
/**
* @description: 自定義異常處理
* @author: DT
* @date: 2021/4/19 21:51
* @version: v1.0
*/
@ControllerAdvice
public class GlobalExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
/**
* 處理自定義的業(yè)務異常
* @param req
* @param e
* @return
*/
@ExceptionHandler(value = BizException.class)
@ResponseBody
public ResultResponse bizExceptionHandler(HttpServletRequest req, BizException e){
logger.error("發(fā)生業(yè)務異常!原因是:{}",e.getErrorMsg());
return ResultResponse.error(e.getErrorCode(),e.getErrorMsg());
}
/**
* 處理空指針的異常
* @param req
* @param e
* @return
*/
@ExceptionHandler(value =NullPointerException.class)
@ResponseBody
public ResultResponse exceptionHandler(HttpServletRequest req, NullPointerException e){
logger.error("發(fā)生空指針異常!原因是:",e);
return ResultResponse.error(ExceptionEnum.BODY_NOT_MATCH);
}
/**
* 處理其他異常
* @param req
* @param e
* @return
*/
@ExceptionHandler(value =Exception.class)
@ResponseBody
public ResultResponse exceptionHandler(HttpServletRequest req, Exception e){
logger.error("未知異常!原因是:",e);
return ResultResponse.error(ExceptionEnum.INTERNAL_SERVER_ERROR);
}
}
2.6 測試代碼
@PostMapping("/add")
public boolean add(@RequestBody User user) {
//如果姓名為空就手動拋出一個自定義的異常!
if(user.getName()==null){
throw new BizException("-1","用戶姓名不能為空!");
}
return true;
}

@PutMapping("/update")
public boolean update(@RequestBody User user) {
//這里故意造成一個空指針的異常,并且不進行處理
String str = null;
str.equals("111");
return true;
}

@DeleteMapping("/delete")
public boolean delete(@RequestBody User user) {
//這里故意造成一個異常,并且不進行處理
Integer.parseInt("abc123");
return true;
}

如果我們想捕獲這個類型轉換異常,是不是再添加一個遺產處理方法就可了。

/**
* 處理類型轉換異常
* @param req
* @param e
* @return
*/
@ExceptionHandler(value = NumberFormatException.class)
@ResponseBody
public ResultResponse exceptionHandler(HttpServletRequest req, NumberFormatException e){
logger.error("發(fā)生類型轉換異常!原因是:",e);
return ResultResponse.error(ExceptionEnum.PARAMS_NOT_CONVERT);
}
PARAMS_NOT_CONVERT("4002","類型轉換不對!"),

自定義全局異常處理除了可以處理上述的數據格式之外,也可以處理頁面的跳轉,只需在新增的異常方法的返回處理上填寫該跳轉的路徑并不使用ResponseBody 注解即可。
總結
異常處理,能夠減少代碼的重復度和復雜度,有利于代碼的維護,并且能夠快速定位到BUG,大大提高我們的開發(fā)效率。
到此這篇關于SpringBoot項目優(yōu)雅的全局異常處理方式(全網最新)的文章就介紹到這了,更多相關SpringBoot 全局異常處理 內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Maven 搭建SpringMVC+Hibernate項目詳解
本文主要介紹Maven 搭建SpringMVC+Hibernate的知識,這里整理了詳細的資料,并附示例代碼,有興趣的小伙伴可以參考下2016-09-09
面試官:java ThreadLocal真的會造成內存泄露嗎
ThreadLocal,java面試過程中的“釘子戶”,在網上也充斥著各種有關ThreadLocal內存泄露的問題,本文換個角度,先思考ThreadLocal體系中的ThreadLocalMap為什么要設計成弱引用2021-08-08
Spring?Boot使用Schedule實現定時任務的方法
這篇文章主要介紹了Spring?Boot使用Schedule實現定時任務,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-03-03

