SpringBoot系列(十)統(tǒng)一異常處理與統(tǒng)一結(jié)果返回

SpringBoot系列(十)統(tǒng)一異常處理與統(tǒng)一結(jié)果返回

往期推薦

SpringBoot系列(一)idea新建Springboot項目

SpringBoot系列(二)入門知識

springBoot系列(三)配置文件詳解

SpringBoot系列(四)web靜態(tài)資源配置詳解

SpringBoot系列(五)Mybatis整合完整詳細版

SpringBoot系列(六)集成thymeleaf詳解版

Springboot系列(七) 集成接口文檔swagger最仑,使用,測試

SpringBoot系列(八)分分鐘學(xué)會Springboot多種解決跨域方式

SpringBoot系列(九)文件上傳的正確姿勢

目錄

引言

?日常開發(fā)過程中赠潦,難免有的程序會因為某些原因拋出異常聘鳞,而這些異常一般都是利用try ,catch的方式處理異常或者throw析蝴,throws的方式拋出異常不管撩匕。這種方法對于程序員來說處理也比較麻煩鹰晨,對客戶來說也不太友好,所以我們希望既能方便程序員編寫代碼止毕,不用過多的自己去處理各種異常編寫重復(fù)的代碼又能提升用戶的體驗模蜡,這時候全局異常處理就顯得很重要也很便捷了,是一種不錯的選擇扁凛。

1. 全局異常捕獲與處理

?因為現(xiàn)在主流的都是前后端分離的項目忍疾,所以我們的異常處理也根據(jù)前后端分離來講述。

?Springboot對于異常的處理也做了不錯的支持谨朝,它提供了一個 @ControllerAdvice注解以及 @ExceptionHandler注解卤妒,前者是用來開啟全局的異常捕獲甥绿,后者則是說明捕獲哪些異常,對那些異常進行處理则披。

@ControllerAdvice
public class MyExceptionHandler {

    @ExceptionHandler(value =Exception.class)
    public String exceptionHandler(Exception e){
        System.out.println("發(fā)生了一個異常"+e);
        return e.getMessage();
    }
}

?上面這段代碼就是說共缕,只要是代碼運行過程中有異常就會進行捕獲,并輸出出這個異常士复。然后我們隨便編寫一個會發(fā)生異常的代碼图谷,測試出來的異常是這樣的。


1.png

?這對于我們前后端分離來說并不好阱洪,前后端分離之后唯一的交互就是json了便贵,我們也希望將后端的異常變成json返回給前端處理。下面我們看看統(tǒng)一結(jié)果處理冗荸。

2. 統(tǒng)一結(jié)果返回與統(tǒng)一異常

代碼:

public class Result<T> {
    //是否成功
    private Boolean success;
    //狀態(tài)碼
    private Integer code;
    //提示信息
    private String msg;
    //數(shù)據(jù)
    private T data;
    public Result() {

    }
    //自定義返回結(jié)果的構(gòu)造方法
    public Result(Boolean success,Integer code, String msg,T data) {
        this.success = success;
        this.code = code;
        this.msg = msg;
        this.data = data;
    }
    //自定義異常返回的結(jié)果
    public static Result defineError(DefinitionException de){
        Result result = new Result();
        result.setSuccess(false);
        result.setCode(de.getErrorCode());
        result.setMsg(de.getErrorMsg());
        result.setData(null);
        return result;
    }
    //其他異常處理方法返回的結(jié)果
    public static Result otherError(ErrorEnum errorEnum){
        Result result = new Result();
        result.setMsg(errorEnum.getErrorMsg());
        result.setCode(errorEnum.getErrorCode());
        result.setSuccess(false);
        result.setData(null);
        return result;
    }
}

?說明:其中省略了get承璃,set方法。另外方法之中包含了一個自定義的枚舉俏竞。代碼如下:

public enum ErrorEnum {
    // 數(shù)據(jù)操作錯誤定義
    SUCCESS(200, "nice"),
    NO_PERMISSION(403,"你沒得權(quán)限"),
    NO_AUTH(401,"你能不能先登錄一下"),
    NOT_FOUND(404, "未找到該資源!"),
    INTERNAL_SERVER_ERROR(500, "服務(wù)器跑路了"),
    ;

    /** 錯誤碼 */
    private Integer errorCode;

    /** 錯誤信息 */
    private String errorMsg;

    ErrorEnum(Integer errorCode, String errorMsg) {
        this.errorCode = errorCode;
        this.errorMsg = errorMsg;
    }

    public Integer getErrorCode() {
        return errorCode;
    }

    public String getErrorMsg() {
        return errorMsg;
    }
}

?說明:枚舉類中定義了常見的錯誤碼以及錯誤的提示信息绸硕。
這里我們就定義好了統(tǒng)一的結(jié)果返回,其中里面的靜態(tài)方法是用來當(dāng)程序異常的時候轉(zhuǎn)換成異常返回規(guī)定的格式魂毁。

?然后我們需要自定義異常處理類玻佩。代碼如下:

public class DefinitionException extends RuntimeException{

    protected Integer errorCode;
    protected String errorMsg;

    public DefinitionException(){

    }
    public DefinitionException(Integer errorCode, String errorMsg) {
        this.errorCode = errorCode;
        this.errorMsg = errorMsg;
    }

    public Integer getErrorCode() {
        return errorCode;
    }

    public void setErrorCode(Integer errorCode) {
        this.errorCode = errorCode;
    }

    public String getErrorMsg() {
        return errorMsg;
    }

    public void setErrorMsg(String errorMsg) {
        this.errorMsg = errorMsg;
    }
}

?其中包含了錯誤的狀態(tài)碼,錯誤的提示信息席楚。然后我們可以自定義一個全局異常處理類咬崔,來處理各種異常,包括自己定義的異常和內(nèi)部異常。這樣可以簡化不少代碼烦秩,不用自己對每個異常都使用try垮斯,catch的方式來實現(xiàn)。

@ControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 處理自定義異常
     *
     */
    @ExceptionHandler(value = DefinitionException.class)
    @ResponseBody
    public Result bizExceptionHandler(DefinitionException e) {
        return Result.defineError(e);
    }

    /**
     * 處理其他異常
     *
     */
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public Result exceptionHandler( Exception e) {
        return Result.otherError(ErrorEnum.INTERNAL_SERVER_ERROR);
    }
}

?說明:每個方法上面加上一個 @ResponseBody的注解只祠,用于將對象解析成json,方便前后端的交互兜蠕,也可以使用 @ResponseBody放在異常類上面。

3. controller代碼測試與結(jié)果

?controller代碼:

@RestController
@RequestMapping("/result")
public class ResultController {
    @GetMapping("/getStudent")
    public Result getStudent(){
        Student student = new Student();
        student.setAge(21);
        student.setId(111);
        student.setName("學(xué)習(xí)筆記");
        Result result = new Result();
        result.setCode(200);
        result.setSuccess(true);
        result.setData(student);
        result.setMsg("學(xué)生列表信息");
        return result;
    }
    @RequestMapping("/getDeException")
    public Result DeException(){
        throw new DefinitionException(400,"我出錯了");
    }
    @RequestMapping("/getException")
    public Result Exception(){
        Result result = new Result();
        int a=1/0;
        return result;
    }
}

?其中的Student類就是前面一直在用的類了抛寝。包含三個屬性熊杨。其中省略了get,set方法盗舰。

public class Student  {
    /**
    * 唯一標(biāo)識id
    */
    private Integer id;
    /**
    * 姓名
    */
    private String name;
    /**
    * 年齡
    */
    private Integer age;

}

?然后啟動項目晶府,來挨個測試。首先測試正常沒有異常發(fā)生的數(shù)據(jù)钻趋。
瀏覽器輸入:localhost:8095/result/getStudent


2.png

?可以看到數(shù)據(jù)是正常返回json串川陆。沒有異常。
然后我們測試第二個自定義異常處理接口蛮位。瀏覽器輸入localhost:8095/result/getDeException较沪。


3.png

?可以看到這個自定義的異常是捕獲到了鳞绕,并且返回了一個json串。
最后我們測試一下其他的異常尸曼。瀏覽器輸入:localhost:8095/result/getException


4.png

?到這里我們就處理完了異常并且正確的返回了前端猾昆。
這里說一下,測試接口又很多方法骡苞,可以使用postman,或者idea自帶的接口測試工具都很好用楷扬。

?但是解幽,你可能會發(fā)現(xiàn)一個問題,這種方法是不能處理404異常的烘苹,捕獲不到躲株。該怎么辦呢?

4. 404異常特殊處理镣衡。

?默認情況下霜定,SpringBoot是不會拋出404異常的,所以@ControllerAdvice也不能捕獲到404異常廊鸥。我們可以通過以下配置來讓這個注解能捕獲到404異常望浩。

spring.mvc.throw-exception-if-no-handler-found=true
spring.resources.add-mappings=false

其中第一句是表示:當(dāng)發(fā)現(xiàn)404異常時直接拋出異常。第二句關(guān)閉默認的靜態(tài)資源路徑映射惰说。這樣404錯誤也能被捕獲到磨德,但是這個配置會讓你的靜態(tài)資源訪問出現(xiàn)問題,也就是不適合前后端不分離的情況吆视。

5. 總結(jié)

?本文講解了如何處理捕獲全局異常以及怎么自定義異常典挑,順便說明了統(tǒng)一結(jié)果的返回格式,并特殊處理的404啦吧,not found的異常您觉,將其作為統(tǒng)一結(jié)果返回。如果你覺得本文有用授滓,點個贊吧琳水!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市褒墨,隨后出現(xiàn)的幾起案子炫刷,更是在濱河造成了極大的恐慌,老刑警劉巖郁妈,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件浑玛,死亡現(xiàn)場離奇詭異,居然都是意外死亡噩咪,警方通過查閱死者的電腦和手機顾彰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門极阅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人涨享,你說我怎么就攤上這事筋搏。” “怎么了厕隧?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵奔脐,是天一觀的道長。 經(jīng)常有香客問我吁讨,道長髓迎,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任建丧,我火速辦了婚禮排龄,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘翎朱。我一直安慰自己橄维,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布拴曲。 她就那樣靜靜地躺著争舞,像睡著了一般。 火紅的嫁衣襯著肌膚如雪疗韵。 梳的紋絲不亂的頭發(fā)上兑障,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天,我揣著相機與錄音蕉汪,去河邊找鬼流译。 笑死,一個胖子當(dāng)著我的面吹牛者疤,可吹牛的內(nèi)容都是我干的福澡。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼驹马,長吁一口氣:“原來是場噩夢啊……” “哼革砸!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起糯累,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤算利,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后泳姐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體效拭,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了缎患。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片慕的。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖挤渔,靈堂內(nèi)的尸體忽然破棺而出肮街,到底是詐尸還是另有隱情,我是刑警寧澤判导,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布嫉父,位于F島的核電站,受9級特大地震影響眼刃,放射性物質(zhì)發(fā)生泄漏熔号。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一鸟整、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧朦蕴,春花似錦篮条、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至疹娶,卻和暖如春伴栓,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背雨饺。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工钳垮, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人额港。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓饺窿,卻偏偏與公主長得像,于是被迫代替她去往敵國和親移斩。 傳聞我的和親對象是個殘疾皇子肚医,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內(nèi)容