公司是采用微服务来做模块化的,各个模块之间采用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,需要注意传入的参数与类型问题
通过这样一个小工具,又对反射有了更进一步的了解。????))))))))
参考: