Springboot全域性異常處理案例--@ControllerAdvice
阿新 • • 發佈:2021-07-07
1.新增依賴
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.72</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies>
2.自定義一個錯誤介面類,包含錯誤碼和錯誤資訊
package com.example.demo.util; /** * @author lyd * @Description: * @date 16:15 */ public interface BaseErrorInfoInterface { /** * 得到錯誤碼 * * @return {@link String} */ String getResultCode(); /** * 得到錯誤資訊 * * @return {@link String} */ String getResultMsg(); }
3.自定義一個列舉類,實現錯誤介面類,在這個列舉裡面自定義一些錯誤型別
package com.example.demo.util; /** * 常見的列舉 * * @author lyd * @Description: 自定義列舉類 * @date 16:16 */ public enum CommonEnum implements BaseErrorInfoInterface { SUCCESS("200", "成功"), BODY_NOT_MATCH("400", "請求的資料格式不符"), SIGNATURE_NOT_MATCH("401", "請求的數字簽名不匹配!"), OT_FOUND("404", "未找到該資源!"), INTERNAL_SERVER_ERROR("500", "伺服器內部錯誤!"), SERVER_BUSY("503", "伺服器正忙,請稍後再試!"); /** * 錯誤碼 */ private String resultCode; /** * 錯誤描述 */ private String resultMsg; CommonEnum(String resultCode, String resultMsg) { this.resultCode = resultCode; this.resultMsg = resultMsg; } @Override public String getResultCode() { return resultCode; } @Override public String getResultMsg() { return resultMsg; } }
4.自定義一個異常類,等會處理業務異常的時候用
package com.example.demo.exception;
import com.example.demo.util.BaseErrorInfoInterface;
/**
* @author lyd
* @Description: 自定義異常類
* @date 16:25
*/
public class BizException extends RuntimeException {
/**
* 錯誤程式碼
*/
private String errorCode;
/**
* 錯誤資訊
*/
private String errorMsg;
public BizException() {
super();
}
public BizException(String message, String errorMsg) {
super(message);
this.errorMsg = errorMsg;
}
public BizException(String message, String errorCode, String errorMsg) {
super(message);
this.errorCode = errorCode;
this.errorMsg = errorMsg;
}
public BizException(BaseErrorInfoInterface baseErrorInfoInterface) {
super(baseErrorInfoInterface.getResultCode());
this.errorCode = baseErrorInfoInterface.getResultCode();
this.errorMsg = baseErrorInfoInterface.getResultMsg();
}
public BizException(BaseErrorInfoInterface baseErrorInfoInterface, Throwable cause) {
super(baseErrorInfoInterface.getResultCode(), cause);
this.errorCode = baseErrorInfoInterface.getResultCode();
this.errorMsg = baseErrorInfoInterface.getResultMsg();
}
public BizException(Throwable cause, String errorCode, String errorMsg) {
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 synchronized Throwable fillInStackTrace() {
return super.fillInStackTrace();
}
}
5.再定義一個數據響應格式,便於資料互動
package com.example.demo.util;
import com.alibaba.fastjson.JSONObject;
/**
* @author lyd
* @Description: 自定義資料傳輸格式
* @date 16:40
*/
public class ResultBody {
/**
* 響應程式碼
*/
private String code;
/**
* 響應訊息
*/
private String message;
/**
* 響應結果
*/
private Object result;
public ResultBody() {
}
public ResultBody(BaseErrorInfoInterface baseErrorInfoInterface) {
this.code = baseErrorInfoInterface.getResultCode();
this.message = baseErrorInfoInterface.getResultMsg();
}
/**
* 成功
*
* @param data 資料
* @return {@link ResultBody}
*/
public static ResultBody success(Object data) {
ResultBody resultBody = new ResultBody();
resultBody.setCode(CommonEnum.SUCCESS.getResultCode());
resultBody.setMessage(CommonEnum.SUCCESS.getResultMsg());
resultBody.setResult(data);
return resultBody;
}
/**
* 錯誤
*
* @param errorInfo 錯誤資訊
* @return {@link ResultBody}
*/
public static ResultBody error(BaseErrorInfoInterface errorInfo) {
ResultBody resultBody = new ResultBody();
resultBody.setCode(errorInfo.getResultCode());
resultBody.setMessage(errorInfo.getResultMsg());
resultBody.setResult(null);
return resultBody;
}
/**
* 錯誤
*
* @return {@link ResultBody}
*/
public static ResultBody error(String code, String message) {
ResultBody resultBody = new ResultBody();
resultBody.setCode(code);
resultBody.setMessage(message);
resultBody.setResult(null);
return resultBody;
}
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;
}
@Override
public String toString() {
return JSONObject.toJSONString(this);
}
}
6.最關鍵的一步:自定義一個全域性異常處理類,用到兩個註解@ControllerAdvice
@ExceptionHandler
package com.example.demo.exception;
import com.example.demo.util.ResultBody;
import com.example.demo.util.CommonEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
/**
* @author lyd
* @Description:自定義全域性異常處理類
* @date 16:12
*/
@ControllerAdvice
public class MyExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(MyExceptionHandler.class);
/**
* 自定義的業務異常處理程式
*
* @param httpServletRequest http servlet請求
* @param ex
* @return {@link ResultBody}
*/
@ExceptionHandler(value = BizException.class)
@ResponseBody
public ResultBody bizExceptionHandler(HttpServletRequest httpServletRequest, BizException ex) {
logger.error("啦啦啦啦啦發生業務異常,原因是:" + ex.getErrorMsg());
return ResultBody.error(ex.getErrorCode(), ex.getErrorMsg());
}
/**
* 空指標異常處理程式
*
* @param req 要求的事情
* @param e e
* @return {@link ResultBody}
*/
@ExceptionHandler(value = NullPointerException.class)
@ResponseBody
public ResultBody exceptionHandler(HttpServletRequest req, NullPointerException e) {
logger.error("啦啦啦啦發生空指標異常!原因是:", e);
return ResultBody.error(CommonEnum.BODY_NOT_MATCH);
}
/**
* 其他異常處理程式
*
* @param req 要求的事情
* @param e e
* @return {@link ResultBody}
*/
@ExceptionHandler(value = Exception.class)
@ResponseBody
public ResultBody exceptionHandler(HttpServletRequest req, Exception e) {
logger.error("啦啦啦啦發生未知異常!原因是:", e);
return ResultBody.error(CommonEnum.INTERNAL_SERVER_ERROR);
}
}
7.定義一個實體類,等會掉介面測試使用
package com.example.demo.pojo;
import java.io.Serializable;
/**
* @author lyd
* @Description:
* @date 17:19
*/
public class User implements Serializable {
private int id;
private String name;
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
8.controller層定義幾個介面做測試
package com.example.demo.controller;
import com.example.demo.exception.BizException;
import com.example.demo.pojo.User;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
@RestController
public class UserRestController {
@PostMapping("/user")
public boolean insert(User user) {
System.out.println("開始新增...");
//如果姓名為空就手動丟擲一個自定義的異常!
if (user.getName() == null) {
throw new BizException("-1", "使用者姓名不能為空!");
}
return true;
}
@PutMapping("/user")
public boolean update(User user) {
System.out.println("開始更新...");
//這裡故意造成一個空指標的異常,並且不進行處理
String str = null;
str.equals("111");
return true;
}
@DeleteMapping("/user")
public boolean delete(User user) {
System.out.println("開始刪除...");
//這裡故意造成一個字元轉換異常,並且不進行處理
Integer.parseInt("abc123");
System.out.println("發生異常後繼續執行");
return true;
}
@GetMapping("/user")
public List<User> findByUser(User user) {
System.out.println("開始查詢...");
List<User> userList = new ArrayList<>();
User user2 = new User();
user2.setId(1);
user2.setName("liuliu");
user2.setAge(18);
userList.add(user2);
return userList;
}
}
最後使用postman測試
先使用Post請求測試
可以看到有手動異常丟擲
再測一下Delete請求的,看看自動的捕捉異常