Dubbo 是支持泛化调用的,什么是泛化调用呢?泛化调用的好处是什么呢,泛化调用说白一点就是服务消费者并没有服务的接口。

  在《Dubbo入门—搭建一个最简单的Demo框架》一文中,我们已完成了最最基本的Dubbo的搭建及调用,我们的dubbo-provider、dubbo-consumer、dubbo-consumer2都是依赖dubbo-api,而dubbo-api其实什么也没做,就定义了一个接口,也就是说,在我们开发写Demo的时候,必做的一件事情,就是在服务消费者和服务提供者两端同路径下有同样的接口,只不过在服务提供者端会有该接口的具体实现,之所以在服务消费者有一个没有任何具体实现的接口,是因为在设计RPC之初,设计者的最高理念就是你去面向接口编程,你在进行远程调用的时候,并没有意识到你在进行远程调用,却也能拿到接口一样,相信你也感觉到了,服务消费者在调用服务的时候,与调用一个普通的接口是一样的。

  泛化调用就是服务消费者端因为某种原因并没有该服务接口,这个原因有很多,比如是跨语言的,一个PHP工程师想调用某个java接口,他并不能按照你约定,去写一个个的接口,Dubbo并不是跨语言的RPC框架,但并不是不能解决这个问题,这个PHP程序员搭建了一个简单的java web项目,引入了dubbo的jar包,使用dubbo的泛化调用,然后利用web返回json,这样也能完成跨语言的调用。泛化调用的好处之一就是这个了。

  好了,简而言之,泛化调用,最最直接的表现就是服务消费者不需要有任何接口的实现,就能完成服务的调用。

一.泛化调用入门

  老规矩,我们现在服务提供者端定义一个简单的接口,(与往常不一样的地方就是不需要把该接口复制到服务提供者的同路径下了,因为服务消费者不需要使用该接口进行调用),在这我们就继续用《Dubbo入门—搭建一个最简单的Demo框架》一文中的案例代码。

  定义一个简单的接口DemoService.java

package com.alibaba.dubbo.demo;

import java.util.List;

public interface DemoService {
List<String> getPermissions(Long id);
}

  该接口的具体实现DemoServiceImpl.java

package com.alibaba.dubbo.demo.impl;

import com.alibaba.dubbo.demo.DemoService;

import java.util.ArrayList;
import java.util.List; public class DemoServiceImpl implements DemoService {
public List<String> getPermissions(Long id) {
List<String> demo = new ArrayList<String>();
demo.add(String.format("Permission_%d", id - 1));
demo.add(String.format("Permission_%d", id));
demo.add(String.format("Permission_%d", id + 1));
return demo;
}
}

  服务提供者端的Spring的配置文件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-admin 或 dubbo-monitor 会显示这个名字,方便辨识-->
<dubbo:application name="demotest-provider" owner="programmer" organization="dubbox"/>
<!--使用 zookeeper 注册中心暴露服务,注意要先开启 zookeeper-->
<dubbo:registry address="zookeeper://localhost:2181"/>
<!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20880" />
<!--使用 dubbo 协议实现定义好的 api.PermissionService 接口-->
<dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService" protocol="dubbo"/>
<!--具体实现该接口的 bean-->
<bean id="demoService" class="com.alibaba.dubbo.demo.impl.DemoServiceImpl"/>
</beans>

  服务提供者端再写一个启动类Provider.java:

package com.alibaba.dubbo.demo.impl;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.IOException;

public class Provider {
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
"provider.xml");
System.out.println(context.getDisplayName() + ": here");
context.start();
System.out.println("服务已经启动...");
System.in.read();
}
}

  好了,到此为止,泛化调用服务提供者的配置文件就全部结束了,你可以看到从代码和spring的配置文件都没有任何特殊处理,与一般的服务提供者并没有任何的不同,泛化调用,从这四个字看也知道是调用的方式不一样而已,我们再看看服务消费者端的代码编写。

  因为服务消费者没有了接口,我们直接编写消费者端spring的配置文件consumer.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="demotest-consumer" owner="programmer" organization="dubbox"/>
<!--向 zookeeper 订阅 provider 的地址,由 zookeeper 定时推送-->
<dubbo:registry address="zookeeper://localhost:2181"/>
<!--使用 dubbo 协议调用定义好的 api.PermissionService 接口-->
<dubbo:reference id="permissionService" interface="com.alibaba.dubbo.demo.DemoService" generic="true"/>
</beans>

  可以看到上图的配置文件中有两个地方需要注意一下,第一个是interface,其实该接口在消费者端并不存在,这是与往常写的不一样的地方,第二个地方需要注意的地方就是generic=”true”这样的标签,表示该接口支持泛型调用。

  好了,我们写一个服务测试类,看看如何进行泛型调用Consumer.java

package com.alibaba.dubbo.consumer;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.alibaba.dubbo.rpc.service.GenericService;

public class Consumer {
public static void main(String[] args) {
/////////////////Spring泛化调用/////////  
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("consumer.xml");
context.start();
System.out.println("consumer start");
GenericService demoService = (GenericService) context.getBean("permissionService");
System.out.println("consumer");
Object result = demoService.$invoke("getPermissions", new String[] { "java.lang.Long" }, new Object[]{ 1L });
System.out.println(result);
}
}

  看到Main函数中,从spring的上下文中读到”permissionService”之后却把它强转为GenericService的类,然后调用GenericService的$invoke的方法,该方法有三个参数,第一个参数是你调用远程接口的具体方法名,第二个参数是permissionService这个方法的入参的类型,最后一个参数是值。

  我们测试一下,启动dubbo-provider的main函数,然后启动服务消费者的测试类Consumer.java,你会发现控制台打印:

[22/04/18 05:06:36:036 CST] main  INFO config.AbstractConfig:  [DUBBO] Refer dubbo service com.alibaba.dubbo.rpc.service.GenericService from url zookeeper://localhost:2181/com.alibaba.dubbo.registry.RegistryService?anyhost=true&application=demotest-consumer&check=false&dubbo=2.5.3&generic=true&interface=com.alibaba.dubbo.demo.DemoService&methods=getPermissions&organization=dubbox&owner=programmer&pid=6604&side=consumer&timestamp=1524387995725, dubbo version: 2.5.3, current host: 10.39.56.134
consumer
[Permission_0, Permission_1, Permission_2]

  可以看到能够调通,没有问题。

  我们刚才说,一个PHP程序员想要搭建一个简单的web项目,可是你却叫他依赖于spring的配置文件,对他难度是不小的,dubbo也帮你想到了,泛型调用,服务消费端可以不依赖spring的配置文件,我们重新写下测试类Consumer:

package com.alibaba.dubbo.consumer;

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 Consumer {
public static void main(String[] args) { // 普通编码配置方式
ApplicationConfig application = new ApplicationConfig();
application.setName("dubbo-consumer"); // 连接注册中心配置
RegistryConfig registry = new RegistryConfig();
registry.setAddress("zookeeper://127.0.0.1:2181"); ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>();
reference.setApplication(application);
reference.setRegistry(registry);
reference.setInterface("com.alibaba.dubbo.demo.DemoService");
reference.setGeneric(true); // 声明为泛化接口 ReferenceConfigCache cache = ReferenceConfigCache.getCache();
GenericService genericService = cache.get(reference); // 基本类型以及Date,List,Map等不需要转换,直接调用
Object result = genericService.$invoke("getPermissions", new String[] { "java.lang.Long" },
new Object[] { 1L });
System.out.println(result);
}
}

  重新启动一下该类。控制台正常打印:

[22/04/18 05:09:09:009 CST] main  INFO config.AbstractConfig:  [DUBBO] Refer dubbo service com.alibaba.dubbo.rpc.service.GenericService from url zookeeper://127.0.0.1:2181/com.alibaba.dubbo.registry.RegistryService?anyhost=true&application=dubbo-consumer&check=false&dubbo=2.5.3&generic=true&interface=com.alibaba.dubbo.demo.DemoService&methods=getPermissions&organization=dubbox&owner=programmer&pid=21144&side=consumer&timestamp=1524388149244, dubbo version: 2.5.3, current host: 10.39.56.134
[Permission_0, Permission_1, Permission_2]

  也能正常进行调用。

二.泛化调用小结

  泛化调用可以方便用户对dubbo服务消费者端的扩展,可以方便,丰富了服务消费者的调用方式,甚至可以做变相的Rest调用,这些都是可以的,不过,它的缺点也是很明显的,参数传递复杂,不方便使用。但是这种方式是不能缺失的。

参考文章:https://blog.csdn.net/linuu/article/details/54313560

实例代码:http://bijian1013.iteye.com/blog/2419726

Dubbo基本特性之泛化调用的更多相关文章

  1. Dubbo高级特性实践-泛化调用

    引言 当后端Java服务用Dubbo协议作为RPC方案的基础,但部分消费方是前端Restful的PHP服务,不能直接调用,于是在中间架设了Router服务提供统一的基于HTTP的后端调用入口. 而Ro ...

  2. Dubbo 高级特性实践-泛化调用

    引言 当后端Java服务用Dubbo协议作为RPC方案的基础,但部分消费方是前端Restful的PHP服务,不能直接调用,于是在中间架设了Router服务提供统一的基于HTTP的后端调用入口. 而Ro ...

  3. Dubbo学习笔记4:服务消费端泛化调用与异步调用

    本文借用dubbo.learn的Dubbo API方式来解释原理. 服务消费端泛化调用 前面我们讲解到,基于Spring和基于Dubbo API方式搭建简单的分布式系统时,服务消费端引入了一个SDK二 ...

  4. dubbo接口泛化调用例子

    @ApiOperation(value = "dubbo泛化调用工具接口") public Result dubboApiTool( @ApiParam(value = " ...

  5. dubbo泛化调用 小demo

    前两天刚好有个同事来问是否用过 dubbo泛化 调用,不需要通过指定配置.第一次听到的时候,还是有点懵,但觉得有意思,可以学点东西. 立马百度了,找了demo,这篇比较容易上手(http://www. ...

  6. dubbo的泛化调用研究

    结论: 泛化调用需要继承一个类,在配置文件里需要明确指出generic=true; 泛化调用在书写provider代码时,变化不大: 泛化调用和普通调用的区别主要在consumer,从‘调用’的表面意 ...

  7. SOFARPC —— Generic Service (泛化调用) 解析

    今晚心情无比激动,多云转晴!原因在于弄懂些 Generic Service 实现原理,很有成就感. 各位看官莫笑,今晚,小小的收获,也是非常满足的.下面进入正题! 一.前言 普遍RPC在客户端需要提供 ...

  8. Dubbo 源码分析 - 服务调用过程

    注: 本系列文章已捐赠给 Dubbo 社区,你也可以在 Dubbo 官方文档中阅读本系列文章. 1. 简介 在前面的文章中,我们分析了 Dubbo SPI.服务导出与引入.以及集群容错方面的代码.经过 ...

  9. pinpoint-dubbo插件兼容泛化调用

    背景 dubbo插件中需要记录当前调用的接口和方法,但是在泛化调用的场景下,记录的接口和方法都变成了 com.alibaba.dubbo.rpc.service.GenericService:$inv ...

随机推荐

  1. JQuery纵向下拉菜单实现心得

    jquery库给我们带来了许多便利,不愧是轻量级的DOM框架,在前面的博文中小编分别对jquery的基础知识以及jquery的一些小demo有一系列的简单介绍,期待各位小伙伴的指导.使用jquery实 ...

  2. Java正则表达式小记

    http://blog.csdn.net/pipisorry/article/details/51059500 正则表达式的一般规则都一样,见[python正则表达式] java正则表达式中的特殊字符 ...

  3. 【原创】Eclipse vs. IDEA快捷键对比大全

    花了一天时间熟悉IDEA的各种操作,将各种快捷键都试了一下,感觉很是不错!于是就整理了一下我经常用的一些Eclipse快捷键与IDEA的对比,方便像我一样使用Eclipse多年但想尝试些改变的同学们. ...

  4. 【一天一道LeetCode】#111. Minimum Depth of Binary Tree

    一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 Given a ...

  5. maven -Dmaven.multiModuleProjectDirectory system propery is not set. Check $M2_HOME

    遇到错误:-Dmaven.multiModuleProjectDirectory system propery is not set. Check $M2_HOME解决办法:在环境变量中设置M2_HO ...

  6. pandas小记:pandas基本设置

    http://blog.csdn.net/pipisorry/article/details/49519545 ): print(df) Note: 试了好久终于找到了这种设置方法! 它是这样实现的 ...

  7. Leetcode_67_Add Binary

    本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/40480151 Given two binary strin ...

  8. Java编写的接口测试工具

    这几天由于要频繁地使用一些天气数据接口,但是每次都要频繁的打开网页,略显繁琐,故就自己做了两个json数据获取的小工具. 第一个 先来看看第一个吧,思路是使用一个网络流的处理,将返回的json字符串数 ...

  9. Ajax 初步学习总结

    Ajax是什么 Ajax是(Asynchronous JavaScript And XML)是异步的JavaScript和xml.也就是异步请求更新技术.Ajax是一种对现有技术的一种新的应用,不是一 ...

  10. H5学习之旅-H5的表单(11)

    H5的表单元素 form:表单 input:输入域,type属性可以设置text,password,button等不同的属性 textarea:文本域 lable:控制标签 fieldset:定义域 ...