亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

SpringBoot統一接口返回及全局異常如何處理

發布時間:2022-06-23 14:02:50 來源:億速云 閱讀:328 作者:iii 欄目:開發技術

這篇文章主要介紹“SpringBoot統一接口返回及全局異常如何處理”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“SpringBoot統一接口返回及全局異常如何處理”文章能幫助大家解決問題。

一、SpringBoot不使用統一返回格式

默認情況下,SpringBoot會有如下三種返回情況。

1.1 使用字符串返回

@GetMapping("/getUserName")
public String getUserName(){
    return "HuaGe";
}

調用接口返回結果:

HuaGe

1.2 使用實體類返回

@GetMapping("/getUserName")
public User getUserName(){
    return new User("HuaGe",18,"男");
}

調用接口返回結果:

{
  "name": "HuaGe",
  "age": "18",
  "性別": "男", 
}

1.3 異常情況下返回

@GetMapping("/getUserName")
public static String getUserName(){
    HashMap hashMap = Maps.newHashMap();
    return hashMap.get(0).toString();
}

模擬一個空指針異常,在不做任何異常處理的情況下,可以看下SpringBoot的默認返回結果:

{
    "timestamp": "2021-08-09T06:56:41.524+00:00",
    "status": 500,
    "error": "Internal Server Error",
    "path": "/sysUser/getUserName"
}

對于上面這幾種情況,如果整個項目沒有定義統一的返回格式,五個后臺開發人員定義五種返回格式,這樣不僅代碼臃腫,前后端對接效率低,而且還會有一些意向不到的情況發生,比如前端直接顯示異常詳情等,這給用戶的體驗是非常差的。

二、基礎玩法

項目中最常見到的是封裝一個工具類,類中定義需要返回的字段信息,把需要返回前端的接口信息,通過該類進行封裝,這樣就可以解決返回格式不統一的現象了。

2.1 參數說明

  • code: 狀態碼,后臺可以維護一套統一的狀態碼;

  • message: 描述信息,接口調用成功/失敗的提示信息;

  • data: 返回數據。

2.2 流程說明

  • 新建Result類

public class Result<T> {
    
    private int code;
    
    private String message;
    
    private T data;

    public Result() {}
    public Result(int code, String message) {
        this.code = code;
        this.message = message;
    }
    
    /**
     * 成功
     */
    public static <T> Result<T> success(T data) {
        Result<T> result = new Result<T>();
        result.setCode(ResultMsgEnum.SUCCESS.getCode());
        result.setMessage(ResultMsgEnum.SUCCESS.getMessage());
        result.setData(data);
        return result;
    }

    /**
     * 失敗
     */
    public static <T> Result<T> error(int code, String message) {
        return new Result(code, message);
    }
}

定義返回狀態碼

public enum ResultMsgEnum {
    SUCCESS(0, "成功"),
    FAIL(-1, "失敗"),
    AUTH_ERROR(502, "授權失敗!"),
    SERVER_BUSY(503, "服務器正忙,請稍后再試!"),
    DATABASE_OPERATION_FAILED(504, "數據庫操作失敗");
    private int code;
    private String message;

    ResultMsgEnum(int code, String message) {
        this.code = code;
        this.message = message;
    }
    public int getCode() {
        return this.code;
    }
    
    public String getMessage() {
        return this.message;
    }
}
  • 使用方式

上面兩步定義了數據返回格式狀態碼,接下來就要看下在接口中如何使用了。

@GetMapping("/getUserName")
public Result getUserName(){
 &nbsp; &nbsp;return Result.success("huage");
}

調用結果如下,可以看到是我們在Result中定義的參數類型。

{
 &nbsp; &nbsp;"code": 0,
 &nbsp; &nbsp;"message": "成功",
 &nbsp; &nbsp;"data": "huage"
}

這樣寫雖然能夠滿足日常需求,而且我相信很多小伙伴也是這么用的,但是如果我們有大量的接口,然后在每一個接口中都使用Result.success來包裝返回信息,會新增很多重復代碼,顯得不夠優雅,甚至都不好意思拿出去顯擺。 肯定會有一種方式能夠再一次提高代碼逼格,實現最優解。

三、進階用法

基本用法學會后,接下來看點究極版本,主要用到如下兩個知識點,用法簡單,無論是拿出來教學妹,還是指點小姐姐,都是必備技能。

3.1 類介紹

  • ResponseBodyAdvice: 該接口是SpringMVC 4.1提供的,它允許在 執行 @ResponseBody后自定義返回數據,用來封裝統一數據格式返回;

  • @RestControllerAdvice: 該注解是對Controller進行增強的,可以全局捕獲拋出的異常。

3.2 用法說明

  • 新建ResponseAdvice類;

  • 實現ResponseBodyAdvice接口,實現supportsbeforeBodyWrite方法;

  • 該類用于統一封裝controller中接口的返回結果。

@RestControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice<Object> {
    @Autowired
    private ObjectMapper objectMapper;

    /**
     * 是否開啟功能 true:是 
     */
    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        return true;
    }

    /**
     * 處理返回結果
     */
    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        //處理字符串類型數據
        if(o instanceof String){
            try {
                return objectMapper.writeValueAsString(Result.success(o));
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
        }
        return Result.success(o);
    }
}

我們可以通過getUserName接口測試一下,會發現和直接使用Result返回的結果是一致的。

不過,細心的小伙伴們肯定注意到了,在ResponseAdvice我們全部使用了Result.success(o)來處理結果,對于error類型的結果未做處理。我們來看下,發生異常情況時,返回結果是什么樣呢?繼續使用上面HashMap空指針異常的代碼,測試結果如下:

{
    "code": 0,
    "message": "成功",
    "data": {
        "timestamp": "2021-08-09T09:33:26.805+00:00",
        "status": 405,
        "error": "Method Not Allowed",
        "path": "/sysUser/getUserName"
    }
}

雖然格式上沒有毛病,但是在code、data字段的具體數據上是不友好或不正確的。不處理好這些事情,會嚴重影響自己在前端妹妹心中的高大形象的,這是決不能容忍的。

3.3 全局異常處理器

以前我們遇到異常時,第一時間想到的應該是try..catch..finnal吧,不過這種方式會導致大量代碼重復,維護困難,邏輯臃腫等問題,這不是我們想要的結果。

今天我們要用的全局異常處理方式,用起來是比較簡單的。首先新增一個類,增加@RestControllerAdvice注解,該注解的作用花哥上面已經介紹過,就不再嘮叨了。

@RestControllerAdvice
public class CustomerExceptionHandler {
 &nbsp; &nbsp;
}

如果我們有想要攔截的異常類型,就新增一個方法,使用@ExceptionHandler注解修飾,注解參數為目標異常類型。

例如:controller中接口發生Exception異常時,就會進入到Execption方法中進行捕獲,將雜亂的異常信息,轉換成指定格式后交給ResponseAdvice方法進行統一格式封裝并返回給前端小伙伴。

@RestControllerAdvice
@Slf4j
public class CustomerExceptionHandler {

    @ExceptionHandler(AuthException.class)
    public String ErrorHandler(AuthorizationException e) {
        log.error("沒有通過權限驗證!", e);
        return "沒有通過權限驗證!";
    }

    @ExceptionHandler(Exception.class)
    public Result Execption(Exception e) {
        log.error("未知異常!", e);
        return Result.error(ResultMsgEnum.SERVER_BUSY.getCode(),ResultMsgEnum.SERVER_BUSY.getMessage());
    }
}

再次調用接口getUserName查看返回結果,會發現還是有一些問題,因為我們在CustomerExceptionHandler中已經將接口返回結果封裝成Result類型,而代碼執行到統一結果返回類ResponseAdvice時,又會結果再次封裝,就出現了如下問題。

{
    "code": 0,
    "message": "成功",
    "data": {
        "code": 503,
        "message": "服務器正忙,請稍后再試!",
        "data": null
    }
}

3.4 統一返回結果處理類最終版

解決上述問題非常簡單,只要在beforeBodyWrite中增加一條判斷即可。

@RestControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice<Object> {
    @Autowired
    private ObjectMapper objectMapper;

    /**
     * 是否開啟功能 true:開啟
     */
    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        return true;
    }

    /**
     * 處理返回結果
     */
    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        //處理字符串類型數據
        if(o instanceof String){
            try {
                return objectMapper.writeValueAsString(Result.success(o));
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
        }
        //返回類型是否已經封裝
        if(o instanceof Result){
            return o;
        }
        return Result.success(o);
    }
}

關于“SpringBoot統一接口返回及全局異常如何處理”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

清苑县| 泾川县| 定边县| 武宣县| 屯昌县| 连江县| 定陶县| 鄂托克旗| 兰州市| 海安县| 和平县| 鄱阳县| 遵义县| 肥东县| 云安县| 壤塘县| 太仓市| 留坝县| 平凉市| 永清县| 浏阳市| 印江| 兴仁县| 交城县| 普陀区| 新田县| 巧家县| 大埔区| 陵川县| 文安县| 渭源县| 兴海县| 武威市| 临桂县| 包头市| 蓝田县| 商河县| 玉田县| 泸西县| 南阳市| 松溪县|