當前位置: 妍妍網 > 碼農

拒絕寫重復程式碼,試試這套開源的 SpringBoot 元件

2024-03-18碼農

來源:www.51cto.com/article/777403.html

Graceful Response是一個Spring Boot技術棧下的優雅響應處理器,提供一站式統一返回值封裝、全域例外處理、自訂異常錯誤碼等功能,使用Graceful Response進行web介面開發不僅可以節省大量的時間,還可以提高程式碼品質,使程式碼邏輯更清晰。

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

本計畫案例工程程式碼:https://github.com/feiniaojin/graceful-response-example.git ,註意選擇最新版本的分支。

Spring Boot版本

Graceful Response版本

graceful-response-example分支

2.x

3.2.1-boot2

3.2.0-boot2

3.x

3.2.1-boot3

3.2.0-boot3

註意,3.2.1-boot2版本的GracefulResponse源碼由單獨的倉庫進行維護,地址為:https://github.com/feiniaojin/graceful-response-boot2。

3.2.1-boot2和3.2.1-boot3除了支持的SpringBoot版本不一樣,其他實作完全一致,Maven參照時只需要根據對應的SpringBoot版本選擇Graceful Response的version即可,兩者的groupId、artifactId是一致的。

二、快速入門

1.Spring Boot介面開發現狀

目前,業界使用Spring Boot進行介面開發時,往往存在效率底下、重復勞動、可讀性差等問題。以下虛擬碼相信大家非常熟悉,我們大部份計畫的Controller介面都是這樣的。

@Controllerpublic classController{@GetMapping("/query")@ResponseBodypublic Response query(Map<String, Object> paramMap) { Response res = new Response();try {//1.校驗params參數合法性,包括非空校驗、長度校驗等if (illegal(paramMap)) { res.setCode(1); res.setMsg("error");return res; }//2.呼叫Service的一系列操作,得到查詢結果 Object data = service.query(params);//3.將操作結果設定到res物件中 res.setData(data); res.setCode(0); res.setMsg("ok");return res; } catch (Exception e) {//4.例外處理:一堆醜陋的try...catch,如果有錯誤碼的,還需要手工填充錯誤碼 res.setCode(1); res.setMsg("error");return res; } }}

這段虛擬碼存在什麽樣的問題呢?

第一個問題,效率低下。Controller層的程式碼應該盡量簡潔,上面的虛擬碼其實只是為了將數據查詢的結果進行封裝,使其以統一的格式進行返回。例如以下格式的響應體:

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

查詢過程中如果發生異常,需要在Controller進行手工捕獲,根據捕獲的異常人工地設定錯誤碼,當然,也用同樣的格式封裝錯誤碼進行返回。

可以看到,除了呼叫service層的query方法這一行,其他大部份的程式碼都執行進行結果的封裝,大量的冗余、低價值的程式碼導致我們的開發活動效率很低。

第二個問題,重復勞動。 以上捕獲異常、封裝執行結果的操作,每個介面都會進行一次,因此造成大量重復勞動。

第三個問題,可讀性低。 上面的核心程式碼被淹沒在許多冗余程式碼中,很難閱讀,如同大海撈針。

我們可以透過Graceful Response這個元件解決這樣的問題。

2. 快速入門


(1) 引入Graceful Response元件

Graceful Response已釋出至maven中央倉庫,我們可以直接引入到計畫中。

maven依賴如下:

<dependency><groupId>com.feiniaojin</groupId><artifactId>graceful-response</artifactId><version>{latest.version}</version></dependency>

Spring Boot版本

Graceful Response最新版本

2.x

3.2.1-boot2

3.x

3.2.1-boot3

(2) 啟用Graceful Response

在啟動類中引入@EnableGracefulResponse註解,即可啟用Graceful Response元件。

@EnableGracefulResponse@SpringBootApplicationpublic classExampleApplication{publicstaticvoidmain(String[] args){ SpringApplication.run(ExampleApplication. class, args); }}

(3) Controller層

引入Graceful Response後,我們不需要再手工進行查詢結果的封裝,直接返回實際結果即可,Graceful Response會自動完成封裝的操作。

Controller層範例如下:

@Controllerpublic classController{@RequestMapping("/get")@ResponseBodypublic UserInfoView get(Long id) { log.info("id={}", id);return UserInfoView.builder().id(id).name("name" + id).build(); }}

在範例程式碼中,Controller層的方法直接返回了UserInfoView物件,沒有進行封裝的操作,但經過Graceful Response處理後,我們還是得到了以下的響應結果。

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

而對於命令操作(Command)盡量不返回數據,因此command操作的方法的返回值應該是void,Graceful Response對於對於返回值型別void的方法,也會自動進行封裝。

public classController{@RequestMapping("/command")@ResponseBodypublicvoidcommand(){//業務操作 }}

成功呼叫該介面,將得到:

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

(3) Service層

在引入Graceful Response前,有的開發者在定義Service層的方法時,為了在介面中返回異常碼,幹脆直接將Service層方法定義為Response,淹沒了方法的正常返回值。

Response的程式碼如下。

//lombok註解@Datapublic class Response {privateString code;privateString msg;privateObject data;}

直接返回Response的Service層方法:

/** * 直接返回Reponse的Service * 不規範 */publicinterfaceService {public Reponse commandMethod(Command command);}

Graceful Response引入@ExceptionMapper註解,透過該註解將異常和錯誤碼關聯起來,這樣Service方法就不需要再維護Response的響應碼了,直接丟擲業務異常,由Graceful Response進行異常和響應碼的關聯。

@ExceptionMapper的用法如下。

/** * NotFoundException的定義,使用@ExceptionMapper註解修飾 * code:代表介面的異常碼 * msg:代表介面的異常提示 */@ExceptionMapper(code = "1404", msg = "找不到物件")public classNotFoundExceptionextendsRuntimeException{}

Service介面定義:

publicinterfaceQueryService {UserInfoView queryOne(Query query);}

Service介面實作:

public classQueryServiceImplimplementsQueryService{@Resourceprivate UserInfoMapper mapper;public UserInfoView queryOne(Query query){ UserInfo userInfo = mapper.findOne(query.getId());if (Objects.isNull(userInfo)) {//這裏直接拋自訂異常thrownew NotFoundException(); }//……後續業務操作 }}

當Service層的queryOne方法丟擲NotFoundException時,Graceful Response會進行異常捕獲,並將NotFoundException對應的異常碼和異常資訊封裝到統一的響應物件中,最終介面返回以下JSON。

{"status": {"code": "1404","msg": "找不到物件" },"payload": {}}

(5) 參數校驗

Graceful Response對JSR-303數據校驗規範和Hibernate Validator進行了增強,Graceful Response自身不提供參數校驗的功能,但是使用者使用了Hibernate Validator後,Graceful Response可以透過@ValidationStatusCode註解為參數校驗結果提供響應碼,並將其統一封裝返回。

例如以下的UserInfoQuery:

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

  • UserInfoQuery物件中定義了@NotNull和@Length兩個校驗規則,在未引入Graceful Response的情況下,會直接丟擲異常;

  • 在引入Graceful Response但是沒有加入@ValidationStatusCode註解的情況下,會以預設的錯誤碼進行返回;

  • 在上面的UserInfoQuery中由於使用了@ValidationStatusCode註解,並指定異常碼為520,則當userName欄位任意校驗不透過時,都會使用異常碼520進行返回,如下:

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

    而對於Controller層直接校驗方法入參的場景,Graceful Response也進行了增強,如以下Controller:

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

    如果該方法入參校驗觸發了userId和userName的校驗異常,將以錯誤碼1314進行返回,如下:

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

    (6) 自訂Response格式

    Graceful Response內建了兩種風格的響應格式,並透過graceful-response.response- style進行配置。

    graceful-response.response- style=0,或者不配置(預設情況),將以以下的格式進行返回:

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

    graceful-response.response- style=1,將以以下的格式進行返回:

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

    如果這兩種格式均不滿足業務需要,Graceful Response也支持使用者自訂響應體,關於自訂響應體的技術實作,請到自訂Response格式進行了解。

    本計畫提供的進階功能,包括:

  • 第三方元件汽車(Swagger、執行器等)

  • 自訂響應

  • 異常請求放行

  • 異常別名

  • 常用配置項

  • 目前該元件在GitHub上已經有兩百多Star,很多朋友已經開始用了,大家可以透過下方連結了解下:https://github.com/feiniaojin/graceful-response。

    熱門推薦