SpringBoot使用ExceptionHandler做異常處理
應(yīng)用程序在運(yùn)行過(guò)程中,會(huì)有大量需要處理的異常。在頁(yè)面解析的一個(gè)工程中,會(huì)存在多個(gè)service類同時(shí)出現(xiàn)頁(yè)面解析異常和解析結(jié)果入庫(kù)異常,而這就表示在程序中需要一個(gè)機(jī)制,去統(tǒng)一處理這些異常,提供統(tǒng)一的異常處理。因?yàn)槲以O(shè)計(jì)這個(gè)結(jié)構(gòu)的主要目的是為了簡(jiǎn)化代碼。
在探尋spring的異常處理機(jī)制的時(shí)候,主要有三種方式來(lái)統(tǒng)一處理異常。三種方式都是使用的@ExceptionHandler注解。
@ExceptionHandler注解解釋:
當(dāng)一個(gè)Controller中有方法加了@ExceptionHandler之后,這個(gè)Controller其他方法中沒有捕獲的異常就會(huì)以參數(shù)的形式傳入加了@ExceptionHandler注解的那個(gè)方法中。
三種方式都需要首先為自己的系統(tǒng)設(shè)計(jì)一個(gè)自定義的異常類,通過(guò)它來(lái)傳遞狀態(tài)碼,以及一些其他參數(shù)信息。
public class ProcessException extends RuntimeException { private static final long serialVersionUID = 1L; // 任務(wù)明細(xì)ID protected String rwmxid; public ProcessException(String rwmxid) { this.rwmxid = rwmxid; } public String getRwmxid() { return rwmxid; } public void setRwmxid(String rwmxid) { this.rwmxid = rwmxid; } }
第一種思路,設(shè)計(jì)一個(gè)基類。類中使用@ExceptionHandler注解 表明要做異常處理的方法
/** * Created by liuruijie. * 處理異常的類,需要處理異常的Controller直接繼承這個(gè)類 */ public class BaseController { /** * 處理Controller拋出的異常 * @param e 異常實(shí)例 * @return Controller層的返回值 */ @ExceptionHandler @ResponseBody public Object expHandler(Exception e){ if(e instanceof SystemException){ SystemException ex= (SystemException) e; return WebResult.buildResult().status(ex.getCode()) .msg(ex.getMessage()); }else{ e.printStackTrace(); return WebResult.buildResult().status(Config.FAIL) .msg("系統(tǒng)錯(cuò)誤"); } } }
這種方式的缺點(diǎn)為:之后所有需要異常處理的Controller都繼承這個(gè)類,從而獲取到異常處理的方法。
雖然這種方式可以解決問(wèn)題,但是極其不靈活,因?yàn)閯?dòng)用了繼承機(jī)制就只為獲取一個(gè)默認(rèn)的方法,這顯然是不好的。
第二種方式,將這個(gè)基類變?yōu)榻涌?,提供此方法的默認(rèn)實(shí)現(xiàn)(也就是接口中的default方法,java8開始支持接口方法的默認(rèn)實(shí)現(xiàn))
/** * Created by liuruijie. * 接口形式的異常處理 */ public interface DataExceptionSolver { @ExceptionHandler @ResponseBody default Object exceptionHandler(Exception e){ try { throw e; } catch (SystemException systemException) { systemException.printStackTrace(); return WebResult.buildResult().status(systemException.getCode()) .msg(systemException.getMessage()); } catch (Exception e1){ e1.printStackTrace(); return WebResult.buildResult().status(Config.FAIL) .msg("系統(tǒng)錯(cuò)誤"); } } }
這種方式雖然沒有占用繼承,但是也不是很優(yōu)雅,因?yàn)閹缀跛械腃ontroller都需要進(jìn)行異常處理,于是我每個(gè)Controller都需要去寫implement DataExceptionSolver,這顯然不是我真正想要的。況且這種方式依賴java8才有的語(yǔ)法,這是一個(gè)很大的局限。
第三種方式,使用加強(qiáng)Controller做全局異常處理。
所謂加強(qiáng)Controller就是@ControllerAdvice注解,有這個(gè)注解的類中的方法的某些注解會(huì)應(yīng)用到所有的Controller里,其中就包括@ExceptionHandler注解。
于是可以寫一個(gè)全局的異常處理類:
/** * @ClassName ExceptionHandle * @Description 統(tǒng)一處理控制層的異常 * @date 2020年3月14日 上午9:55:41 * @version 1.0 */ @ControllerAdvice public class ExceptionHandle { private final Logger log = LoggerFactory.getLogger(getClass()); @ExceptionHandler(ParseException.class) public void parseException(ParseException ex) { ex.printStackTrace(); log.error("parseException ",ExceptionUtil.getMessage(ex)); Map<String,Object> paraMap = new HashMap<String,Object>(); paraMap.put("rwmxid", ex.getRwmxid()); CommonUtil.updateDataLog(paraMap); } @ExceptionHandler(ProcessException.class) public void processException(ProcessException ex) { ex.printStackTrace(); log.error("ProcessException ",ExceptionUtil.getMessage(ex)); Map<String,Object> paraMap = new HashMap<String,Object>(); paraMap.put("rwmxid", ex.getRwmxid()); CommonUtil.updateDataLog(paraMap); } @ExceptionHandler(Exception.class) @ResponseBody public TransEntity<?> error(Exception ex) { ex.printStackTrace(); log.error("Exception ",ExceptionUtil.getMessage(ex)); return TransEntity.error(); } }
如此,我們現(xiàn)在的Controller中的方法就可以很簡(jiǎn)潔了:
/** * Created by liuruijie on 2016/12/28. * 賬號(hào) */ @RestController @RequestMapping("passport") public class PassportController { PassportService passportService; @RequestMapping("login") public Object doLogin(HttpSession session, String username, String password){ User user = passportService.doLogin(username, password); session.setAttribute("user", user); return WebResult.buildResult().redirectUrl("/student/index"); } }
在passprotService的doLogin方法中,可能會(huì)拋出用戶名或密碼錯(cuò)誤等異常,然后就會(huì)交由ExceptionHandle 去處理,直接返回異常信息給前端,然后前端也不需要關(guān)心是否返回了異常,因?yàn)檫@些都已經(jīng)定義好了。
如果我們自定義了異常,也可以在指定拋出我們自定義的異常,然后在全局異常處理類中進(jìn)行處理, @ExceptionHandler(ParseException.class) 表明,會(huì)處理拋出的 ParseException 異常。
到此這篇關(guān)于SpringBoot使用ExceptionHandler做異常處理的文章就介紹到這了,更多相關(guān)SpringBoot使用ExceptionHandler內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于Java網(wǎng)絡(luò)編程和多線程的多對(duì)多聊天系統(tǒng)
這篇文章主要介紹了基于Java網(wǎng)絡(luò)編程和多線程的多對(duì)多聊天系統(tǒng),文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java網(wǎng)絡(luò)編程的小伙伴們有非常好的幫助,需要的朋友可以參考下2021-04-04搭建SpringBoot項(xiàng)目三種方式(圖文教程)
Springboot作為當(dāng)下最主流的java開發(fā)框架,已成為IT從業(yè)人員的入門必備技能,本文主要介紹了搭建SpringBoot項(xiàng)目三種方式,感興趣的可以了解一下2023-09-09簡(jiǎn)單的理解java集合中的HashSet和HashTree幾個(gè)重寫方法
這篇文章主要介紹了簡(jiǎn)單的理解java集合中的HashSet和HashTree幾個(gè)重寫方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10基于request.getAttribute與request.getParameter的區(qū)別詳解
本篇文章小編為大家介紹,基于request.getAttribute與request.getParameter的區(qū)別詳解。需要的朋友參考下2013-04-04如何用注解的方式實(shí)現(xiàn)Mybatis插入數(shù)據(jù)時(shí)返回自增的主鍵Id
這篇文章主要介紹了如何用注解的方式實(shí)現(xiàn)Mybatis插入數(shù)據(jù)時(shí)返回自增的主鍵Id,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07java利用Future實(shí)現(xiàn)多線程執(zhí)行與結(jié)果聚合實(shí)例代碼
這篇文章主要給大家介紹了關(guān)于java利用Future實(shí)現(xiàn)多線程執(zhí)行與結(jié)果聚合的相關(guān)資料,Future模式的核心,去除了主函數(shù)的等待時(shí)間,并使得原本需要等待的時(shí)間段可以用于處理其他業(yè)務(wù)邏輯,需要的朋友可以參考下2021-12-12