《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":"這裡可以返回一些定義的資料。。。"}