公司是采用微服務來做子產品化的,各個子產品之間采用dubbo通信。好處就不用提了,省略了之前子產品間複雜的http通路。不過也遇到一些問題:
對于開發來說,倒是挺省勁。但是對于測試來說就有點麻煩了, 每次還要去寫dubbo的消費程式,而且每次新增一個接口,都需要重新改寫程式,費時費力。
由于我這邊是做一些商品的推薦,每次結果的類型都是相同的,隻是内部的算法不同。不過接口隻是傳回id,無法直覺的判斷商品相似程度或者使用者的偏好程度,需要一個可視化的傳回結果界面。
于是在這種需求下,我設想了一個小程式,它可以滿足下面的功能:
測試可以根據測試需要,在界面自動選擇請求的class和方法
開發完成後,測試界面自動掃描出dubbo的提供者的class和對應的方法
傳回結果自動請求對應的圖檔和文字說明
提前放一個效果圖:

小程式開始的第一步就是需要掃描某個包下所有的dubbo實作類。
由于工程是springboot,是以最終部署是在jar中。這時,就需要面臨兩個問題,如果是在開發工具中,如何擷取包下的所有類;如果是在jar中,如何擷取包下所有的類。
首先通過classloader可以加載特定路徑下的所有URL:
在工程中,class其實是以目錄形式存放在本地的,直接按照file的方式周遊掃描class檔案就行了:
jar包是一種特殊的壓縮包,java提供了JarFile類的entries方法,可以周遊jar中所有的檔案。不過這裡就沒有目錄或者檔案的差別了,因為都是一個zip包中的資源而已。是以最後需要針對報名進行一下過濾:
然後通過反射可以直接通過class的名字,拿到它的所有方法,這些方法裡面包含了一些通用的方法,如wait,notify等,需要給過濾掉。
這裡需要注意,兩個不同參數的方法,雖然名字相同,但是他們的parameterTypes是不同的。是以這裡最好直接傳回method,把name和parameterTypes一同作為結果傳回。因為最終invoke的時候,還得通過參數類型把所有的參數都轉換類型一下。
第三個難點,就是前端傳過來的參數都是字元串,比如:
<code>com.xingoo.test.Provider1Impl</code> 是對應的class
<code>test1</code> 是對應的方法
<code>100</code> 是對應的參數
<code>java.lang.Long</code> 是參數對應的類型
怎麼能把請求通過正确的dubbo provider執行呢?——答案 就是Bean
因為在Spring的項目中,dubbo的provider都是一個單例的bean。是以可以直接通過applicationContext獲得對應的bean,隻要保證bean的名字能規律的映射過來就行。
可以參考下面的擷取bean的方法:
在真正的實作類上,需要指定bean的名字:
然後利用反射,就可以執行這個bean的特定方法了:
對應參數處理的兩個方法是:
最後就是jquery基于ajax請求,查詢對應的接口結果就行了。需要注意ajax的同步問題:
總結來說,下面是遇到的問題和簡單的對應辦法:
1 如何掃描工程或者普通web項目 某個包下的class——通過classloader獲得路徑,直接周遊file即可
2 如何掃描jar中某個包下的class——通過JarFile獲得對應的JarEntry
3 如何擷取Spring Boot中的Bean——通過實作ApplicationContextAware接口,擷取applicationContext的引用
4 如何動态執行某個對象的特定方法——基于反射method.invoke,需要注意傳入的參數與類型問題
通過這樣一個小工具,又對反射有了更進一步的了解。????))))))))
參考: