springboot處理異常的5種方式
程序的異常:Throwable
嚴重錯誤問題:Error 我們不處理。這種問題一般都是很嚴重的,我們一般處理不了,比如說內(nèi)存溢出。
問題:Exception
1.運行期問題:RuntimeException 這種問題我們也不處理,因為是你寫代碼的問題,而且這個問題的出現(xiàn)肯定是我們的代碼不夠嚴謹,需要修正代碼的。
2.編譯期問題:不是RuntimeException的異常 必須進行處理的,因為你不處理,編譯就不能通過。
如果程序出現(xiàn)了問題,我們沒有做任何處理,最終JVM會做出默認的處理。
1.把異常的名稱、原因及出現(xiàn)的位置等信息輸出在控制臺。
2.同時會結(jié)束程序。
(但是呢,其余沒有問題的程序就不能繼續(xù)執(zhí)行了)
所以感覺JVM的默認處理不夠好,既然不好那我們就自己來處理唄。
1、自定義錯誤頁面
SpringBoot默認的異常處理機制:springboot默認提供了一套處理異常的機制。一旦程序出現(xiàn)了異常,SpringBoot會向/error的url發(fā)送請求。在springboot中提供了一個叫BasicErrorController 來處理/error 請求,然后跳轉(zhuǎn)到默認顯示異常的頁面來展示異常信息。
如 果 我 們 需 要 將 所 有 的 異 常 統(tǒng)一 跳 轉(zhuǎn) 到 自 定 義 的 錯 誤 頁 面 , 需 要 再
src/main/resources/templates 目錄下創(chuàng)建 error.html 頁面。注意:名稱必須叫 error
還可以在src/main/resources/templates/error目錄下編寫狀態(tài)碼.html文件,會默認先從這里找,找不到再找src/main/resources/templates下的error.html
2、@ExceptionHandle 注解處理異常
上一種方法不管發(fā)生什么異常,都只能跳轉(zhuǎn)到一個頁面,顆粒度太大,這一種方式可以實現(xiàn)對不同的異常做不同的處理。
@RequestMapping @Controller public class ExceptionController { ? ? @PostMapping("/exception") ? ? public String hello(){ ? ? ? ? //int i = 1/0; ? ? ? ? return "index"; ? ? } ? ? /** ? ? ?* 該方法返回ModelAndView:目的是為了可以讓我們封裝視圖和錯誤信息 ? ? ?* @param e 參數(shù) Exception e:會將產(chǎn)生異常對象注入到方法中 ? ? ?* @return ? ? ?*/ ? ? @ExceptionHandler(value = {java.lang.ArithmeticException.class}) ? ? public ModelAndView arithmeticExceptionHandler(Exception e){ ? ? ? ? ModelAndView mv = new ModelAndView(); ? ? ? ? mv.addObject("errorMsg",e); ? ? ? ? mv.setViewName("error"); ? ? ? ? return mv; ? ? } }
優(yōu)點:可以自定義存儲異常信息的key,和跳轉(zhuǎn)視圖的名稱。
缺點:需要編寫大量的異常方法,不能跨controller,如果兩個controller中出現(xiàn)同樣的異常,需要重新編寫異常處理方法。
3、@ControllerAdvice+@ExceptionHandler 注解處理異常
上一種方式必須要在每一個Controler里面重復(fù)寫異常處理代碼,代碼復(fù)用性太差,這一種方法可以實現(xiàn)異常的全局處理。需要創(chuàng)建一個能夠處理異常的全局異常類。在該類上需要添加@ControllerAdvice 注解
/** ?* 全局異常處理類 ?*/ @ControllerAdvice public class GlobalController { ? ? /** ? ? ?* 該方法返回ModelAndView:目的是為了可以讓我們封裝視圖和錯誤信息 ? ? ?* @param e 參數(shù) Exception e:會將產(chǎn)生異常對象注入到方法中 ? ? ?* @return ? ? ?*/ ? ? //攔截的異??梢詫慐xception ? ? @ExceptionHandler(value = {java.lang.ArithmeticException.class}) ? ? public ModelAndView arithmeticExceptionHandler(Exception e){ ? ? ? ? ModelAndView mv = new ModelAndView(); ? ? ? ? mv.addObject("errorMsg",e+"controllerAdvice"); ? ? ? ? mv.setViewName("error"); ? ? ? ? return mv; ? ? } }
缺點:編寫大量的異常處理方法,代碼冗余。
4、配置 SimpleMappingExceptionResolver 處理異常
上一種方式,每處理一種異常就要寫一個處理方法,如果有很多異常需要處理,寫起來會很麻煩,這一種方式可以很好的解決這種問題,需要在全局異常類中添加一個方法完成異常的統(tǒng)一處理。
/** ?* 通過 SimpleMappingExceptionResolver 做全局異常處理 ?*/ @Configuration public class GlobalException { ? ? /** ? ? ?* 該方法必須要有返回值。返回值類型必須是: SimpleMappingExceptionResolver ? ? ?* @return ? ? ?*/ ? ? @Bean ? ? public SimpleMappingExceptionResolver getSimpleMappingExceptionResolver(){ ? ? ? ? SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver(); ? ? ? ? Properties prop = new Properties(); ? ? ? ? //參數(shù)1:異常的全類名 ?參數(shù)2:視圖的名字 ? ? ? ? prop.setProperty("java.lang.ArithmeticException","error"); ? ? ? ? prop.setProperty("java.lang.NullPointerException","error"); ? ? ? ? //設(shè)置異常與視圖的映射信息 ? ? ? ? resolver.setExceptionMappings(prop); ? ? ? ? return resolver; ? ? } }
缺點:不顯示具體異常信息
5、自定義 HandlerExceptionResolver 類處理異常
上一種方式不能在跳轉(zhuǎn)頁面的同時攜帶異常信息,這樣不利于排錯,當前這種方式可以解決上述問題,我們需 要 在全局異常處理類中實現(xiàn)HandlerExceptionResolver 接口。
/** ?* 通過實現(xiàn) HandlerExceptionResolver 接口做全局異常處理 ?*/ @Configuration public class GlobalException implements HandlerExceptionResolver { ? ? @Override ? ? public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { ? ? ? ? ModelAndView mv = new ModelAndView(); ? ? ? ? //判斷不同的異常類型跳轉(zhuǎn)不同視圖 ? ? ? ? if(ex instanceof ArithmeticException){ ? ? ? ? ? ? mv.setViewName("error"); ? ? ? ? } ? ? ? ? if(ex instanceof NullPointerException){ ? ? ? ? ? ? mv.setViewName("error"); ? ? ? ? } ? ? ? ? mv.addObject("errorMsg",ex.toString()); ? ? ? ? return mv; ? ? } }
通用異常處理:
1、自定義異常枚舉類
public enum ExceptionEnum { ? ? //枚舉常量 ? ? PRICE_CANNOT_BE_NULL(500,"商品價格不能為空"), ? ? ; ? ? private int code; ?//狀態(tài)碼 ? ? private String msg; //異常信息 ? ? ExceptionEnum() { ? ? } ? ? ExceptionEnum(int code, String msg) { ? ? ? ? this.code = code; ? ? ? ? this.msg = msg; ? ? } ? ? public int getCode() { ? ? ? ? return code; ? ? } ? ? public void setCode(int code) { ? ? ? ? this.code = code; ? ? } ? ? public String getMsg() { ? ? ? ? return msg; ? ? } ? ? public void setMsg(String msg) { ? ? ? ? this.msg = msg; ? ? } }
2、自定義異常類
/** ?* 自定義異常類,繼承RuntimeException ?*/ public class MyException extends RuntimeException{ ? ? private ExceptionEnum exceptionEnum; ? ? public MyException() { ? ? } ? ? public MyException(ExceptionEnum exceptionEnum) { ? ? ? ? this.exceptionEnum = exceptionEnum; ? ? } ? ? public ExceptionEnum getExceptionEnum() { ? ? ? ? return exceptionEnum; ? ? } ? ? public void setExceptionEnum(ExceptionEnum exceptionEnum) { ? ? ? ? this.exceptionEnum = exceptionEnum; ? ? } ? ? @Override ? ? public String toString() { ? ? ? ? return "MyException{" + ? ? ? ? ? ? ? ? "exceptionEnum=" + exceptionEnum + ? ? ? ? ? ? ? ? '}'; ? ? } }
3、自定義異常結(jié)果處理類
/** ?* 自定義異常結(jié)果處理類 ?*/ public class ResultException { ? ? private Integer statusCode; //狀態(tài)碼 ? ? private String message; ? ? //異常信息 ? ? private Long timeStamp; //時間戳 ? ? public ResultException() { ? ? } ? ? public ResultException(ExceptionEnum em){ ? ? ? ? this.statusCode = em.getCode(); ? ? ? ? this.message = em.getMsg(); ? ? ? ? this.timeStamp = System.currentTimeMillis(); ? ? } ? ? public Integer getStatusCode() { ? ? ? ? return statusCode; ? ? } ? ? public void setStatusCode(Integer statusCode) { ? ? ? ? this.statusCode = statusCode; ? ? } ? ? public String getMessage() { ? ? ? ? return message; ? ? } ? ? public void setMessage(String message) { ? ? ? ? this.message = message; ? ? } ? ? public Long getTimeStamp() { ? ? ? ? return timeStamp; ? ? } ? ? public void setTimeStamp(Long timeStamp) { ? ? ? ? this.timeStamp = timeStamp; ? ? } ? ? @Override ? ? public String toString() { ? ? ? ? return "ResultException{" + ? ? ? ? ? ? ? ? "statusCode=" + statusCode + ? ? ? ? ? ? ? ? ", message='" + message + '\'' + ? ? ? ? ? ? ? ? ", timeStamp=" + timeStamp + ? ? ? ? ? ? ? ? '}'; ? ? } }
4、全局異常處理
/** ?* ?@ControllerAdvice + @ExceptionHandler +自定義異常 ?來做全局異常處理 ?*/ @ControllerAdvice public class GlobalException { ? ? /** ? ? ?* 攔截自定義異常MyException ? ? ?* @param e ? ? ?* @return ? ? ?*/ // ? ?@ExceptionHandler(MyException.class) // ? ?public @ResponseBody ResultException handlerRuntimeException(MyException e){ // ? ? ? ?ExceptionEnum exceptionEnum = e.getExceptionEnum(); // ? ? ? ?ResultException res = new ResultException(exceptionEnum); // ? ? ? ?
到此這篇關(guān)于springboot處理異常的5種方式的文章就介紹到這了,更多相關(guān)springboot處理異常內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java中使用同步回調(diào)和異步回調(diào)的示例詳解
這篇文章主要介紹了Java中使用同步回調(diào)和異步回調(diào)的相關(guān)資料,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-04-04java連接池Druid連接回收DestroyConnectionThread&DestroyTask
這篇文章主要為大家介紹了java連接池Druid連接回收DestroyConnectionThread&DestroyTask示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-09-09Java 使用keytool創(chuàng)建CA證書的操作
這篇文章主要介紹了Java 使用keytool創(chuàng)建CA證書的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-01-01