前两天刚好有个同事来问是否用过 dubbo泛化 调用,不需要通过指定配置。第一次听到的时候,还是有点懵,但觉得有意思,可以学点东西。
立马百度了,找了demo,这篇比较容易上手(http://www.cnblogs.com/lobo/p/7129119.html)。并结合 dubbo的官方文档(http://dubbo.io/user-guide/demos/%E6%B3%9B%E5%8C%96%E5%BC%95%E7%94%A8.html)写了个demo。
provider 直接引用了 dubbo官方文档中的例子。
接口:
public interface DemoService { String sayHello(String name); }
实现类:
public class DemoServiceImpl implements DemoService { @Override public String sayHello(String name) { return "Hello " + name; } }
配置文件 provider.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> <!-- 提供方应用信息,用于计算依赖关系 --> <dubbo:application name="hello-world-app" /> <!-- 使用multicast广播注册中心暴露服务地址 --> <dubbo:registry address="zookeeper://127.0.0.1:2181" /> <!--<dubbo:registry address="multicast://224.5.6.7:1234" />--> <!-- 用dubbo协议在20880端口暴露服务 --> <dubbo:protocol name="dubbo" port="20880" /> <!-- 声明需要暴露的服务接口 --> <dubbo:service interface="persistence.dubbo.DemoService" ref="demoService" /> <!-- 和本地bean一样实现服务 --> <bean id="demoService" class="persistence.dubbo.impl.DemoServiceImpl" /> </beans>
启动类:
public class Provider { public static void main(String[] args) throws IOException { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"classpath:provider.xml"}); // new ClassPathXmlApplicationContext(new String[] {"thread/src/main/resources/provider.xml"}); context.start(); System.in.read(); // 按任意键退出 } }
结合 dubbo文档中的consumer 进行了测试,亲测可以调用成功。
然后进行 dubbo泛化调用测试。主要是通过 GenericService 来实现泛化调用。
1 public class DubboServiceFactory { 2 3 private ApplicationConfig application; 4 private RegistryConfig registry; 5 6 private static class SingletonHolder { 7 private static DubboServiceFactory INSTANCE = new DubboServiceFactory(); 8 } 9 10 private DubboServiceFactoryDemo(){ 11 Properties prop = new Properties(); 12 ClassLoader loader = DubboServiceFactory.class.getClassLoader(); 13 14 try { 15 InputStream resourceAsStream = loader.getResourceAsStream("dubboconf.properties"); 16 prop.load(loader.getResourceAsStream("dubboconf.properties")); 17 } catch (IOException e) { 18 e.printStackTrace(); 19 } 20 21 ApplicationConfig applicationConfig = new ApplicationConfig(); 22 //这个应该对应 <dubbo:registry id="${dubbo.registry.id}"/> 的id 23 //我这里测试随意些没关系 24 applicationConfig.setName("dubbo-test"); 25 //这里配置了dubbo的application信息*(demo只配置了name)*,因此demo没有额外的dubbo.xml配置文件 26 RegistryConfig registryConfig = new RegistryConfig(); 27 registryConfig.setAddress("zookeeper://127.0.0.1:2181"); 28 29 this.application = applicationConfig; 30 this.registry = registryConfig; 31 32 } 33 34 public static DubboServiceFactoryDemo getInstance() { 35 return SingletonHolder.INSTANCE; 36 } 37 38 public Object genericInvoke(String interfaceClass, String methodName, List<Map<String, Object>> parameters){ 39 40 ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>(); 41 reference.setApplication(application); 42 reference.setRegistry(registry); 43 reference.setInterface(interfaceClass); // 接口名 44 reference.setGeneric(true); // 声明为泛化接口 45 // reference.setId("reportReadService"); 46 //这里有version的必须注明 47 // reference.setVersion("1.0.0.test"); 48 49 //ReferenceConfig实例很重,封装了与注册中心的连接以及与提供者的连接, 50 //需要缓存,否则重复生成ReferenceConfig可能造成性能问题并且会有内存和连接泄漏。 51 //API方式编程时,容易忽略此问题。 52 //这里使用dubbo内置的简单缓存工具类进行缓存 53 54 ReferenceConfigCache cache = ReferenceConfigCache.getCache(); 55 GenericService genericService = cache.get(reference); 56 // 用com.alibaba.dubbo.rpc.service.GenericService可以替代所有接口引用 57 58 int len = parameters.size(); 59 String[] invokeParamTyeps = new String[len]; 60 Object[] invokeParams = new Object[len]; 61 for(int i = 0; i < len; i++){ 62 invokeParamTyeps[i] = parameters.get(i).get("ParamType") + ""; 63 invokeParams[i] = parameters.get(i).get("Object"); 64 } 65 return genericService.$invoke(methodName, invokeParamTyeps, invokeParams); 66 } 67 68 }
注:这里我把参数都直接写死了,Properties部分这里是没其作用。
这里笔者也有点没弄清楚classLoader.getResourceAsStream("dubboconf.properties"); 路径问题!!!!!!(需要课后补补课,查了一些也没太搞明白,有通俗易通的解释,麻烦和我说下,先谢过啦,??)
测试类:(别忘启动zookeeper)
1 @org.junit.Test 2 public void test1() { 3 Map map = new HashMap<>(); 4 map.put("ParamType", "java.lang.String"); //后端接口参数类型 5 map.put("Object", "world"); //用以调用后端接口的实参 6 7 List<Map<String, Object>> paramInfos= new ArrayList<>(); 8 paramInfos.add(map); 9 10 DubboServiceFactory dubbo = DubboServiceFactory.getInstance(); 11 12 Object getReportResult = dubbo.genericInvoke("persistence.dubbo.DemoService", "sayHello", paramInfos); 13 14 System.out.println(getReportResult); 15 16 Map result = (Map) getReportResult; 17 }
dubbo泛化的小demo就这样完成了,应用到实际项目中,只要把参数提出来,写到配置文件就好了。
这里只是为了做个小demo,只是为了实现dubbo泛化调用功能,先动起来而已。其中有一些类、方法、参数的含义,需要自己再去深入了解。我本人也只是用了dubbo而已,很多东西也还没去深入学习。
想养成写技术博客的习惯,从这里开始。目前格式排布还有很大改进,在后续中慢慢学习改变。欢迎大家指正!!
时间: 2024-10-31 01:09:26