一、什么是異常處理
異常(exception) 是程序運行過程中發(fā)生的事件, 該事件可以中斷程序指令的正常執(zhí)行流程.
1當Java程序運行時出現問題時,系統會自動檢測到該錯誤,并立即生成一個與該錯誤對應的異常對象
2:然后把該異常對象提交給JAVA虛擬機
3:JAVA虛擬機會自動尋找相應的處理代碼來處理這個異常,如果沒有找到,則程序終止
4:程序員可以自己編寫代碼來撲捉可能出現的異常,并編寫代碼來處理相應的異常.
二、實現方法
1、通過@ControllerAdvice和@ExceptionHandler實現處理controller層的異常
@ControllerAdvice
@ResponseBody //表示返回的對象,Spring會自動把該對象進行json轉化,最后寫入到Response中。
public class GlobalExceptionHandler {
?
@ExceptionHandler(Exception.class) //表示讓Spring捕獲到所有拋出的SignException異常,并交由這個被注解的方法處理。
@ResponseStatus(HttpStatus.BAD_REQUEST) //表示設置狀態(tài)碼。
String handleException(){
return "Exception Deal!";
}
}
這樣方法 handleException() 就會處理所有 Controller 層拋出的 Exception 及其子類的異常。
又因為service層的異常會拋出到controller層,所以service層拋出的異常也會被handleException處理.
2、異常是處理了,但是希望前端頁面能夠看到統一的返回結果,如下:
{
"code": "33316",
"msg": "This is NullPointerException.",
"data": null
}
創(chuàng)建統一的JSON返回對象,code:消息類型,message:消息內容,url:請求的url,data:請求返回的數據
如創(chuàng)建類ResponseDto,無論正確的返回還是異常返回,都返回這個類對象
public class ResponseDto<T> {
//錯誤碼
private String code;
//提示信息
private String msg;
//具體的內容
private T data;
public ResponseDto() {
}
public ResponseDto(String code, String msg) {
this.code = code;
this.msg = msg;
this.data = null;
}
//getter和setter方法。。。
}
controller中,都返回這個對象,如下:
@RequestMapping(value = "/getUser")
public ResponseDto getUser(String id){
ResponseDto dto = new ResponseDto();
dto.setCode("10000");
dto.setMsg("操作成功");
dto.setData(userServiceImpl.getUser(id));
return dto;
}
?
@RequestMapping(value = "/listUser")
public ResponseDto getUser(){
ResponseDto dto = new ResponseDto();
dto.setCode("10000");
dto.setMsg("操作成功");
dto.setData(userServiceImpl.listUser());
return dto;
}
看到有重復代碼,那就需要將重復代碼提取出來,寫一個工具類ResultUtil,在類中定義方法
public static ResponseDto success(Object object){
ResponseDto result = new ResponseDto();
result.setCode("10000");
result.setMsg("操作成功");
result.setData(object);
return result;
}
這樣controller中的方法就可以改為:
@RequestMapping(value = "/getUser")
public ResponseDto getUser(String id){
return ResultUtil.success(userServiceImpl.getUser(id));
}
?
@RequestMapping(value = "/listUser")
public ResponseDto getUser(){
return ResultUtil.success(userServiceImpl.listUser());
}
異常處理的handleException方法也要做出對應的修改,這樣處理異常的返回才能是對應的格式
@ExceptionHandler(Exception.class) //表示讓Spring捕獲到所有拋出的SignException異常,并交由這個被注解的方法處理。
@ResponseBody //表示返回的對象,Spring會自動把該對象進行json轉化,最后寫入到Response中。
@ResponseStatus(HttpStatus.BAD_REQUEST) //表示設置狀態(tài)碼。
String handleException(){
logger.error("Exception Deal!") ;
return ResultUtil.error(CommonConstant.RESPONSE_CODE_UNKNOW_EXCEPTION,e.getMessage());
}
三、對參數進行校驗。
//添加全局異常處理流程,根據需要設置需要處理的異常,本文以MethodArgumentNotValidException為例
@ExceptionHandler(value=MethodArgumentNotValidException.class)
public Object MethodArgumentNotValidHandler(HttpServletRequest request,
MethodArgumentNotValidException exception) {
List<ObjectError> errors =exception.getBindingResult().getAllErrors();
StringBuffer errorMsg=new StringBuffer();
errors.stream().forEach(x -> errorMsg.append(x.getDefaultMessage()).append(";"));
logger.error("---MethodArgumentNotValidException Handler--- ERROR: {}", errorMsg.toString());
respBean.setRespCode(RespCodeConstant.VALIDATE_ERROR);
respBean.setRespDesc(RespCodeConstant.VALIDATE_ERROR_DESC);
respBean.setRespData(errorMsg.toString());
return respBean;
}
在contorller中的方法中添加@Validated校驗
public RespBean getWeeklyVisitTrend(@RequestBody @Validated ParamsDto dto) {
在ParamsDto 里面的字段添加上具體的校驗,以及出錯時打印的信息
@NotBlank(message = "params.dto.begin.date.null")
private String begin_date;