日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

为什么阿里巴巴RPC接口不允许使用枚举类型?

發布時間:2025/3/20 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 为什么阿里巴巴RPC接口不允许使用枚举类型? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

點擊上方?好好學java?,選擇?星標?公眾號

重磅資訊、干貨,第一時間送達

今日推薦:今天給大家推薦 6 個 Spring Boot 項目,拿來就可以賺錢!

個人原創100W+訪問量博客:點擊前往,查看更多

作者 l Hollis

來源 l Hollis(ID:hollischuang)

最近,我們的線上環境出現了一個問題,線上代碼在執行過程中拋出了一個IllegalArgumentException,分析堆棧后,發現最根本的的異常是以下內容:

java.lang.IllegalArgumentException:?No?enum?constant?com.a.b.f.m.a.c.AType.P_M

大概就是以上的內容,看起來還是很簡單的,提示的錯誤信息就是在AType這個枚舉類中沒有找到P_M這個枚舉項。

于是經過排查,我們發現,在線上開始有這個異常之前,該應用依賴的一個下游系統有發布,而發布過程中是一個API包發生了變化,主要變化內容是在一個RPC接口的Response返回值類中的一個枚舉參數AType中增加了P_M這個枚舉項。

但是下游系統發布時,并未通知到我們負責的這個系統進行升級,所以就報錯了。

我們來分析下為什么會發生這樣的情況。

問題重現

首先,下游系統A提供了一個二方庫的某一個接口的返回值中有一個參數類型是枚舉類型。

一方庫指的是本項目中的依賴

二方庫指的是公司內部其他項目提供的依賴

三方庫指的是其他組織、公司等來自第三方的依賴

public?interface?AFacadeService?{public?AResponse?doSth(ARequest?aRequest);}public?Class?AResponse{private?Boolean?success;private?AType?aType;}public?enum?AType{P_T,A_B}

然后B系統依賴了這個二方庫,并且會通過RPC遠程調用的方式調用AFacadeService的doSth方法。

public?class?BService?{@AutowiredAFacadeService?aFacadeService;public?void?doSth(){ARequest?aRequest?=?new?ARequest();AResponse?aResponse?=?aFacadeService.doSth(aRequest);AType?aType?=?aResponse.getAType();}}

這時候,如果A和B系統依賴的都是同一個二方庫的話,兩者使用到的枚舉AType會是同一個類,里面的枚舉項也都是一致的,這種情況不會有什么問題。

但是,如果有一天,這個二方庫做了升級,在AType這個枚舉類中增加了一個新的枚舉項P_M,這時候只有系統A做了升級,但是系統B并沒有做升級。

那么A系統依賴的的AType就是這樣的:

public?enum?AType{P_T,A_B,P_M}

而B系統依賴的AType則是這樣的:

public?enum?AType{P_T,A_B}

這種情況下,在B系統通過RPC調用A系統的時候,如果A系統返回的AResponse中的aType的類型為新增的P_M時候,B系統就會無法解析。一般在這種時候,RPC框架就會發生反序列化異常。導致程序被中斷。

原理分析

這個問題的現象我們分析清楚了,那么再來看下原理是怎樣的,為什么出現這樣的異常呢。

其實這個原理也不難,這類RPC框架大多數會采用JSON的格式進行數據傳輸,也就是客戶端會將返回值序列化成JSON字符串,而服務端會再將JSON字符串反序列化成一個Java對象。

而JSON在反序列化的過程中,對于一個枚舉類型,會嘗試調用對應的枚舉類的valueOf方法來獲取到對應的枚舉。

而我們查看枚舉類的valueOf方法的實現時,就可以發現,如果從枚舉類中找不到對應的枚舉項的時候,就會拋出IllegalArgumentException

public?static?<T?extends?Enum<T>>?T?valueOf(Class<T>?enumType, String?name)?{T?result?=?enumType.enumConstantDirectory().get(name);if?(result?!=?null)return?result;if?(name?==?null)throw?new?NullPointerException("Name?is?null");throw?new?IllegalArgumentException("No?enum?constant?"?+?enumType.getCanonicalName()?+?"."?+?name);}

關于這個問題,其實在《阿里巴巴Java開發手冊》中也有類似的約定:

這里面規定"對于二方庫的參數可以使用枚舉,但是返回值不允許使用枚舉"。這背后的思考就是本文上面提到的內容。

擴展思考

為什么參數中可以有枚舉?

不知道大家有沒有想過這個問題,其實這個就和二方庫的職責有點關系了。

一般情況下,A系統想要提供一個遠程接口給別人調用的時候,就會定義一個二方庫,告訴其調用方如何構造參數,調用哪個接口。

而這個二方庫的調用方會根據其中定義的內容來進行調用。而參數的構造過程是由B系統完成的,如果B系統使用到的是一個舊的二方庫,使用到的枚舉自然是已有的一些,新增的就不會被用到,所以這樣也不會出現問題。

比如前面的例子,B系統在調用A系統的時候,構造參數的時候使用到AType的時候就只有P_T和A_B兩個選項,雖然A系統已經支持P_M了,但是B系統并沒有使用到。

如果B系統想要使用P_M,那么就需要對該二方庫進行升級。

但是,返回值就不一樣了,返回值并不受客戶端控制,服務端返回什么內容是根據他自己依賴的二方庫決定的。

但是,其實相比較于手冊中的規定,我更加傾向于,在RPC的接口中入參和出參都不要使用枚舉。

一般,我們要使用枚舉都是有幾個考慮:

  • 1、枚舉嚴格控制下游系統的傳入內容,避免非法字符。

  • 2、方便下游系統知道都可以傳哪些值,不容易出錯。

不可否認,使用枚舉確實有一些好處,但是我不建議使用主要有以下原因:

  • 1、如果二方庫升級,并且刪除了一個枚舉中的部分枚舉項,那么入參中使用枚舉也會出現問題,調用方將無法識別該枚舉項。

  • 2、有的時候,上下游系統有多個,如C系統通過B系統間接調用A系統,A系統的參數是由C系統傳過來的,B系統只是做了一個參數的轉換與組裝。這種情況下,一旦A系統的二方庫升級,那么B和C都要同時升級,任何一個不升級都將無法兼容。

我其實建議大家在接口中使用字符串代替枚舉,相比較于枚舉這種強類型,字符串算是一種弱類型。

如果使用字符串代替RPC接口中的枚舉,那么就可以避免上面我們提到的兩個問題,上游系統只需要傳遞字符串就行了,而具體的值的合法性,只需要在A系統內自己進行校驗就可以了。

為了方便調用者使用,可以使用javadoc的@see注解表明這個字符串字段的取值從那個枚舉中獲取。

public?Class?AResponse{private?Boolean?success;/***??@see?AType?*/private?String?aType;}

對于像阿里這種比較龐大的互聯網公司,隨便提供出去的一個接口,可能有上百個調用方,而接口升級也是常態,我們根本做不到每次二方庫升級之后要求所有調用者跟著一起升級,這是完全不現實的,并且對于有些調用者來說,他用不到新特性,完全沒必要做升級。

還有一種看起來比較特殊,但是實際上比較常見的情況,就是有的時候一個接口的聲明在A包中,而一些枚舉常量定義在B包中,比較常見的就是阿里的交易相關的信息,訂單分很多層次,每次引入一個包的同時都需要引入幾十個包。

對于調用者來說,我肯定是不希望我的系統引入太多的依賴的,一方面依賴多了會導致應用的編譯過程很慢,并且很容易出現依賴沖突問題。

所以,在調用下游接口的時候,如果參數中字段的類型是枚舉的話,那我沒辦法,必須得依賴他的二方庫。但是如果不是枚舉,只是一個字符串,那我就可以選擇不依賴。

所以,我們在定義接口的時候,會盡量避免使用枚舉這種強類型。規范中規定在返回值中不允許使用,而我自己要求更高,就是即使在接口的入參中我也很少使用。

最后,我只是不建議在對外提供的接口的出入參中使用枚舉,并不是說徹底不要用枚舉,我之前很多文章也提到過,枚舉有很多好處,我在代碼中也經常使用。所以,切不可因噎廢食。

當然,文中的觀點僅代表我個人,具體是是不是適用其他人,其他場景或者其他公司的實踐,需要讀者們自行分辨下,建議大家在使用的時候可以多思考一下。

推薦文章
  • 今天給大家推薦 6 個 Spring Boot 項目,拿來就可以賺錢!

  • 交公糧了:我經常逛的技術網站

  • 圈子哥推薦一款基于 Spring Boot 開發 OA 開源產品,學習/搞外快都是不二選擇!

  • 硬剛一周,3W字總結,一年的經驗告訴你如何準備校招!

原創電子書歷時整整一年總結的?Java 面試 + Java 后端技術學習指南,這是本人這幾年及校招的總結,各種高頻面試題已經全部進行總結,按照章節復習即可,已經拿到了大廠offer。 原創思維導圖掃碼或者微信搜?程序員的技術圈子?回復?面試?領取原創電子書和思維導圖。

總結

以上是生活随笔為你收集整理的为什么阿里巴巴RPC接口不允许使用枚举类型?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 天天久久综合网 | 国产精品久久久久久亚洲色 | 一区二区视频在线免费观看 | 日韩在线视频一区 | 国产精品成人无码专区 | 日韩欧美大片 | 日韩视频在线观看一区 | 国产丝袜视频 | 香蕉视频在线免费播放 | 自拍视频啪 | 香蕉免费在线视频 | 免费看污的网站 | 亚洲一区二区三区蜜桃 | 国产麻豆精品一区 | 午夜国产在线视频 | 久久精品视频无码 | 日本a级在线 | 天天干天天做天天操 | 中文字幕淫 | 日韩国产成人无码av毛片 | 在线观看欧美一区二区 | 人妻视频一区二区 | 日本草逼视频 | jizz日本18| 免费观看黄色一级视频 | 成人欧美一区二区三区白人 | 日本一二三区不卡 | 午夜88| 国产小视频自拍 | 国产一区二区在线免费观看视频 | 秋霞二区 | 91羞羞网站 | 五月色婷 | 欧美成人免费在线观看视频 | 亚洲欧美另类图片 | 玖玖爱这里只有精品 | 男生插女生的视频 | 欧美日本三级 | 少妇被按摩师摸高潮了 | 91sex国产| 黄色免费入口 | 国产亚洲欧美日韩精品 | 日韩精品久久久久 | 日韩欧美一区二区区 | 草草影院在线播放 | 成人免费毛片aaaaaa片 | 一级精品毛片 | 国产三级三级三级三级三级 | 美女色av | 精品人妻一区二区三区换脸明星 | 在线播放你懂得 | 国产综合在线播放 | av av片在线看| 国产一区二区女内射 | 日本特黄一级大片 | 香蕉久久夜色精品 | 美国毛片基地 | 伊朗做爰xxxⅹ性视频 | 7mav视频 | 台湾三级伦理片 | 奇米影视在线观看 | 91麻豆精品在线观看 | 天天草天天操 | 国产超碰人人模人人爽人人添 | 一级裸体片 | 亚洲自拍激情 | 天天干天天操天天爽 | av毛片观看 | 亚洲v欧美v另类v综合v日韩v | 色综合久久av | av福利在线 | 欧美视频日韩视频 | 欧美另类视频在线观看 | aaa日韩 | 涩涩涩999| 毛片网站免费在线观看 | 九九久视频 | 天天干夜夜欢 | 亚洲综合另类小说 | 中文字幕第十一页 | 国产精品中文无码 | 婷婷6月天 | 青娱乐av在线 | 中国一级黄色大片 | 日韩av在线看 | 91国在线观看 | www.在线播放 | 久久久久亚洲av无码麻豆 | 艳妇臀荡乳欲伦交换在线播放 | 爱爱视频在线看 | 永久av网站| 国产精品偷拍 | 美女视频一区二区 | 中文字幕一区二区三区四区欧美 | 999久久久国产 | 欧美mv日韩mv国产网站 | 中文字幕被公侵犯的漂亮人妻 | 日韩伦理av | 国产成人中文字幕 |