<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          教你玩轉(zhuǎn) 統(tǒng)一異常處理

          共 16649字,需瀏覽 34分鐘

           ·

          2021-04-08 16:46

          點(diǎn)擊上方 好好學(xué)java ,選擇 星標(biāo) 公眾號(hào)

          重磅資訊,干貨,第一時(shí)間送達(dá)


          今日推薦:推薦 19 個(gè) github 超牛逼項(xiàng)目!

          個(gè)人原創(chuàng)100W +訪問量博客:點(diǎn)擊前往,查看更多

          作者:Cs_hnu_scw

          blog.csdn.net/Cs_hnu_scw/article/details/85097972

          情景引入

          我:呼嚕呼嚕呼嚕呼嚕。。。。。。。。

          小白:起床起床起床,,快點(diǎn)起床。。。

          我:小白,又遇到什么事了,這么火急火燎的,年輕人,做事要穩(wěn)重

          小白:我遇到了一個(gè)很嚴(yán)重的問題,想讓你指導(dǎo)指導(dǎo)我!

          我:哎喲,這次這么虛心請(qǐng)教啦,那我不生氣了,,你說,怎么了呢?

          小白:就是,我在開發(fā)的過程中,因?yàn)槭菆F(tuán)隊(duì)開發(fā),所以,有時(shí)候邏輯就對(duì)不上,然后就會(huì) 莫名其妙的出現(xiàn)一些問題,并且顯示的效果非常難堪,而且也不容易發(fā)現(xiàn)問題,每次都要查看后臺(tái)才能知道問題,可是部署到服務(wù)器之后,都只能看Log日志來定位問題。

          我:對(duì)呀,這項(xiàng)目開發(fā)本來就是一個(gè)團(tuán)隊(duì)的事情,這是很正常的事,有什么大驚小怪呢?

          小白:所以,我想著,有沒有什么辦法,可以針對(duì)系統(tǒng)中的異常(未知和已知)能夠友好的進(jìn)行顯示呢?這樣,我們?cè)诮涣鞯臅r(shí)候也相對(duì)更加方便呀,否則,總是看著一堆亂七八糟的錯(cuò)誤,挺心煩的。我:我好像理解了你的意思。你就是想著,能對(duì)系統(tǒng)中的異常能夠友好顯示或者說能方便你們團(tuán)隊(duì)開發(fā)嘛。

          小白:對(duì)的對(duì)的,就是這么個(gè)意思。

          我:這當(dāng)然有了,而且你現(xiàn)在遇到的這個(gè)問題,其實(shí)在每個(gè)系統(tǒng)中都應(yīng)該有進(jìn)行處理,雖然它比較簡(jiǎn)單,但是不容小視,也有很多重要的東西的呢~那就好好聽課吧!

          小白:真開心,,,,,迫不及待了

          導(dǎo)入

          問題

          針對(duì)Web項(xiàng)目來說,我們都知道,一般都是一個(gè)團(tuán)隊(duì)進(jìn)行開發(fā),而不會(huì)是一個(gè)人單打獨(dú)斗,并且開發(fā)團(tuán)隊(duì)還有前后端的人員,那么有一定的規(guī)范就是必不可少的。

          我們可能都遇到過一個(gè)問題,就是開發(fā)環(huán)境和正式上線的環(huán)境是有很大的差別的。開發(fā)環(huán)境是針對(duì)我們開發(fā)人員,而正式環(huán)境是一種以用戶的角度來審視我們的整個(gè)系統(tǒng)。

          想想一個(gè)問題,如果遇到了我們?cè)陂_發(fā)中沒有碰到的異常,而用戶卻發(fā)現(xiàn)了,用戶體驗(yàn)是不是會(huì)非常不好,而且這是我們的一個(gè)大忌。。

          既然如此,我們也知道,開發(fā)過程中,有如此多的異常可能會(huì)出現(xiàn),那么里面就包含著我們已經(jīng)考慮到了的,然而還有一些隱藏的異常卻是我們可能忽視的,所以,為了能夠?qū)⒛切撛诘漠惓2槐挥脩糁苯影l(fā)現(xiàn),而影響用戶體驗(yàn),這---------異常統(tǒng)一處理,,,就必不可少!

          異常統(tǒng)一處理

          定義:簡(jiǎn)單點(diǎn)說,就是針對(duì)我們系統(tǒng)中的異常,給予一定規(guī)范的處理結(jié)果。(比如,默認(rèn)的情況,就是將異常堆棧信息直接打印到頁面,然而這種是極其丑陋的)

          出現(xiàn)的情景

          1. 開發(fā)人員預(yù)測(cè)得到的自定義異常
            在開發(fā)中,開發(fā)人員對(duì)某些可能出現(xiàn)的情形是可以預(yù)知的,這時(shí)候是一種主動(dòng)處理的狀態(tài)。

          2. 開發(fā)人員無法預(yù)測(cè)的系統(tǒng)異常
            在開發(fā)中,存在著開發(fā)人員無法全面思考到的異常,那么這時(shí)候就是一種潛在性的可能異常狀態(tài)。

          3. 前端和后臺(tái)交互異常
            由于前后端的分離,而且前后端的開發(fā)方向也存在著差異,那么就有可能導(dǎo)致異常的出現(xiàn)。

          開發(fā)環(huán)境

          1. windows 7 + 渣渣筆記本

          2. IDEA + SpringBoot + Mybatis +Mysql

          開發(fā)步驟

          創(chuàng)建自定義異常

          分析:在系統(tǒng)中,存在著系統(tǒng)異常和我們?nèi)藶榈淖远x異常,所以,為了能夠有效的針對(duì)不同異常進(jìn)行處理,那么擁有我們自定義的異常類是非常有必要的。

          package com.hnu.csapp.exception;

          /**
           * @ Author     :scw
           * @ Description:自定義異常,為了區(qū)分系統(tǒng)異常和更方便系統(tǒng)的特定一些處理
           * @ Modified By:
           * @Version: 1
           */

          public class MyException extends RuntimeException{
              //錯(cuò)誤碼
              private Integer code;

              public Integer getCode() {
                  return code;
              }

              public void setCode(Integer code) {
                  this.code = code;
              }

              public MyException(String message) {
                  super(message);
              }

              /**
               * 構(gòu)造器重載,主要是自己考慮某些異常自定義一些返回碼
               * @param code
               * @param message
               */

              public MyException(Integer code,String message) {
                  super(message);
                  this.code = code;
              }
          }

          創(chuàng)建消息返回的包裝實(shí)體

          分析:對(duì)于后臺(tái)返回給前端的數(shù)據(jù)來說,我們很多情況都是返回的JSON格式的數(shù)據(jù)(當(dāng)然,并不是局限于這一種),那么JSON是一種格式化的形式,所以,我們應(yīng)該有效的針對(duì)這樣的形式來給予一定的返回規(guī)范,這樣也方便前端對(duì)于我們返回?cái)?shù)據(jù)的解析。

          比如:很多情況一般是如下的格式:

          {
            "retCode"200,  //通過狀態(tài)碼可以得到消息是否返回正常,然后再?zèng)Q定是否去解析data域的內(nèi)容
           "data": {        //返回的數(shù)據(jù)內(nèi)容
           }
           "retMes": success  //返回的提示內(nèi)容
           
          }

          所以,我們可以定義如下的類:

          package com.hnu.csapp.exception;

          /**
           * @ Author     :scw
           * @ Description:異常處理實(shí)體包裝類,自己用泛型進(jìn)行寫,擴(kuò)展性強(qiáng)點(diǎn)
           * @ Modified By:
           * @Version: 1
           */

          public class Result<T{
              //返回碼
              private Integer code;
              //返回消息
              private String msg;
              //返回?cái)?shù)據(jù)
              private T data;

              public Integer getCode() {
                  return code;
              }

              public void setCode(Integer code) {
                  this.code = code;
              }

              public String getMsg() {
                  return msg;
              }

              public void setMsg(String msg) {
                  this.msg = msg;
              }

              public T getData() {
                  return data;
              }

              public void setData(T data) {
                  this.data = data;
              }
          }

          定義一系列的枚舉返回信息

          分析:在系統(tǒng)中,我們應(yīng)該有統(tǒng)一的某些編碼對(duì)應(yīng)某些內(nèi)容,這樣能夠方便開發(fā)人員進(jìn)行及時(shí)的處理。

          package com.hnu.csapp.exception;

          /**
           * @ Author     :scw
           * @ Description:自定義一些返回狀態(tài)碼,便于本系統(tǒng)的使用,自己先定義如下的,有需要就后續(xù)補(bǔ)充
           * @ Modified By:
           * @Version: 1
           */

          public enum ResultEnum {
              /**
               * 成功.: 200 (因?yàn)閔ttp中的狀態(tài)碼200一般都是表示成功)
               */

              SUCCESS(200,"成功"),

              /**
               * 系統(tǒng)異常. ErrorCode : -1
               */

              SystemException(-1,"系統(tǒng)異常"),

              /**
               * 未知異常. ErrorCode : 01
               */

              UnknownException(01,"未知異常"),

              /**
               * 服務(wù)異常. ErrorCode : 02
               */

              ServiceException(02"服務(wù)異常"),

              /**
               * 業(yè)務(wù)錯(cuò)誤. ErrorCode : 03
               */

              MyException(03,"業(yè)務(wù)錯(cuò)誤"),
              /**
               * 提示級(jí)錯(cuò)誤. ErrorCode : 04
               */

              InfoException(04"提示級(jí)錯(cuò)誤"),

              /**
               * 數(shù)據(jù)庫操作異常. ErrorCode : 05
               */

              DBException(05,"數(shù)據(jù)庫操作異常"),

              /**
               * 參數(shù)驗(yàn)證錯(cuò)誤. ErrorCode : 06
               */

              ParamException(06,"參數(shù)驗(yàn)證錯(cuò)誤");

              private Integer code;

              private String msg;

              ResultEnum(Integer code, String msg) {
                  this.code = code;
                  this.msg = msg;
              }

              public Integer getCode() {
                  return code;
              }

              public String getMsg() {
                  return msg;
              }
          }

          定義消息返回工具類

          分析:對(duì)于消息的返回,這是一個(gè)非常普通的工作,所以,我們可以將其封裝一個(gè)工具類,能夠進(jìn)行有效代碼的封裝,減少多余的代碼。

          package com.hnu.csapp.exception;

          /**
           * @ Author     :scw
           * @ Description:返回消息處理的工具類,主要是處理操作成功和失敗的一些內(nèi)容
           * @ Modified By:
           * @Version: 1
           */

          public class ResultUtil {

              /**
               * 操作成功的處理流程
               * @param object
               * @return
               */

              public static Result getSuccess(Object object){
                  Result result = new Result();
                  //設(shè)置操作成功的返回碼
                  result.setCode(200);
                  //設(shè)置操作成功的消息
                  result.setMsg("成功");
                  result.setData(object);
                  return result;
              }

              /**
               * 重載返回成功的方法,因?yàn)橛袝r(shí)候我們不需要任何的消息數(shù)據(jù)被返回
               * @return
               */

              public static Result getSuccess(){
                  return getSuccess(null);
              }

              /**
               * 操作失敗的處理流程
               * @param code 錯(cuò)誤碼
               * @param msg 錯(cuò)誤消息
               * @param o   錯(cuò)誤數(shù)據(jù)(其實(shí)這個(gè)一般都不需要的,因?yàn)槎家呀?jīng)返回失敗了,數(shù)據(jù)都沒必要返回)
               * @return
               */

              public static Result getError(Integer code, String msg, Object o){
                  Result result = new Result();
                  result.setCode(code);
                  result.setMsg(msg);
                  result.setData(o);
                  return result;
              }

              /**
               * 重載,操作失敗的方法(因?yàn)椴僮魇∫话愣疾恍枰祷財(cái)?shù)據(jù)內(nèi)容)
               * @param code
               * @param msg
               * @return
               */

              public static Result getError(Integer code, String msg){
                  return getError(code, msg, null);
              }
          }

          定義異常統(tǒng)一處理類(重點(diǎn))

          分析:這是如何實(shí)現(xiàn)異常統(tǒng)一處理的關(guān)鍵地方,而且我也將不同的處理情形,進(jìn)行了分開注釋,所以,大家一定可以認(rèn)真的看代碼,我相信你一定能夠明白。

          package com.hnu.csapp.exception;

          import org.slf4j.Logger;
          import org.slf4j.LoggerFactory;
          import org.springframework.web.bind.annotation.ControllerAdvice;
          import org.springframework.web.bind.annotation.ExceptionHandler;
          import org.springframework.web.bind.annotation.ResponseBody;
          import org.springframework.web.servlet.ModelAndView;

          import javax.servlet.http.HttpServletRequest;

          /**
           * @ Author     :scw
           * @ Description:異常統(tǒng)一處理類,方便用戶可以更加友好的看到錯(cuò)誤信息
           * @ Modified By:
           * @Version: 1
           */

          @ControllerAdvice
          public class ExceptionHandle {
              //增加異常日志打印
              private final static Logger logger = LoggerFactory.getLogger(ExceptionHandle.class);
              //設(shè)置異常錯(cuò)誤的頁面
              public static final String DEFAULT_ERROR_VIEW = "error";
              /**
               * 以json的格式進(jìn)行返回內(nèi)容(開發(fā)環(huán)境一般個(gè)人是用這個(gè)比較好)
               * @param e
               * @return
               */

              @ExceptionHandler(Exception.class)
              @ResponseBody
              public Object handle(HttpServletRequest reqException e)
          {
                  //如果是自定義的異常
                  if(e instanceof MyException){
                      MyException myException = (MyException)e;
                      return ResultUtil.getError(myException.getCode(),myException.getMessage());
                  }else{
                      //如果是系統(tǒng)的異常,比如空指針這些異常
                      logger.error("【系統(tǒng)異常】={}",e);
                      return ResultUtil.getError(ResultEnum.SystemException.getCode(),ResultEnum.SystemException.getMsg());
                  }
              }

              /**
               * 判斷是否是Ajax的請(qǐng)求
               * @param request
               * @return
               */

              public boolean isAjax(HttpServletRequest request){
                  return (request.getHeader("X-Requested-With") != null
                          &&
                          "XMLHttpRequest".equals(request.getHeader("X-Requested-With").toString()));
              }
              /*
              //備注:
              //這個(gè)是正式項(xiàng)目完成之后的錯(cuò)誤統(tǒng)一處理(開發(fā)情況先用上面的的)
              //我們?cè)陂_發(fā)過程中還是用json格式的會(huì)好一些,要不然看錯(cuò)誤麻煩
              @ExceptionHandler(value = Exception.class)
              public ModelAndView defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
                  e.printStackTrace();
                  //判斷是否是Ajax的異常請(qǐng)求(如果是Ajax的那么就是返回json格式)
                  if(isAjax(req)){
                      //如果是自定義的異常
                      if(e instanceof MyException){
                          MyException myException = (MyException)e;
                          return ResultUtil.getError(myException.getCode(),myException.getMessage());
                      }else{
                          //如果是系統(tǒng)的異常,比如空指針這些異常
                          logger.error("【系統(tǒng)異常】={}",e);
                          return ResultUtil.getError(ResultEnum.SystemException.getCode(),ResultEnum.SystemException.getMsg());
                      }
                  }else{
                      //如果是系統(tǒng)內(nèi)部發(fā)生異常,那么就返回到錯(cuò)誤頁面進(jìn)行友好的提示
                      ModelAndView mav = new ModelAndView();
                      //這些就是要返回到頁面的內(nèi)容(其實(shí)不用都行,反正用戶也不懂,沒必要在頁面顯示都可以,先寫著吧)
                      mav.addObject("exception", e);
                      mav.addObject("url", req.getRequestURL());
                      mav.setViewName(DEFAULT_ERROR_VIEW);
                      return mav;
                  }
              }
              */


          }

          定義異常處理頁面

          分析:這個(gè)的話,其實(shí)主要是在正式環(huán)境才有,因?yàn)槲覀冊(cè)跍y(cè)試環(huán)境的時(shí)候,一般都還是會(huì)將錯(cuò)誤以JSON或者堆棧的格式顯示在頁面,而當(dāng)上線的時(shí)候,那么就一定要有一個(gè)統(tǒng)一的錯(cuò)誤頁面,這樣就能夠讓用戶發(fā)現(xiàn)不了是系統(tǒng)出現(xiàn)了哪些問題。

          效果

          1:開發(fā)環(huán)境

          在這里插入圖片描述

          2:正式環(huán)境

          分析:當(dāng)出現(xiàn)異常的時(shí)候,則顯示如下的頁面。(該頁面是參考一個(gè)博友的,感覺挺有意思,,老司機(jī)~)

          總結(jié)

          異常統(tǒng)一處理,或許我們看起來實(shí)現(xiàn)非常簡(jiǎn)單,然而,其他它包含的思想?yún)s是一種大局思想,這是我們開發(fā)人員在開發(fā)過程中都應(yīng)該關(guān)注的點(diǎn),我們并不是只需要關(guān)注我們每個(gè)人開發(fā)的那點(diǎn)任務(wù),而要以一種全局的角度去審視整個(gè)項(xiàng)目,這樣也能夠提升我們開問題的高度。

          異常統(tǒng)一處理,是每個(gè)項(xiàng)目都存在的,只是可能實(shí)現(xiàn)的方式不一樣而已,或者顯示的效果不一樣而已,這些都不是關(guān)鍵的地方。

          異常統(tǒng)一處理這個(gè)問題,并不是很難,但是這個(gè)可以幫助我們延伸到其他的一些相關(guān)的開發(fā)層面的知識(shí),比如:

          1. 登錄攔截

          2. 權(quán)限管理

          3. 日志管理

          4. 事務(wù)處理

          5. 數(shù)據(jù)控制和過濾

          6. 。。。

          所以,我們應(yīng)該學(xué)會(huì)從一個(gè)問題,發(fā)散的看到相關(guān)類似的問題,這樣,我們的系統(tǒng)才會(huì)更加健壯,高效和可擴(kuò)展性強(qiáng)。

          感謝你的閱讀

          源碼的話,都已經(jīng)在上面進(jìn)行了貼出

          推薦文章


          更多項(xiàng)目源碼


          瀏覽 27
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日韩一区二区在线观看 | 久久一区二区三区四区五区 | 久久亚洲综合精品人妻 | 国内免费毛片 | 亚洲精品国产精品乱码不卡√香蕉 亚洲日韩一区二区三区四区丨高清 |