1. 程式人生 > >《SpringBoot從入門到放棄》之第(五)篇——統一異常處理

《SpringBoot從入門到放棄》之第(五)篇——統一異常處理

在平時的開發測試過程中,經常能看到下面的錯誤頁面,該頁面是SpringBoot提供的預設error對映頁面,該頁面如果直接傳遞給使用者,那將非常的不友好,因此,我們通常需要去實現自定義的異常提示。

建立全域性異常處理類:通過使用@ControllerAdvice定義統一的異常處理類,而不是在每個Controller中逐個定義。@ExceptionHandler用來定義函式針對的異常型別,最後將Exception物件和請求URL對映到自定義的頁面中。

在 src/main/resources/templates 目錄下建立 myError.html 檔案:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>SpringBoot統一異常處理</title>
</head>
<body>
<h2 th:text="${url}"></h2>
<h2 th:text="${exception.message}"></h2>
<h2 th:text="${#dates.format(date, 'yyyy-MM-dd HH:mm:ss')}"></h2>
</body>
</html>

建立 MyException 類,繼承 Exception 類:

public class MyException extends Exception{

    //構造方法,super方法,呼叫的是父類的構造器
    public MyException(String message){
        super(message);
    }
}

建立全域性的異常類,新增@ControllerAdvice註解,方法上新增@ExceptionHandler(value = Exception.class) 註解:

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(value = Exception.class)
    public ModelAndView defaultExceptionHandler(HttpServletRequest request,Exception e)throws Exception{
        ModelAndView mav = new ModelAndView();
        mav.addObject("exception",e);
        mav.addObject("url",request.getRequestURL());
        mav.addObject("date",new Date());
        mav.setViewName("myError");//html的檔名
        return mav;
    }
}

建立MyExceptionController測試類: 

@Controller //不是使用 ResController
public class MyExceptionController {

    @RequestMapping("/myError")
    public String defaultError()throws Exception {
        throw new Exception("我的自定義錯誤資訊");
    }
}

啟動服務,在瀏覽器位址列輸入:http://localhost:9090/myError

實現上面的內容後,我們只需要在 Controller 層的方法裡丟擲 Exception 異常,即可返回我們自定義的錯誤資訊。比如我們新增一個Controller測試方法,除數為0:

@RequestMapping("/login")
    public String userLogin()throws Exception {
        int k = 1 /0 ;
        return "";
    }

啟動服務,瀏覽器地址輸入:http://localhost:9090/login

 

接下來我們改造一下,返回的錯誤資訊是 json 格式的。

建立 ErrorEntity 實體類:

import java.util.Date;

public class ErrorEntity<T> {

    public static final Integer OK = 0;
    public static final Integer ERROR = 100;

    private Integer code;//返回碼
    private String url;//請求url
    private String desc;//錯誤描述
    private Date date;
    private T data;

    public Integer getCode() {
        return code;
    }
    public void setCode(Integer code) {
        this.code = code;
    }
    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }
    public String getDesc() {
        return desc;
    }
    public void setDesc(String desc) {
        this.desc = desc;
    }
    public Date getDate() {
        return date;
    }
    public void setDate(Date date) {
        this.date = date;
    }
    public T getData() {
        return data;
    }
    public void setData(T data) {
        this.data = data;
    }
}

全域性的異常類增加返回 json 格式的方法,在方法增加註解​@ResponseBody(方法 jsonErrorHandler):

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(value = Exception.class)
    public ModelAndView defaultExceptionHandler(HttpServletRequest request,Exception e)throws Exception{
        ModelAndView mav = new ModelAndView();
        mav.addObject("exception",e);
        mav.addObject("url",request.getRequestURL());
        mav.addObject("date",new Date());
        mav.setViewName("myError");//html的檔名
        return mav;
    }

    @ExceptionHandler(value = MyException.class)
    @ResponseBody
    public ErrorEntity<String> jsonErrorHandler(HttpServletRequest request,Exception e)throws Exception{
        ErrorEntity<String> entity = new ErrorEntity<>();
        entity.setCode(ErrorEntity.ERROR);
        entity.setUrl(request.getRequestURL().toString());
        entity.setDesc(e.getMessage());
        entity.setDate(new Date());
        entity.setData("這裡可以返回一些定義的資料。。。");
        return entity;
    }
}

 在類 MyExceptionController 裡增加測試 json 的方法:

import com.test.exception.MyException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller //不是使用 ResController
public class MyExceptionController {

    @RequestMapping("/myError")
    public String myError()throws Exception {
        throw new Exception("我的自定義錯誤資訊");
    }

    @RequestMapping("/login")
    public String userLogin()throws Exception {
        int k = 1 /0 ;
        return "";
    }

    @RequestMapping("/jsonError")
    public String myJsonError()throws MyException {
        throw new MyException("我的自定義錯誤資訊");
    }
}

啟動服務,瀏覽器地址輸入:http://localhost:9090/jsonError

頁面輸出結果:

{"code":100,"url":"http://localhost:9090/jsonError","desc":"我的自定義錯誤資訊","date":"2018-10-16T06:54:35.745+0000","data":"這裡可以返回一些定義的資料。。。"}