一.父子類有相同屬性時值丟失
假設Provider提供的服務中某個服務的參數(shù)是WordDTO矾湃,并且WordDTO繼承自BaseDTO铃绒,兩個類的定義如下:
image.png
問題描述:在Consumer側給WordDTO賦的值炼彪,其id屬性的值無法在Provider側獲取到莹规。假設Consumer傳的值是:{"id":68,"timestamp":1570928394380,"uuid":"f774f99f-987c-4506-8ab8-366cd619bb15","word":"hello world"},在Provider拿到的卻是:{"timestamp":1570928394380,"uuid":"f774f99f-987c-4506-8ab8-366cd619bb15","word":"hello world"}
原因分析:dubbo默認采用的是hessian序列化&反序列化方式忧额,JavaDeserializer在獲取fileds時厘肮,采用了Map去重。但是在讀取值時睦番,根據(jù)serializer的順序类茂,對于同名字段,子類的該字段值會被賦值兩次托嚣,總是被父類的值覆蓋巩检,導致子類的字段值丟失。
解決方案:
更改序列化方式(不建議)
刪掉子類中與父類同名屬性(建議)
二.自定義異常被包裝成RuntimeException
首先需要說明的是示启,出現(xiàn)這個問題有一定的條件兢哭。如果Provider中的api和自定義Exception定義都是在一個api.jar中,那么是不會有任何問題的夫嗓。但是如果自定義Exception是在一個單獨的比如common.jar包中就會出現(xiàn)這個問題(此時api和model在另一個api.jar中)迟螺。
下面是一段調(diào)用一個會拋出自定義異常的服務的代碼:
image.png
但是,調(diào)用的日志卻是如下所示啤月,通過日志我們可以發(fā)現(xiàn)煮仇,在Consumer中并沒有捕獲到自定義的WrongArgumentException異常劳跃,只能捕獲到RuntimeException中的異常谎仲,且這個異常信息是封裝自定義的WrongArgumentException異常.
image.png
這是什么原因呢?這是因為dubbo Provider的ExceptionFilter.java對異常統(tǒng)一封裝導致的刨仑,其封裝的核心源碼我就不貼出來了郑诺,你如果有興趣可以自己下載查看夹姥。我這里只貼出它的處理邏輯,當碰到如下這些情況時辙诞,dubbo會直接拋出異常.
(1)如果是checked異常(不是RuntimeException但是是Exception.java類型的異常)辙售,直接拋出
(2)在方法簽名上有聲明(例如String saySomething()throws MyException ),直接拋出
(3)異常類和接口類在同一jar包里飞涂,直接拋出旦部;
(4)是JDK自帶的異常(全類名以java或者javax開頭,例如java.lang.IllegalStateException)较店,直接拋出
(5)是Dubbo本身的異常RpcException士八,直接拋出;
否則梁呈,Dubbo通過如下代碼將異常包裝成RuntimeException拋給客戶端
通過上面對ExceptionFilter的源碼分析可知婚度,如果要讓Provider拋出自定義異常,有如下幾個解決辦法:
將自定義異常和接口類放到一個包中即可(推薦)官卡;
方法簽名上申明自定義異常蝗茁;