在web後臺使用controller、service、dao模式開發時。controller負責調用業務方法和返回前臺數據,service層負責處理業務邏輯返回數據到controller,dao負責訪問數據庫。因爲service返回的數據需要在controller層包裝下才能返回到前臺。而service的返回值只有一種。對於複雜的異常情況(非程序異常)來說是不夠的,所以返回的都是正常業務的數據。
對於此種情況可以使用自定義異常來處理。
基本思路:
1、自定義一個異常類。
2、編寫全局的異常處理類,捕獲自定義異常統一處理,生成前臺可識別的消息返回給前臺。
3、service層處理業務邏輯遇到異常情況時throw自定義異常。
代碼實現:
1、自定義異常類
public class ExpectedException extends RuntimeException {
private static final long serialVersionUID = 4061732202885069884L;
/**
* 錯誤碼
*/
private int code;
/**
* 錯誤描述
*/
private String msg;
public ExpectedException(int code, String msg) {
super(msg);
this.code = code;
this.msg = msg;
}
public ExpectedException(String msg) {
super(msg);
//通用錯誤碼,可以使用常量或枚舉
this.code = 500;
this.msg = msg;
}
/**
* 重寫堆棧填充,不填充錯誤堆棧信息,提高性能
*/
@Override
public Throwable fillInStackTrace() {
return this;
}
}
因爲該異常不是程序異常,所以沒有必要記錄異常棧信息,所以重寫fillInStackTrace方法。且記錄異常棧信息非常影響性能。
2、異常處理類,使用spingboot的@RestControllerAdvice註解來實現。
@RestControllerAdvice
@Slf4j
public class MyExceptionHandler extends BaseController {
@ExceptionHandler(value = Exception.class)
@ResponseBody
public Response defaultExceptionHandler(Exception exception) throws Exception {
Response result = new Response();
result.setSuccess(false);
try {
throw exception;
} catch (ExpectedException e) {
//自定義異常處理,返回前臺能識別的狀態碼和描述
log.error(e.getMessage());
result.setCode(e.getCode());
result.setMessage(e.getMsg());
} catch (Exception e) {
//其他異常統一處理,上面也可以加上一些特別的異常處理
log.error(e.getMessage(), e);
result.setCode(WebError.SYS_ERROR_CODE);
result.setMessage(WebError.SYS_ERROR_MSG);
}
log.info(result.toString());
return result;
}
}
3、service層業務邏輯異常時throw自定義異常
public User getUser(String id){
User user = userDao.get(id);
if (user == null) {
throw new ExpectedException("該用戶不存在");
}
return user;
}