国产精品久久久aaaa,日日干夜夜操天天插,亚洲乱熟女香蕉一区二区三区少妇,99精品国产高清一区二区三区,国产成人精品一区二区色戒,久久久国产精品成人免费,亚洲精品毛片久久久久,99久久婷婷国产综合精品电影,国产一区二区三区任你鲁

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

一站式統一返回值封裝、異常處理、異常錯誤碼解決方案—最強的Sping Boot接口優雅響應處理器

京東云 ? 來源:jf_75140285 ? 作者:jf_75140285 ? 2024-06-20 15:42 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

1. 前言

統一返回值封裝、統一異常處理和異常錯誤碼體系的意義在于提高代碼的可維護性和可讀性,使得代碼更加健壯和穩定。統一返回值封裝可以避免每一個接口都需要手工拼裝響應報文;統一異常處理可以將異常處理的邏輯集中到一個地方,避免代碼中出現大量的try-catch語句,降低了代碼的復雜度,提高了代碼的可讀性;異常體系的設計可以清晰地區分不同類型的異常,使得開發者能夠更加精準地處理異常情況,并且能夠更好地定位和解決問題。

Graceful Response是一個Spring Boot體系下的優雅響應處理組件,提供一站式統一返回值封裝、全局異常處理、自定義異常錯誤碼、自定義參數校驗異常碼等功能,使用Graceful Response進行web接口開發不僅可以節省大量的時間,還可以提高代碼質量,使代碼邏輯更清晰。

強烈推薦你花3分鐘學會它!

Graceful Response的Github地址: https://github.com/feiniaojin/graceful-response ,歡迎star!

Graceful Response的案例工程代碼:https://github.com/feiniaojin/graceful-response-example.git

2. Spring Boot Web API接口數據返回的現狀

我們進行Spring Boo Web API接口開發時,通常大部分的Controller代碼是這樣的:

public class Controller {
    @GetMapping("/query")
    @ResponseBody
    public Response query(Parameter params) {

        Response res = new Response();
        try {
            //1.校驗params參數,非空校驗、長度校驗
            if (illegal(params)) {
                res.setCode(1);
                res.setMsg("error");
                return res;
            }
            //2.調用Service的一系列操作
            Data data = service.query(params);
            //3.執行正確時,將操作結果設置到res對象中
            res.setData(data);
            res.setCode(0);
            res.setMsg("ok");
            return res;
        } catch (BizException1 e) {
            //4.異常處理:一堆丑陋的try...catch,如果有錯誤碼的,還需要手工填充錯誤碼
            res.setCode(1024);
            res.setMsg("error");
            return res;
        } catch (BizException2 e) {
            //4.異常處理:一堆丑陋的try...catch,如果有錯誤碼的,還需要手工填充錯誤碼
            res.setCode(2048);
            res.setMsg("error");
            return res;
        } catch (Exception e) {
            //4.異常處理:一堆丑陋的try...catch,如果有錯誤碼的,還需要手工填充錯誤碼
            res.setCode(1);
            res.setMsg("error");
            return res;
        }
    }
}

這段代碼存在什么問題呢?真正的業務邏輯被冗余代碼淹沒,可讀性太差。

真正執行業務的代碼只有

Data data=service.query(params);

其他代碼不管是正常執行還是異常處理,都是為了異常封裝、把結果封裝為特定的格式,例如以下格式:

{
  "code": 0,
  "msg": "ok",
  "data": {
    "id": 1,
    "name": "username"
  }
}

這樣的邏輯每個接口都需要處理一遍,都是繁瑣的重復勞動。

現在,只需要引入Graceful Response組件并通過@EnableGracefulResponse啟用,就可以直接返回業務結果并自動完成response的格式封裝。

以下是使用Graceful Response之后的代碼,實現同樣的返回值封裝、異常處理、異常錯誤碼功能,但可以看到代碼變得非常簡潔,可讀性非常強。

public class Controller {
    @GetMapping("/query")
    @ResponseBody
    public Data query(Parameter params) {
       return service.query(params);
    }
}

3. 快速入門

3.1 引入maven依賴

graceful-response已發布至maven中央倉庫,可以直接引入到項目中,maven依賴如下:


    com.feiniaojin
    graceful-response
    {此處替換為最新的版本號}

以下鏈接可以查看maven中央倉庫中最新的版本:

https://central.sonatype.com/artifact/com.feiniaojin/graceful-response/3.0/versions

3.2 在啟動類中引入@EnableGracefulResponse注解

@EnableGracefulResponse
@SpringBootApplication
public class ExampleApplication {
    public static void main(String[] args) {
        SpringApplication.run(ExampleApplication.class, args);
    }
}

3.3 Controller方法直接返回結果

?普通的查詢

@Controller
public class Controller {
    @RequestMapping("/get")
    @ResponseBody
    public UserInfoView get(Long id) {
        log.info("id={}", id);
        return UserInfoView.builder().id(id).name("name" + id).build();
    }
}

UserInfoView的源碼:

@Data
@Builder
public class UserInfoView {
    private Long id;
    private String name;
}

這個接口直接返回了 UserInfoView的實例對象,調用接口時,Graceful Response將自動封裝為以下格式:

{
  "status": {
    "code": "0",
    "msg": "ok"
  },
  "payload": {
    "id": 1,
    "name": "name1"
  }
}

可以看到UserInfoView被自動封裝到payload字段中。

Graceful Response提供了兩種風格的Response,可以通過在application.properties文件中配置gr.responseStyle=1,將以以下的格式進行返回:

{
  "code": "0",
  "msg": "ok",
  "data": {
    "id": 1,
    "name": "name1"
  }
}

如果這兩種風格也不能滿足需要,我們還可以根據自己的需要進行自定義返回的Response格式。詳細見本文 4.3自定義Respnse格式。

?異常處理的場景

通過Graceful Response,我們不需要專門在Controller中處理異常,詳細見 4.1 Graceful Response異常錯誤碼處理。

?返回值為空的場景

某些Command類型的方法只執行修改操作,不返回數據,這個時候我們可以直接在Controller中返回void,Graceful Response會自動封裝默認的操作成功Response報文。

@Controller
public class Controller {
    @RequestMapping("/void")
    @ResponseBody
    public void testVoidResponse() {
        //省略業務操作
    }
}

testVoidResponse方法的返回時void,調用這個接口時,將返回:

{
  "status": {
    "code": "200",
    "msg": "success"
  },
  "payload": {}
}

3.4 Service方法業務處理

在引入Graceful Response后,Service層的方法的可讀性可以得到極大的提升。

?接口直接返回業務數據類型,而不是Response,更具備可讀性

public interface ExampleService {
    UserInfoView query1(Query query);
}

?Service接口實現類中,直接拋自定義的業務異常,Graceful Response將其轉化為返回錯誤碼和錯誤提示

public class ExampleServiceImpl implements ExampleService {
    @Resource
    private UserInfoMapper mapper;

    public UserInfoView query1(Query query) {
        UserInfo userInfo = mapper.findOne(query.getId());
        if (Objects.isNull(userInfo)) {
           //這里直接拋自定義異常,異常通過@ExceptionMapper修飾,提供異常碼和異常提示
           throw new NotFoundException();
        }
        // 省略后續業務操作
    }
}
/**
 * NotFoundException的定義,使用@ExceptionMapper注解修飾
 * code:代表接口的異常碼
 * msg:代表接口的異常提示
 */
@ExceptionMapper(code = "1404", msg = "找不到對象")
public class NotFoundException extends RuntimeException {

}
//Controller不再捕獲處理異常
@RequestMapping("/get")
@ResponseBody
public UserInfoView get(Query query)) {
    return exampleService.query1(query);
}

當Service方法拋出NotFoundException異常時,接口將直接返回錯誤碼,不需要手工set,極大地簡化了異常處理邏輯。

{
  "status": {
    "code": "1404",
    "msg": "找不到對象"
  },
  "payload": {}
}

驗證:啟動example工程后,請求

http://localhost:9090/example/notfound

3.5 通用異常類和通用工具類

@ExceptionMapper設計的初衷是將異常與錯誤碼關聯起來,用戶只需要拋異常,不需要再關注異常與錯誤碼的對應關系。

部分用戶反饋,希望在不自定義新異常類的情況下,也能可以按照預期返回錯誤碼和異常信息,因此從2.1版本開始,新增了GracefulResponseException異常類,用戶只需要拋出該異常即可。

public class Service {
  
  public void method() {
    throw new GracefulResponseException("自定義的錯誤碼","自定義的錯誤信息");
  }
}

為簡化使用,從2.1版本開始提供GracefulResponse通用工具類,在需要拋出GracefulResponseException時,只需要調用raiseException方法即可。 這樣設計原因是用戶拋通用異常,其實已經不關心具體是什么異常了,用戶實際上只是想要錯誤碼和錯誤信息。

示例如下:

public class Service {

    public void method() {
        
        //當condition==true時,拋出GracefulResponseException異常,返回自定義的錯誤碼和錯誤信息
        if (condition) {
            GracefulResponse.raiseException("自定義的錯誤碼", "自定義的錯誤信息");
        }
        //省略其他業務邏輯
    }
}

3.6 參數校驗異常以及錯誤碼

3.0版本以前,如果引用validation框架并發生了校驗異常,Graceful Response在默認情況下會捕獲并返回code=1,參數校驗發生的異常信息會丟失;如果使用異常別名功能,可以對大的校驗異常返回統一的錯誤碼,但是不夠靈活且依舊沒有解決參數異常提示的問題。

Graceful Response從3.0版本開始,引入@ValidationStatusCode注解,可以非常方便地支持validation校驗異常。

@ValidationStatusCode注解目前只有一個code屬性,用于指定參數校驗異常時的錯誤碼,錯誤提示則取自validation校驗框架。

對入參類進行參數校驗

@Data
public class UserInfoQuery {

    @NotNull(message = "userName is null !")
    @Length(min = 6, max = 12)
    @ValidationStatusCode(code = "520")
    private String userName;

}

userName字段任意一項校驗不通過時,接口將會返回異常碼520和校驗注解中的message

{
  "status": {
    "code": "520",
    "msg": "userName is null !"
  },
  "payload": {}
}

詳細見example工程ExampleController的validateDto方法
http://localhost:9090/example/validateDto

注意:@ValidationStatusCode校驗參數對象字段的情況,code取值順序為:會先取字段上的注解,再去該屬性所在對象的類(即UserInfoQuery類)上的注解,再取全局配置的參數異常碼gr.defaultValidateErrorCode,最后取默認的全局默認的錯誤碼(默認code=1)

直接在Controller中校驗方法入參

直接在Controller方法中進行參數校驗:

@Validated
public class ExampleController {

  @RequestMapping("/validateMethodParam")
  @ResponseBody
  @ValidationStatusCode(code = "1314")
  public void validateMethodParam(@NotNull(message = "userId不能為空") Long userId,
                                  @NotNull(message = "userName不能為空") Long userName) {
      //省略業務邏輯
  }
}

當userId、或者userName校驗不通過時,將會返回code=1314,msg為對應的校驗信息。

{
  "status": {
    "code": "1314",
    "msg": "userId不能為空"
  },
  "payload": {}
}

詳細見example工程ExampleController的validateMethodParam方法
http://localhost:9090/example/validateMethodParam

注意:@ValidationStatusCode校驗Controller方法參數字段的情況,code取值順序為:會先取當前方法上的注解,再去該方法所在類(即ExampleController類)上的注解,再取全局配置的參數異常碼gr.defaultValidateErrorCode,最后取默認的全局默認的錯誤碼(默認code=1)

4. 進階用法

4.1 Graceful Response異常錯誤碼處理

以下是使用Graceful Response進行異常、錯誤碼處理的開發步驟。

?創建自定義異常

通過繼承RuntimeException類創建自定義的異常,采用 @ExceptionMapper注解修飾,注解的 code屬性為返回碼,msg屬性為錯誤提示信息。

關于是繼承RuntimeException還是繼承Exception,讀者可以根據實際情況去選擇,Graceful Response對兩者都支持。

@ExceptionMapper(code = "1007", msg = "有內鬼,終止交易")
public static final class RatException extends RuntimeException {

}

?Service執行具體邏輯

Service執行業務邏輯的過程中,需要拋異常的時候直接拋出去即可。由于已經通過@ExceptionMapper定義了該異常的錯誤碼,我們不需要再單獨的維護異常碼枚舉與異常類的關系。

//Service層偽代碼
public class Service {
    public void illegalTransaction() {
        //需要拋異常的時候直接拋
        if (check()) {
            throw new RatException();
        }
        doIllegalTransaction();
    }
}

Controller層調用Service層偽代碼:

public class Controller {
    @RequestMapping("/test3")
    public void test3() {
        //Controller中不會進行異常處理,也不會手工set錯誤碼,只關心核心操作,其他的統統交給Graceful Response
        exampleService.illegalTransaction();
    }
}

在瀏覽器中請求controller的/test3方法,有異常時將會返回:

{
  "status": {
    "code": "1007",
    "msg": "有內鬼,終止交易"
  },
  "payload": {
  }
}

4.2 外部異常別名

案例工程( https://github.com/feiniaojin/graceful-response-example.git )啟動后, 通過瀏覽器訪問一個不存在的接口,例如 http://localhost:9090/example/get2?id=1
如果沒開啟Graceful Response,將會跳轉到404頁面,主要原因是應用內部產生了 NoHandlerFoundException異常。如果開啟了Graceful Response,默認會返回code=1的錯誤碼。

這類非自定義的異常,如果需要自定義一個錯誤碼返回,將不得不對每個異常編寫Advice邏輯,在Advice中設置錯誤碼和提示信息,這樣做也非常繁瑣。

Graceful Response可以非常輕松地解決給這類外部異常定義錯誤碼和提示信息的問題。

以下為操作步驟:

?創建異常別名,并用 @ExceptionAliasFor注解修飾

@ExceptionAliasFor(code = "1404", msg = "Not Found", aliasFor = NoHandlerFoundException.class)
public class NotFoundException extends RuntimeException {
}

code:捕獲異常時返回的錯誤碼

msg:異常提示信息

aliasFor:表示將成為哪個異常的別名,通過這個屬性關聯到對應異常。

?注冊異常別名

創建一個繼承了AbstractExceptionAliasRegisterConfig的配置類,在實現的registerAlias方法中進行注冊。

@Configuration
public class GracefulResponseConfig extends AbstractExceptionAliasRegisterConfig {

    @Override
    protected void registerAlias(ExceptionAliasRegister aliasRegister) {
        aliasRegister.doRegisterExceptionAlias(NotFoundException.class);
    }
}

?瀏覽器訪問不存在的URL

再次訪問 http://localhost:9090/example/get2?id=1 ,服務端將返回以下json,正是在ExceptionAliasFor中定義的內容

{
  "code": "1404",
  "msg": "not found",
  "data": {
  }
}

4.3 自定義Response格式

Graceful Response內置了兩種風格的響應格式,可以在application.properties文件中通過gr.responseStyle進行配置。

?gr.responseStyle=0,或者不配置(默認情況)

將以以下的格式進行返回:

{
  "status": {
    "code": "1007",
    "msg": "有內鬼,終止交易"
  },
  "payload": {
  }
}

?gr.responseStyle=1

將以以下的格式進行返回:

{
  "code": "1404",
  "msg": "not found",
  "data": {
  }
}

?自定義響應格式

如果以上兩種格式均不能滿足業務需要,可以通過自定義去滿足,Response

例如以下響應:

public class CustomResponseImpl implements Response {

    private String code;

    private Long timestamp = System.currentTimeMillis();

    private String msg;

    private Object data = Collections.EMPTY_MAP;

    @Override
    public void setStatus(ResponseStatus statusLine) {
        this.code = statusLine.getCode();
        this.msg = statusLine.getMsg();
    }

    @Override
    @JsonIgnore
    public ResponseStatus getStatus() {
        return null;
    }

    @Override
    public void setPayload(Object payload) {
        this.data = payload;
    }

    @Override
    @JsonIgnore
    public Object getPayload() {
        return null;
    }

    public String getCode() {
        return code;
    }

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

    public String getMsg() {
        return msg;
    }

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

    public Object getData() {
        return data;
    }

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

    public Long getTimestamp() {
        return timestamp;
    }
}

注意,不需要返回的屬性可以返回null或者加上@JsonIgnore注解

?配置gr.responseClassFullName

將CustomResponseImpl的全限定名配置到gr.responseClassFullName屬性。

gr.responseClassFullName=com.feiniaojin.gracefuresponse.example.config.CustomResponseImpl

注意,配置gr.responseClassFullName后,gr.responseStyle將不再生效。

實際的響應報文如下:

{
    "code":"200",
    "timestamp":1682489591319,
    "msg":"success",
    "data":{

    }
}

如果還是不能滿足需求,那么可以考慮同時自定義實現Response和ResponseFactory這兩個接口。

5. 常用配置

Graceful Response在版本迭代中,根據用戶反饋提供了一些常用的配置項,列舉如下:

gr.printExceptionInGlobalAdvice
是否打印異常日志,默認為false

gr.responseClassFullName
自定義Response類的全限定名,默認為空。 配置gr.responseClassFullName后,gr.responseStyle將不再生效

gr.responseStyle
Response風格,不配置默認為0

gr.defaultSuccessCode
自定義的成功響應碼,不配置則為0

gr.defaultSuccessMsg
自定義的成功提示,默認為ok

gr.defaultErrorCode
自定義的失敗響應碼,默認為1

gr.defaultErrorMsg
自定義的失敗提示,默認為error

gr.defaultValidateErrorCode
全局的參數校驗錯誤碼,默認等于gr.defaultErrorCode

6. 總結

本文介紹了Graceful Response這個框架的使用,讀者在使用過程中遇到問題,歡迎到GitHub提交issue進行反饋,幫助我們將Graceful Response優化得更好。

審核編輯 黃宇

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 處理器
    +關注

    關注

    68

    文章

    20250

    瀏覽量

    252212
  • 接口
    +關注

    關注

    33

    文章

    9519

    瀏覽量

    157019
  • 封裝
    +關注

    關注

    128

    文章

    9248

    瀏覽量

    148614
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    高頻陶瓷解決方案:Johanson Technology的一站式選擇

    高頻陶瓷解決方案:Johanson Technology的一站式選擇 在當今快速發展的電子科技領域,高頻陶瓷組件在無線通信、射頻微波等應用中扮演著至關重要的角色。Johanson
    的頭像 發表于 02-03 14:35 ?170次閱讀

    一站式維修解決方案:恢復BONN波恩BLWA系列窄帶固態功率放大器至出廠指標

    一站式維修解決方案:恢復BONN波恩BLWA系列窄帶固態功率放大器至出廠指標
    的頭像 發表于 12-18 17:24 ?741次閱讀
    <b class='flag-5'>一站式</b>維修<b class='flag-5'>解決方案</b>:恢復BONN波恩BLWA系列窄帶固態功率放大器至出廠指標

    使用setjmp及longjmp函數處理異常

    ) { // 調用foo函數,傳入個非零 foo(10); // 調用foo函數,傳入個零 foo(0); } else { // 如果
    發表于 12-11 08:00

    檢查函數返回值錯誤異常處理方法

    檢查函數返回值:這是最常見也最基本的錯誤處理異常處理方法,就是在調用個函數后,檢查其返回值
    發表于 12-11 06:48

    Axiometrix Solutions 一站式方案引領汽車測試新變革

    和測量解決方案。這三大品牌在AxiometrixSolutions的統一技術平臺下協同運作,為汽車測試需求提供一站式解決方案,幫助制造商和工程師避免因系統分散和供應商管理而產生的成本
    的頭像 發表于 10-29 09:04 ?612次閱讀
    Axiometrix Solutions <b class='flag-5'>一站式</b><b class='flag-5'>方案</b>引領汽車測試新變革

    Cortex-M0+處理器的HardFault錯誤介紹

    在ARM處理器中,如果個程序產生了錯誤并且被處理器檢測到,就會產生錯誤異常。Cortex-M0
    的頭像 發表于 10-14 10:50 ?3379次閱讀
    Cortex-M0+<b class='flag-5'>處理器</b>的HardFault<b class='flag-5'>錯誤</b>介紹

    掛載sramfs文件系統到外掛sdram ,掛載時返回錯誤碼為-1,怎么解決?

    掛載sramfs文件系統到外掛sdram ,掛載時返回錯誤碼為-1。求大神指點。謝謝各位大佬。
    發表于 09-16 06:41

    芯圣電子重磅推出一站式HC AI玩具盒子服務方案

    芯圣電子重磅推出一站式HCAI玩具盒子服務方案,HCAI玩具盒子提供PCBA服務、云端中臺服務、大模型部署對接服務、定制化模型微調以及免費的3D外殼設計服務。為什么選擇HCAI玩具盒子服務方案?六大
    的頭像 發表于 08-15 14:28 ?1027次閱讀
    芯圣電子重磅推出<b class='flag-5'>一站式</b>HC AI玩具盒子服務<b class='flag-5'>方案</b>

    芯圣電子重磅推出一站式HC AI玩具盒子服務方案

    芯圣電子重磅推出一站式HCAI玩具盒子服務方案,HCAI玩具盒子提供PCBA服務、云端中臺服務、大模型部署對接服務、定制化模型微調以及免費的3D外殼設計服務。為什么選擇HCAI玩具盒子服務方案?六大
    的頭像 發表于 08-15 14:26 ?1438次閱讀
    芯圣電子重磅推出<b class='flag-5'>一站式</b>HC AI玩具盒子服務<b class='flag-5'>方案</b>

    NCS放大器DAD3350常見錯誤碼解決方案

    NCS放大器DAD3350在工業應用中可能出現的錯誤碼解決方案如下: ? 、常見錯誤碼及原因 ? ? 過載報警(如LV低電壓報警、OVC過電流報警) ? ? 原因 ?: 電源電壓
    的頭像 發表于 07-12 09:41 ?909次閱讀

    一站式PCBA加工全流程大揭秘!從設計到交付一站式搞定

    一站式PCBA加工廠家今天為大家講講一站式PCBA加工流程有哪些?一站式PCBA加工流程全解析及優勢。在現代電子制造領域,PCBA加工已成為各類電子產品生產的核心環節。對許多客戶來說,了解PCBA
    的頭像 發表于 06-11 09:18 ?1101次閱讀

    文解析一站式代工代料服務

    一站式PCBA加工廠家今天為大家講講一站式PCBA代工代料服務概述及一站式服務的便利性與專業性。一站式代工代料服務(Turnkey Solution)是
    的頭像 發表于 06-10 09:18 ?915次閱讀

    行芯科技提供Signoff工具鏈一站式解決方案

    近日,EDA 三巨頭集體斷供,中國半導體產業面臨更加嚴峻的挑戰。行芯科技作為EDA行業排頭兵,憑借七年時間完全自主研發的Signoff 一站式解決方案,“與中國芯,路同行”。
    的頭像 發表于 06-09 13:39 ?1135次閱讀

    高速風機EMC整改:從測試到合規的一站式解決方案

    深圳南柯電子|高速風機EMC整改:從測試到合規的一站式解決方案
    的頭像 發表于 06-09 11:20 ?1009次閱讀
    高速風機EMC整改:從測試到合規的<b class='flag-5'>一站式</b><b class='flag-5'>解決方案</b>

    解鎖數據中心效能密碼:一站式綜合能效管理方案

    解鎖數據中心效能密碼:一站式綜合能效管理方案
    的頭像 發表于 03-08 08:13 ?705次閱讀
    解鎖數據中心效能密碼:<b class='flag-5'>一站式</b>綜合能效管理<b class='flag-5'>方案</b>