Dubbo 是支持泛化调用的,什么是泛化调用呢,泛化调用的好处是什么呢,泛化调用说白一点就是服务消费者并没有服务的接口,学了前面几章的内容之后,你肯定会发现,在我们开发写Demo的时候,必做的一件事情,就是在服务消费者和服务提供者两端同路径下有同样的接口,只不过在服务提供者端会有该接口的具体实现,之所以在服务消费者有一个没有任何具体实现的接口,是因为在设计RPC之初,设计者的最高理念就是你去面向接口编程,你在进行远程调用的时候,并没有意识到你在进行远程调用,却也能拿到接口一样,相信你也感觉到了,服务消费者在调用服务的时候,与调用一个普通的接口是一样的。
泛化调用就是服务消费者端因为某种原因并没有该服务接口,这个原因有很多,比如是跨语言的,一个PHP工程师想调用某个java接口,他并不能按照你约定,去写一个个的接口,Dubbo并不是跨语言的RPC框架,但并不是不能解决这个问题,这个PHP程序员搭建了一个简单的java web项目,引入了dubbo的jar包,使用dubbo的泛化调用,然后利用web返回json,这样也能完成跨语言的调用。泛化调用的好处之一就是这个了
好了,简而言之,泛化调用,最最直接的表现就是服务消费者不需要有任何接口的实现,就能完成服务的调用。
3.5.1 泛化调用入门
老规矩,我们现在服务提供者端定义一个简单的接口,(与往常不一样的地方就是不需要把该接口复制到服务提供者的同路径下了,因为服务消费者不需要使用该接口进行调用),好了,定义一个简单的接口EasyCommonService.java
package org.bazinga.service;
public interface EasyCommonService {
public String helloService(String name);
}
该接口的具体实现EasyCommonServiceImpl.java
package org.bazinga.service.impl;
import org.bazinga.service.EasyCommonService;
public class EasyCommonServiceImpl implements EasyCommonService {
public String helloService(String name) {
System.out.println("name is "+ name);
return "hello " + name;
}
}
服务提供者端的Spring的配置文件spring-dubbo-provider-generic.xml
服务提供者端再写一个启动类DubboxProviderGenericService.java:
package org.bazinga.service.test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class DubboxProviderGenericService {
public static void main(String[] args) throws InterruptedException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
"spring-dubbo-provider-generic.xml");
context.start();
Thread.sleep(2000000l);
}
}
好了,到此为止,泛化调用服务提供者的配置文件就全部结束了,你可以看到从代码和spring的配置文件都没有任何特殊处理,与一般的服务提供者并没有任何的不同,泛化调用,从这四个字看也知道是调用的方式不一样而已,我们再看看服务消费者端的代码编写
因为服务消费者没有了接口,我们直接编写消费者端spring的配置文件spring-dubbo-consumer-generic.xml
可以看到上图的配置文件中有两个地方需要注意一下,第一个是interface,其实该接口在消费者端并不存在,这是与往常写的不一样的地方,第二个地方需要注意的地方就是generic=”true”这样的标签,表示该接口支持泛型调用。
好了,我们写一个服务测试类,看看如何进行泛型调用DubboConsumerGenericService.java
package org.bazinga.service.test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.alibaba.dubbo.rpc.service.GenericService;
public class DubboConsumerGenericService {
public static void main(String[] args) {
/////////////////Spring泛化调用/////////
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
"spring-dubbo-consumer-generic.xml");
context.start();
GenericService easyCommonService = (GenericService) context.getBean("easyCommonService");
Object result = easyCommonService.$invoke("helloService", new String[] { "java.lang.String" }, new Object[] { "hello" });
System.out.println(result);
}
}
看到Main函数中,从spring的上下文中读到”easyCommonService”之后却把它强转为GenericService的类,然后调用GenericService的$invoke的方法,该方法有三个参数,第一个参数是你调用远程接口的具体方法名,第二个参数是helloService这个方法的入参的类型,最后一个参数是值。
我们测试一下,启动DubboxProviderGenericService的main函数,然后启动服务消费者的测试类DubboConsumerGenericService.java,你会发现控制台打印:
可以看到能够调通,没有问题。
我们刚才说,一个PHP程序员想要搭建一个简单的web项目,可是你却叫他依赖于spring的配置文件,对他难度是不小的,dubbo也帮你想到了,泛型调用,服务消费端可以不依赖spring的配置文件,我们重新写下测试类DubboConsumerGenericService:
package org.bazinga.service.test;
import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ReferenceConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.utils.ReferenceConfigCache;
import com.alibaba.dubbo.rpc.service.GenericService;
public class DubboConsumerGenericService {
public static void main(String[] args) {
// 普通编码配置方式
ApplicationConfig application = new ApplicationConfig();
application.setName("bazinga-consumer");
// 连接注册中心配置
RegistryConfig registry = new RegistryConfig();
registry.setAddress("zookeeper://127.0.0.1:2181");
ReferenceConfig reference = new ReferenceConfig();
reference.setApplication(application);
reference.setRegistry(registry);
reference.setInterface("org.bazinga.service.EasyCommonService");
reference.setGeneric(true); // 声明为泛化接口
ReferenceConfigCache cache = ReferenceConfigCache.getCache();
GenericService genericService = cache.get(reference);
// 基本类型以及Date,List,Map等不需要转换,直接调用
Object result = genericService.$invoke("helloService", new String[] { "java.lang.String" },
new Object[] { "world" });
System.out.println(result);
}
}
重新启动一下该类。控制台正常打印:
也能正常进行调用。
3.5.2 泛化调用小结
泛化调用可以方便用户对dubbo服务消费者端的扩展,可以方便,丰富了服务消费者的调用方式,甚至可以做变相的Rest调用,这些都是可以的,不过,它的缺点也是很明显的,参数传递复杂,不方便使用。但是这种方式是不能缺失的。