在項目開發(fā)過程中,不管是對底層數(shù)據(jù)庫的操作過程,還是業(yè)務(wù)層的處理過程,還是控制層的處理過程,都不可避免會遇到各種可預(yù)知的、不可預(yù)知的異常需要處理。如果對每個過程都單獨作異常處理,那系統(tǒng)的代碼耦合度會變得很高,此外,開發(fā)工作量也會加大而且不好統(tǒng)一,這也增加了代碼的維護成本。
針對這種實際情況,我們需要將所有類型的異常處理從各處理過程解耦出來,這樣既保證了相關(guān)處理過程的功能單一,也實現(xiàn)了異常信息的統(tǒng)一處理和維護。同時,我們也不希望直接把異常拋給用戶,應(yīng)該對異常進行處理,對錯誤信息進行封裝,然后返回一個友好的信息給用戶。
方法如下:
1. 定義返回的統(tǒng)一 json 結(jié)構(gòu)
import lombok.Data;
@Data
public class EJson {
/**
* 異常碼
*/
protected String code;
/**
* 異常信息
*/
protected String msg;
public EJson() {
this.code = "200";
this.msg = "操作成功";
}
public EJson(String code, String msg) {
this.code = code;
this.msg = msg;
}
}2. 處理系統(tǒng)異常
新建一個 GlobalExceptionHandler 全局異常處理類,
@ControllerAdvice 注解即可攔截項目中拋出的異常
@ResponseBody 注解是為了異常處理完之后給調(diào)用方輸出一個 json 格式的封裝 數(shù)據(jù)。
如下:
第一個攔截異常:參數(shù)缺失的時候,會拋出 HttpMessageNotReadableException
第二個攔截異常:空指針異常, NullPointerException
以此類推: 可以定義更多的異常.....................
最后把再定義一個 Exception異常, 前邊沒有被攔截的異常,統(tǒng)統(tǒng)都會在這里被攔截
Exception 異常是父類,所有異常都會繼承該異常,所以我們可以直接攔截 Exception 異常,一勞永逸
@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {
// 打印log
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
/**
* 缺少請求參數(shù)異常
* @param ex HttpMessageNotReadableException
* @return
*/
@ExceptionHandler(MissingServletRequestParameterException.class)
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
public EJson handleHttpMessageNotReadableException(
MissingServletRequestParameterException ex) {
logger.error("缺少請求參數(shù),{}", ex.getMessage());
return new EJson("400", "缺少必要的請求參數(shù)");
}
/**
* 空指針異常
* @param ex NullPointerException
* @return
*/
@ExceptionHandler(NullPointerException.class)
@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
public EJson handleTypeMismatchException(NullPointerException ex) {
logger.error("空指針異常,{}", ex.getMessage());
return new EJson("500", "空指針異常了");
}
/**
* 系統(tǒng)異常 預(yù)期以外異常
* @param ex
* @return
*/
@ExceptionHandler(Exception.class)
@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
public EJson handleUnexpectedServer(Exception ex) {
logger.error("系統(tǒng)異常:", ex);
return new EJson("500", "系統(tǒng)發(fā)生異常,請聯(lián)系管理員");
}
}定義控制器做個測試:
@RestController
@RequestMapping("/exception")
public class ExceptionController {
private static final Logger logger =
LoggerFactory.getLogger(ExceptionController.class);
@PostMapping("/test")
public EJson test(@RequestParam("name") String name,
@RequestParam("sex") String sex) {
logger.info("name:{}", name);
logger.info("sex:{}", sex);
return new EJson();
}
@RequestMapping("/null")
public EJson test1(String name,String sex){
if(sex.equals("男")){
logger.info("性別:{}",sex);
}
return new EJson();
}
@RequestMapping("/byzero")
public EJson test2(){
int result = 1 / 0;
return new EJson();
}
}通過Postman訪問做個測試



