<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>

          減少 try-catch ,這樣做才叫優(yōu)雅!

          共 8501字,需瀏覽 18分鐘

           ·

          2022-06-10 01:49

          文章目錄

          • 情景引入
          • 導入
            • 問題
            • 異常統(tǒng)一處理
            • 出現(xiàn)的情景
          • 開發(fā)環(huán)境
          • 開發(fā)步驟
            • 創(chuàng)建自定義異常
            • 創(chuàng)建消息返回的包裝實體
            • 定義一系列的枚舉返回信息
            • 定義消息返回工具類
            • 定義異常統(tǒng)一處理類(重點)
            • 定義異常處理頁面
          • 效果
            • 開發(fā)環(huán)境
            • 正式環(huán)境
          • 總結

          情景引入

          (我) 呼嚕呼嚕呼嚕呼嚕。。。。。。。。

          (小白) 起床起床起床,,快點起床。。。

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

          (小白) 我遇到了一個很嚴重的問題,想讓你指導指導我!

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

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

          (我) 對呀,這項目開發(fā)本來就是一個團隊的事情,這是很正常的事,有什么大驚小怪呢?

          (小白) 所以,我想著,有沒有什么辦法,可以針對系統(tǒng)中的異常(未知和已知)能夠友好的進行顯示呢?這樣,我們在交流的時候也相對更加方便呀,否則,總是看著一堆亂七八糟的錯誤,挺心煩的。

          (我) 我好像理解了你的意思。你就是想著,能對系統(tǒng)中的異常能夠友好顯示或者說能方便你們團隊開發(fā)嘛。

          (小白) 對的對的,就是這么個意思。

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

          (小白) 真開心,,,,,迫不及待了

          導入

          問題

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

          我們可能都遇到過一個問題,就是開發(fā)環(huán)境和正式上線的環(huán)境是有很大的差別的。開發(fā)環(huán)境是針對我們開發(fā)人員,而正式環(huán)境是一種以用戶的角度來審視我們的整個系統(tǒng)。想想一個問題,如果遇到了我們在開發(fā)中沒有碰到的異常,而用戶卻發(fā)現(xiàn)了,用戶體驗是不是會非常不好,而且這是我們的一個大忌。。

          既然如此,我們也知道,開發(fā)過程中,有如此多的異常可能會出現(xiàn),那么里面就包含著我們已經(jīng)考慮到了的,然而還有一些隱藏的異常卻是我們可能忽視的,所以,為了能夠將那些潛在的異常不被用戶直接發(fā)現(xiàn),而影響用戶體驗,這---------異常統(tǒng)一處理,,,就必不可少!

          異常統(tǒng)一處理

          定義:

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

          出現(xiàn)的情景

          • 開發(fā)人員預測得到的自定義異常:在開發(fā)中,開發(fā)人員對某些可能出現(xiàn)的情形是可以預知的,這時候是一種主動處理的狀態(tài)。
          • 開發(fā)人員無法預測的系統(tǒng)異常:在開發(fā)中,存在著開發(fā)人員無法全面思考到的異常,那么這時候就是一種潛在性的可能異常狀態(tài)。
          • 前端和后臺交互異常:由于前后端的分離,而且前后端的開發(fā)方向也存在著差異,那么就有可能導致異常的出現(xiàn)。

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

          • windows 7 + 渣渣筆記本
          • IDEA + SpringBoot + Mybatis +Mysql

          開發(fā)步驟

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

          分析:在系統(tǒng)中,存在著系統(tǒng)異常和我們人為的自定義異常,所以,為了能夠有效的針對不同異常進行處理,那么擁有我們自定義的異常類是非常有必要的。

          package?com.hnu.csapp.exception;

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

          public?class?MyException?extends?RuntimeException{
          ????//錯誤碼
          ????private?Integer?code;

          ????public?Integer?getCode()?{
          ????????return?code;
          ????}

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

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

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

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

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

          分析:對于后臺返回給前端的數(shù)據(jù)來說,我們很多情況都是返回的JSON格式的數(shù)據(jù)(當然,并不是局限于這一種),那么JSON是一種格式化的形式。

          所以,我們應該有效的針對這樣的形式來給予一定的返回規(guī)范,這樣也方便前端對于我們返回數(shù)據(jù)的解析。

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

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

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

          package?com.hnu.csapp.exception;

          /**
          ?*?@ Author ????:scw
          ?*?@ Description:異常處理實體包裝類,自己用泛型進行寫,擴展性強點
          ?*?@ Modified By:
          ?*?@Version:?1
          ?*/

          public?class?Result<T>?{
          ????//返回碼
          ????private?Integer?code;
          ????//返回消息
          ????private?String?msg;
          ????//返回數(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)中,我們應該有統(tǒng)一的某些編碼對應某些內容,這樣能夠方便開發(fā)人員進行及時的處理。

          package?com.hnu.csapp.exception;

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

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

          ????SUCCESS(200,"成功"),

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

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

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

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

          ????/**
          ?????*?服務異常.?ErrorCode?:?02
          ?????*/

          ????ServiceException(02,?"服務異常"),

          ????/**
          ?????*?業(yè)務錯誤.?ErrorCode?:?03
          ?????*/

          ????MyException(03,"業(yè)務錯誤"),
          ????/**
          ?????*?提示級錯誤.?ErrorCode?:?04
          ?????*/

          ????InfoException(04,?"提示級錯誤"),

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

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

          ????/**
          ?????*?參數(shù)驗證錯誤.?ErrorCode?:?06
          ?????*/

          ????ParamException(06,"參數(shù)驗證錯誤");

          ????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;
          ????}
          }

          定義消息返回工具類

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

          package?com.hnu.csapp.exception;

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

          public?class?ResultUtil?{

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

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

          ????/**
          ?????*?重載返回成功的方法,因為有時候我們不需要任何的消息數(shù)據(jù)被返回
          ?????*?@return
          ?????*/

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

          ????/**
          ?????*?操作失敗的處理流程
          ?????*?@param?code?錯誤碼
          ?????*?@param?msg?錯誤消息
          ?????*?@param?o???錯誤數(shù)據(jù)(其實這個一般都不需要的,因為都已經(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;
          ????}

          ????/**
          ?????*?重載,操作失敗的方法(因為操作失敗一般都不需要返回數(shù)據(jù)內容)
          ?????*?@param?code
          ?????*?@param?msg
          ?????*?@return
          ?????*/

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

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

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

          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)一處理類,方便用戶可以更加友好的看到錯誤信息
          ?*?@ Modified By:
          ?*?@Version:?1
          ?*/

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

          ????@ExceptionHandler(Exception.class)
          ????@ResponseBody
          ????public?Object?handle(HttpServletRequest?req,?Exception?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的請求
          ?????*?@param?request
          ?????*?@return
          ?????*/

          ????public?boolean?isAjax(HttpServletRequest?request){
          ????????return?(request.getHeader("X-Requested-With")?!=?null
          ????????????????&&
          ????????????????"XMLHttpRequest".equals(request.getHeader("X-Requested-With").toString()));
          ????}
          ????/*
          ????//備注:
          ????//這個是正式項目完成之后的錯誤統(tǒng)一處理(開發(fā)情況先用上面的的)
          ????//我們在開發(fā)過程中還是用json格式的會好一些,要不然看錯誤麻煩
          ????@ExceptionHandler(value?=?Exception.class)
          ????public?ModelAndView?defaultErrorHandler(HttpServletRequest?req,?Exception?e)?throws?Exception?{
          ????????e.printStackTrace();
          ????????//判斷是否是Ajax的異常請求(如果是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)內部發(fā)生異常,那么就返回到錯誤頁面進行友好的提示
          ????????????ModelAndView?mav?=?new?ModelAndView();
          ????????????//這些就是要返回到頁面的內容(其實不用都行,反正用戶也不懂,沒必要在頁面顯示都可以,先寫著吧)
          ????????????mav.addObject("exception",?e);
          ????????????mav.addObject("url",?req.getRequestURL());
          ????????????mav.setViewName(DEFAULT_ERROR_VIEW);
          ????????????return?mav;
          ????????}
          ????}
          ????*/


          }

          定義異常處理頁面

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

          效果

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

          正式環(huán)境

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

          總結

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

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

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

          • 登錄攔截
          • 權限管理
          • 日志管理
          • 事務處理
          • 數(shù)據(jù)控制和過濾
          • 。。。

          所以,我們應該學會從一個問題,發(fā)散的看到相關類似的問題,這樣,我們的系統(tǒng)才會更加健壯,高效和可擴展性強。

          來源:blog.csdn.net/Cs_hnu_scw/article/

          details/85097972


          瀏覽 13
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <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>
                  欧美乱伦一区二区 | 日本亚洲色大成网站www久久 | 不卡中文字幕 | 大香蕉伊人在钱 | 国产77777 |