SpringBoot 統(tǒng)一異常處理

一、什么是異常處理

異常(exception) 是程序運行過程中發(fā)生的事件, 該事件可以中斷程序指令的正常執(zhí)行流程.
1當Java程序運行時出現(xiàn)問題時,系統(tǒng)會自動檢測到該錯誤,并立即生成一個與該錯誤對應(yīng)的異常對象
2:然后把該異常對象提交給JAVA虛擬機
3:JAVA虛擬機會自動尋找相應(yīng)的處理代碼來處理這個異常,如果沒有找到,則程序終止
4:程序員可以自己編寫代碼來撲捉可能出現(xiàn)的異常,并編寫代碼來處理相應(yīng)的異常.

二、實現(xiàn)方法

1、通過@ControllerAdvice@ExceptionHandler實現(xiàn)處理controller層的異常

@ControllerAdvice
@ResponseBody  //表示返回的對象,Spring會自動把該對象進行json轉(zhuǎn)化,最后寫入到Response中。
public class GlobalExceptionHandler {
?
    @ExceptionHandler(Exception.class) //表示讓Spring捕獲到所有拋出的SignException異常,并交由這個被注解的方法處理。
    @ResponseStatus(HttpStatus.BAD_REQUEST)  //表示設(shè)置狀態(tài)碼。
    String handleException(){
        return "Exception Deal!";
    }
}

這樣方法 handleException() 就會處理所有 Controller 層拋出的 Exception 及其子類的異常。
又因為service層的異常會拋出到controller層,所以service層拋出的異常也會被handleException處理.

2、異常是處理了,但是希望前端頁面能夠看到統(tǒng)一的返回結(jié)果,如下:

{
    "code": "33316",
    "msg": "This is NullPointerException.",
    "data": null
}

創(chuàng)建統(tǒng)一的JSON返回對象,code:消息類型,message:消息內(nèi)容,url:請求的url,data:請求返回的數(shù)據(jù)
如創(chuàng)建類ResponseDto,無論正確的返回還是異常返回,都返回這個類對象

public class ResponseDto<T> {
    //錯誤碼
    private String code;
    //提示信息
    private String msg;
    //具體的內(nèi)容
    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;
    }

看到有重復(fù)代碼,那就需要將重復(fù)代碼提取出來,寫一個工具類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方法也要做出對應(yīng)的修改,這樣處理異常的返回才能是對應(yīng)的格式

    @ExceptionHandler(Exception.class) //表示讓Spring捕獲到所有拋出的SignException異常,并交由這個被注解的方法處理。
    @ResponseBody  //表示返回的對象,Spring會自動把該對象進行json轉(zhuǎn)化,最后寫入到Response中。
    @ResponseStatus(HttpStatus.BAD_REQUEST)  //表示設(shè)置狀態(tài)碼。
    String handleException(){
        logger.error("Exception Deal!") ;
        return ResultUtil.error(CommonConstant.RESPONSE_CODE_UNKNOW_EXCEPTION,e.getMessage());
    }

三、對參數(shù)進行校驗。

 //添加全局異常處理流程,根據(jù)需要設(shè)置需要處理的異常,本文以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;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容