針對代碼中的異常,常規有兩種處理方式,一種throws直接拋出,另外一種try..catch捕獲。java
在java項目中,有可能存在人爲邏輯的異常,也可能爲取得異常的詳情,或是保證程序在異常時繼續向下執行,會採用第二種處理方式。程序員
可是,代碼中每一處異常都來捕獲,會使代碼什麼冗餘且不利於維護。json
定義一個全局異常處理類,返回統一規範的異常信息;服務器
處理邏輯是,先斷定是否會出現異常,再執行後續具體的業務。網絡
本文主要爲了實現全局異常處理的邏輯,只舉簡單業務app
某公司部門需增長員工,處理流程:1先根據員工編號查詢員工對象,2判斷員工對象是否有信息,便是否不爲空,3如有信息,則說明已存在,無需再添加,若不是,則直接添加。ide
代碼以下:ui
public class MyService {
// 注入dao層
@Autowired
EmployeeecMapper employeeecMapper;
/** * 添加員工信息 * @param employee 員工對象 * @return 影響的行數 */
public int add(Employee employee) {
// 根據id查詢員工對象
Employeeec emp = employeeecMapper.selectByPrimaryKey(employee.getId());
// 判斷是否已有該員工
if (emp != null){
// 已有,拋出異常,異常信息爲已有該員工
throw new RuntimeException("異常代碼:1201,錯誤信息:該員工已存在");
}
// 沒有,插入該員工
return employeeecMapper.insert(emp);
}
}
複製代碼
業務中存在運行時異常和業務邏輯異常,前者不運行時很難察覺,後者在遍佈業務時就能夠定義出來,所以異常分爲不可預知異常和可知異常。流程以下:this
@ControllerAdvice
,控制器加強SpringMVC
統一捕獲。RuntimeException
類型(運行時異常)。定義異常信息類,變量爲錯誤代碼和錯誤信息,捕獲自定義異常時,直接將該對象返回spa
定義一個map,將常見的異常存入其中,並定義錯誤代碼。對於其餘不常見的異常,即map中沒有的,同一一個異常對象返回便可。
一、定義打印異常信息與返回結果的接口
public interface ResultCode {
// 操做是否成功
boolean success();
// 操做結果代碼
long code();
// 提示信息
String message();
}
複製代碼
public interface Response {
public static final boolean SUCCESS = true;
public static final int SUCCESS_CODE = 10000;
}
複製代碼
二、定義打印異常信息的枚舉類和返回結果類
@ToString
public enum CommonCode implements ResultCode {
NO_PAGE(false,404,"沒有信息"),
FAIL(false,500,"操做失敗!"),
SUCCESS(true,200,"操做成功!");
// 結果信息
boolean success;
long code;
String message;
// 帶參構造
CommonCode(boolean success, long code, String message) {
this.success = success;
this.code = code;
this.message = message;
}
@Override
public boolean success() {
return true;
}
@Override
public long code() {
return code;
}
@Override
public String message() {
return message;
}
}
複製代碼
@Data
@ToString
public class ResponseResult implements Response {
boolean success = SUCCESS;
long code = SUCCESS_CODE;
String message;
public ResponseResult(ResultCode resultCode){
this.success = resultCode.success();
this.code = resultCode.code();
this.message = resultCode.message();
}
}
複製代碼
三、定義錯誤異常類
public class CustomException extends RuntimeException{
@Autowired
ResultCode resultCode;
// 帶參構造
public CustomException(ResultCode resultCode){
this.resultCode = resultCode;
}
// getter
public ResultCode getResultCode(){
return resultCode;
}
}
複製代碼
四、定義異常拋出類
public class ExceptionCast {
// 靜態方法
public static void cast(ResultCode resultCode){
throw new CustomException(resultCode);
}
}
複製代碼
五、定義異常捕獲類,使用ControllerAdvice
控制器加強的註解,並在捕獲CustomException異常的方法上加ExceptionHandler
註解,便可捕獲該類的全部異常,返回json數據。
@ControllerAdvice
public class ExceptionCatch {
/** * 捕獲CustomException類異常 * @param customException * @return 結果信息,json數據 */
@ExceptionHandler(CustomException.class)
@ResponseBody
public ResponseResult customException(CustomException customException){
ResultCode resultCode = customException.getResultCode();
return new ResponseResult(resultCode);
}
}
複製代碼
六、在業務中拋出異常
public class MyService {
@Autowired
EmployeeecMapper employeeecMapper;
public int add(Employee employee) {
Employeeec emp = employeeecMapper.selectByPrimaryKey(employee.getId());
if (emp != null){
ExceptionCast.cast(CommonCode.FAIL);
}
return employeeecMapper.insert(emp);
}
}
複製代碼
一、相似可知異常,先在CommonCode類中添加錯誤代碼,如
UNAUTHORISE(false,510,"沒有權限"),
複製代碼
二、在異常捕獲類中添加不可知異常的捕獲方法。該方法中,定義一個只讀的map存儲異常類型的錯誤代碼的映射,map中沒有的元素,統一用錯誤代碼999來定義。
UNKNOWNERROR(false,999,"未知異常"),
複製代碼
@ControllerAdvice
public class ExceptionCatch {
// 定義map,存貯常見錯誤信息。該類map不可修改
private static ImmutableMap<Class<? extends Throwable>,ResultCode> EXCEPTIONS;
// 構建ImmutableMap
protected static ImmutableMap.Builder<Class<? extends Throwable>,ResultCode> builder = ImmutableMap.builder();
@ExceptionHandler(CustomException.class)
@ResponseBody
public ResponseResult customException(CustomException customException){
ResultCode resultCode = customException.getResultCode();
return new ResponseResult(resultCode);
}
/** * 捕獲非自定義類異常 * @param exception * @return */
@ExceptionHandler(Exception.class)
@ResponseBody
public ResponseResult exception(Exception exception){
// 記錄日誌
LOGGER.error("catch exception ==> ",exception.getMessage());
if (EXCEPTIONS == null){
EXCEPTIONS = builder.build();
}
ResultCode resultCode = EXCEPTIONS.get(exception.getClass());
if (resultCode != null){
return new ResponseResult(resultCode);
}else {
return new ResponseResult(CommonCode.UNKNOWNERROR);
}
}
static {
builder.put(HttpMessageNotReadableException.class, CommonCode.INVALID_PARAM);
}
}
複製代碼
完成~~