javascript
《SpringBoot从菜鸟到老鸟》之SpringBoot 如何配置全局的异常捕获
SpringBoot 如何配置全局的異常捕獲
SpringBoot中自帶的異常捕獲機(jī)制返回的默認(rèn)頁面比較丑,對(duì)用戶來說不夠人性化。
所以這篇文章來講解SpringBoot鐘自定義全局異常捕獲。
主要講解三種異常捕獲形式:
頁面跳轉(zhuǎn)異常
ajax異常
統(tǒng)一返回異常的形式
分別來看三種形式的全局異常捕獲:
1.頁面跳轉(zhuǎn)異常
首先新建一個(gè)異常:
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";} }瀏覽器請(qǐng)求,會(huì)得到SpringBoot默認(rèn)的異常頁面:
新建異常處理工具類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());//發(fā)生異常的路徑mv.setViewName(ERROR_VIEW);//指定發(fā)生異常之后跳轉(zhuǎn)頁面return mv;} }這里我們使用了@ControllerAdvice標(biāo)注,可以將其理解為增強(qiáng)型控制器,想要了解關(guān)于其更多信息請(qǐng)自行百度。
@ExceptionHandler標(biāo)注用于指定需要攔截的異常。
其余的代碼沒有需要過多解釋的,目的就是在系統(tǒng)中發(fā)生了指定的異常時(shí),進(jìn)行捕獲,并返回指定的異常處理路徑。我們?cè)趓esources/templates下新建my_error.html:
這里有一點(diǎn)需要強(qiáng)調(diào):我之前新建的異常跳轉(zhuǎn)頁面取名為error.html,這樣會(huì)報(bào)錯(cuò)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中有默認(rèn)的異常跳轉(zhuǎn)路徑(可能命名為error),而且其中有timestamp的屬性,而當(dāng)我們發(fā)生異常指定其跳轉(zhuǎn)至error.html時(shí),系統(tǒng)會(huì)以為是要跳轉(zhuǎn)至默認(rèn)的異常處理路徑,就會(huì)去加載timestamp屬性,這時(shí)當(dāng)然是加載不到的,因?yàn)槲覀儾]有設(shè)置這個(gè)屬性。
所以,這里最好不要將自定義的異常跳轉(zhuǎn)路徑命名為error。
我們?cè)僭跒g覽器中請(qǐng)求err/error:
得到了我們想要的結(jié)果,小伙們可以打斷點(diǎn)看一下。當(dāng)然這個(gè)只是一個(gè)測(cè)試頁面,并不美觀。正式環(huán)境中當(dāng)然會(huì)有專業(yè)的美工和前端來設(shè)計(jì)報(bào)錯(cuò)頁面。
2.ajax異常
如果出現(xiàn)ajax異常而不捕獲的話,就會(huì)一直loading,用戶體驗(yàn)更加不好。所以ajax請(qǐng)求也需要處理。
我們首先要將之前創(chuàng)建的MyExceptionHandler類刪除掉,避免其產(chǎn)生影響(只需要將類頭部的@ControllerAdvice標(biāo)注和方法頭部的@ExceptionHandler標(biāo)注注釋掉即可)
然后新建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;} }這里和之前頁面跳轉(zhuǎn)異常的不同在于類頭部的標(biāo)注換成了@RestControllerAdvice,其他的地方基本一致。在這里,當(dāng)ajax異常發(fā)生時(shí),我使用了一個(gè)簡單的包裝類返回信息給前臺(tái)。
在ErrorCtrl中新增兩個(gè)方法:
//跳轉(zhuǎn)到發(fā)生ajax異常頁面@RequestMapping("/ajaxerror")public String ajaxerror(){return "thymeleaf/ajaxerror";}//發(fā)生ajax異常@RequestMapping("/getAjaxerror")public int getAjaxerror(){int a = 1/0;return a;}其中ajaxerror方法用于跳轉(zhuǎn)到前臺(tái),getAjaxerror方法用于接收前臺(tái)ajax請(qǐng)求并制造異常。我們新建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>測(cè)試ajax錯(cuò)誤異常</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("發(fā)生異常:"+ data.message);}},error:function(){alert("error");} })在瀏覽器中發(fā)起請(qǐng)求,跳轉(zhuǎn)至ajaxerror.html頁面,立即向后臺(tái)發(fā)起ajax請(qǐng)求,并發(fā)生1/0異常,這時(shí)會(huì)被自定義的MyAjaxExceptionHandler捕獲到,然后將異常信息等返回前臺(tái)。
3.統(tǒng)一異常處理
web頁面跳轉(zhuǎn)和ajax異常的統(tǒng)一異常處理也是非常簡單的,主要就是整合一下前兩步的思路。可以判斷前端請(qǐng)求request是否是ajax請(qǐng)求,然后采取不同的措施。
我們還是使用第一步中使用的MyExceptionHandler異常處理助手類,將之前寫好的errorHandler方法注釋掉,并在其中添加如下兩個(gè)方法:
@ExceptionHandler(value = Exception.class) public Object errorHandler(HttpServletRequest request,HttpServletResponse response,Exception e)throws Exception{e.printStackTrace();if(isAjax(request)){//是ajax請(qǐng)求CommonRspVo rsp = new CommonRspVo("555",e.getMessage());return rsp;}else{//不是ajax請(qǐng)求ModelAndView mv = new ModelAndView();mv.addObject("exception",e);mv.addObject("url",request.getRequestURL());//發(fā)生異常的路徑mv.setViewName(ERROR_VIEW);//指定發(fā)生異常之后跳轉(zhuǎn)頁面return mv;}}private boolean isAjax(HttpServletRequest request){//判斷request是否是ajax請(qǐng)求return (request.getHeader("X-Requested-With") != null&& "XMLHttpRequest".equals( request.getHeader("X-Requested-With").toString()) );}其中,isAjax方法用于判斷HttpServletRequest是否是ajax請(qǐng)求。
這里需要注意的一點(diǎn)是,我們需要將MyExceptionHandler類頭部的@ControllerAdvice標(biāo)注修改為@RestControllerAdvice,否則在進(jìn)行ajax異常捕獲之后會(huì)報(bào)出TemplateInputException。
我們可以根據(jù)之前的err/error和err/ajaxerror路徑分別進(jìn)行頁面跳轉(zhuǎn)異常和ajax異常的測(cè)試,通過dubug調(diào)試可以更清楚的看到程序的執(zhí)行過程。
IT技術(shù)分享社區(qū)
個(gè)人博客網(wǎng)站:https://programmerblog.xyz
文章推薦程序員效率:畫流程圖常用的工具程序員效率:整理常用的在線筆記軟件遠(yuǎn)程辦公:常用的遠(yuǎn)程協(xié)助軟件,你都知道嗎?51單片機(jī)程序下載、ISP及串口基礎(chǔ)知識(shí)硬件:斷路器、接觸器、繼電器基礎(chǔ)知識(shí)
總結(jié)
以上是生活随笔為你收集整理的《SpringBoot从菜鸟到老鸟》之SpringBoot 如何配置全局的异常捕获的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: win10家庭版下loadrunner1
- 下一篇: gradle idea java ssm