javascript
《SpringBoot从菜鸟到老鸟》之SpringBoot 如何配置全局的异常捕获
SpringBoot 如何配置全局的異常捕獲
SpringBoot中自帶的異常捕獲機制返回的默認頁面比較丑,對用戶來說不夠人性化。
所以這篇文章來講解SpringBoot鐘自定義全局異常捕獲。
主要講解三種異常捕獲形式:
頁面跳轉異常
ajax異常
統一返回異常的形式
分別來看三種形式的全局異常捕獲:
1.頁面跳轉異常
首先新建一個異常:
package com.topjavaer.exceptiondemo.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping;/*** @author javaHuang* @date 2018/6/19 16:57* @description*/ @Controller @RequestMapping(value = "/err") public class ErrorCtrl {@RequestMapping(value = "/error")public String error(){int a = 1/0;return "abcdefg";} }瀏覽器請求,會得到SpringBoot默認的異常頁面:
新建異常處理工具類MyExceptionHandler:
package com.topjaver.exceptiondemo.utils;import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;/*** @author javaHuang* @date 2018/6/19 17:16* @description*/ @ControllerAdvice public class MyExceptionHandler {public static final String ERROR_VIEW = "my_error";@ExceptionHandler(value = Exception.class)//指定攔截的異常public Object errorHandler(HttpServletRequest request, HttpServletResponse response,Exception e) throws Exception{e.printStackTrace();//打印異常信息ModelAndView mv = new ModelAndView();mv.addObject("exception",e);mv.addObject("url",request.getRequestURL());//發生異常的路徑mv.setViewName(ERROR_VIEW);//指定發生異常之后跳轉頁面return mv;} }這里我們使用了@ControllerAdvice標注,可以將其理解為增強型控制器,想要了解關于其更多信息請自行百度。
@ExceptionHandler標注用于指定需要攔截的異常。
其余的代碼沒有需要過多解釋的,目的就是在系統中發生了指定的異常時,進行捕獲,并返回指定的異常處理路徑。我們在resources/templates下新建my_error.html:
這里有一點需要強調:我之前新建的異常跳轉頁面取名為error.html,這樣會報錯EL1008L:
org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'timestamp' cannot be found on object of type 'java.util.HashMap...
后來在這篇帖子中找到了解決辦法:http://makaidong.com/FlyAway2013/104144_12644765.html,我的理解是,SpringBoot中有默認的異常跳轉路徑(可能命名為error),而且其中有timestamp的屬性,而當我們發生異常指定其跳轉至error.html時,系統會以為是要跳轉至默認的異常處理路徑,就會去加載timestamp屬性,這時當然是加載不到的,因為我們并沒有設置這個屬性。
所以,這里最好不要將自定義的異常跳轉路徑命名為error。
我們再在瀏覽器中請求err/error:
得到了我們想要的結果,小伙們可以打斷點看一下。當然這個只是一個測試頁面,并不美觀。正式環境中當然會有專業的美工和前端來設計報錯頁面。
2.ajax異常
如果出現ajax異常而不捕獲的話,就會一直loading,用戶體驗更加不好。所以ajax請求也需要處理。
我們首先要將之前創建的MyExceptionHandler類刪除掉,避免其產生影響(只需要將類頭部的@ControllerAdvice標注和方法頭部的@ExceptionHandler標注注釋掉即可)
然后新建ajax形式的異常處理工具類,命名為MyAjaxExceptionHandler:
package com.topjavaer.thymeleafdemo.utils; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import javax.servlet.http.HttpServletRequest;/*** @author javaHuang* @date 2018/6/19 18:41* @description*/ @RestControllerAdvice public class MyAjaxExceptionHandler {@ExceptionHandler(value = Exception.class)public CommonRspVo defaultErrorHandler(HttpServletRequest request,Exception e)throws Exception{e.printStackTrace();CommonRspVo rsp = new CommonRspVo("555",e.getMessage());return rsp;} }這里和之前頁面跳轉異常的不同在于類頭部的標注換成了@RestControllerAdvice,其他的地方基本一致。在這里,當ajax異常發生時,我使用了一個簡單的包裝類返回信息給前臺。
在ErrorCtrl中新增兩個方法:
//跳轉到發生ajax異常頁面@RequestMapping("/ajaxerror")public String ajaxerror(){return "thymeleaf/ajaxerror";}//發生ajax異常@RequestMapping("/getAjaxerror")public int getAjaxerror(){int a = 1/0;return a;}其中ajaxerror方法用于跳轉到前臺,getAjaxerror方法用于接收前臺ajax請求并制造異常。我們新建ajaxerror.html及ajaxerror.js:
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.springframework.org/schema/mvc"> <head><meta charset="UTF-8"><title>Title</title><script type="text/javascript" th:src="@{/js/jquery.min.js}"></script> </head> <body><h1>測試ajax錯誤異常</h1><script type="text/javascript" th:src="@{/js/ajaxerror.js}"></script> </body> </html>$.ajax({url:"/err/getAjaxerror",type:"POST",async:false,success:function(data){debugger;if(data.code == "200"){alert("success!");}else {alert("發生異常:"+ data.message);}},error:function(){alert("error");} })在瀏覽器中發起請求,跳轉至ajaxerror.html頁面,立即向后臺發起ajax請求,并發生1/0異常,這時會被自定義的MyAjaxExceptionHandler捕獲到,然后將異常信息等返回前臺。
3.統一異常處理
web頁面跳轉和ajax異常的統一異常處理也是非常簡單的,主要就是整合一下前兩步的思路。可以判斷前端請求request是否是ajax請求,然后采取不同的措施。
我們還是使用第一步中使用的MyExceptionHandler異常處理助手類,將之前寫好的errorHandler方法注釋掉,并在其中添加如下兩個方法:
@ExceptionHandler(value = Exception.class) public Object errorHandler(HttpServletRequest request,HttpServletResponse response,Exception e)throws Exception{e.printStackTrace();if(isAjax(request)){//是ajax請求CommonRspVo rsp = new CommonRspVo("555",e.getMessage());return rsp;}else{//不是ajax請求ModelAndView mv = new ModelAndView();mv.addObject("exception",e);mv.addObject("url",request.getRequestURL());//發生異常的路徑mv.setViewName(ERROR_VIEW);//指定發生異常之后跳轉頁面return mv;}}private boolean isAjax(HttpServletRequest request){//判斷request是否是ajax請求return (request.getHeader("X-Requested-With") != null&& "XMLHttpRequest".equals( request.getHeader("X-Requested-With").toString()) );}其中,isAjax方法用于判斷HttpServletRequest是否是ajax請求。
這里需要注意的一點是,我們需要將MyExceptionHandler類頭部的@ControllerAdvice標注修改為@RestControllerAdvice,否則在進行ajax異常捕獲之后會報出TemplateInputException。
我們可以根據之前的err/error和err/ajaxerror路徑分別進行頁面跳轉異常和ajax異常的測試,通過dubug調試可以更清楚的看到程序的執行過程。
IT技術分享社區
個人博客網站:https://programmerblog.xyz
文章推薦程序員效率:畫流程圖常用的工具程序員效率:整理常用的在線筆記軟件遠程辦公:常用的遠程協助軟件,你都知道嗎?51單片機程序下載、ISP及串口基礎知識硬件:斷路器、接觸器、繼電器基礎知識
總結
以上是生活随笔為你收集整理的《SpringBoot从菜鸟到老鸟》之SpringBoot 如何配置全局的异常捕获的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: win10家庭版下loadrunner1
- 下一篇: 神经稀疏体素场论文笔记