Dubbo泛化调用

  dubbo消费端,一般必须依赖服务端提供的api包,服务端api包一旦升级,消费端也要跟着升级(依赖的情况下),不像spring cloud一样,采用rest协议,对服务端的api依赖几乎可以没有,不过dubbo也有rest协议扩展,见当当网dubbox,也有jsonrpc协议的扩展,见https://github.com/apache/incubator-dubbo-rpc-jsonrpc ,都不依赖服务端提供的api包。

    dubbo消费端做到不依赖服务端提供的api,除了rest协议及jsonrpc协议扩展,dubbo也有一个功能可以做到,这个功能就是dubbo的泛化调用:

   泛化接口调用方式主要用于客户端没有 API 接口及模型类元的情况,参数及返回值中的所有 POJO 均用 Map 表示,通常用于框架集成,比如:实现一个通用的服务测试框架,可通过 GenericService 调用所有服务实现。

--引文:官方文档http://dubbo.apache.org/#/docs/user/demos/generic-reference.md?lang=zh-cn

 

 泛化调用的实现主要涉及到两个filter类:

    com.alibaba.dubbo.rpc.filter.GenericFilter
    com.alibaba.dubbo.rpc.filter.GenericImplFilter
分别在服务端和消费端做处理。

先看个简单的例子:

package com.sdcuike.dubbo.learning.service;
 
import com.alibaba.fastjson.JSONObject;
 
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
 
/**
 * @author sdcuike
 * @date 2018/5/31
 * @since 2018/5/31
 */
public interface HystrixService {
 
    String echo();
 
    int echo(int primitive);
 
    JSONObject testGener(String para);
 
    String testGenerRe(String para);
 
    String test(Par par);
 
    Set<String> testSet(Set<String> set);
 
    Object testMap(Map<String, Object> map);
 
    int[] testArray(int[] array);
 
    String[] testArray2(String[] strings);
 
    Date testDate(Date date);
 
    List<Object> testList(List<Object> list);
 
    public static class Par {
        private String name;
        private int age;
 
        public String getName() {
            return name;
        }
 
        public void setName(String name) {
            this.name = name;
        }
 
        public int getAge() {
            return age;
        }
 
        public void setAge(int age) {
            this.age = age;
        }
    }
 
    public static void main(String[] args) {
        System.out.println(Par.class.toString());
    }
}
package com.sdcuike.dubbo.learning.service.impl;
 
import com.alibaba.fastjson.JSONObject;
import com.sdcuike.dubbo.learning.service.HystrixService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
 
/**
 * @author sdcuike
 * @date 2018/5/31
 * @since 2018/5/31
 */
public class HystrixServiceImpl implements HystrixService {
    private Logger logger = LoggerFactory.getLogger(getClass());
 
    private AtomicLong atomicLong = new AtomicLong(0);
 
    private long startTimeMill = 0;
 
 
    @Override
    public String echo() {
        return "hello no param";
    }
 
    @Override
    public int echo(int primitive) {
        return primitive;
    }
 
    @Override
    public JSONObject testGener(String para) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("para", para);
        return jsonObject;
    }
 
    @Override
    public String testGenerRe(String para) {
 
        return "haha " + para;
    }
 
    @Override
    public String test(Par par) {
        return "wowo " + par.getName() + par.getAge();
    }
 
    @Override
    public Date testDate(Date date) {
        return date;
    }
 
    @Override
    public List<Object> testList(List<Object> list) {
        return list;
    }
 
 
    @Override
    public Set<String> testSet(Set<String> set) {
        return set;
    }
 
    @Override
    public Object testMap(Map<String, Object> map) {
        return map;
    }
 
    @Override
    public int[] testArray(int[] array) {
        return array;
    }
 
    @Override
    public String[] testArray2(String[] strings) {
        return strings;
    }
}

 上面代码定义了一个接口一个该接口对应的实现类。

 服务端的配置和普通的没区别: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="provider-test"/>
 
    <!-- 使用multicast广播注册中心暴露服务地址 -->
    <dubbo:registry address="zookeeper://127.0.0.1:2181"/>
    <!-- 用dubbo协议在20880端口暴露服务 -->
    <dubbo:protocol name="dubbo" port="20088" host="127.0.0.1"/>
 
    <!-- 声明需要暴露的服务接口 -->
    <dubbo:service interface="com.sdcuike.dubbo.learning.service.HystrixService" ref="hystrixService" />
 
    <!-- 和本地bean一样实现服务 -->
    <bean id="hystrixService" class="com.sdcuike.dubbo.learning.service.impl.HystrixServiceImpl"/>
 
 
</beans>

消费端的配置就有些不同了,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="consumer-test"/>
 
    <!-- 使用multicast广播注册中心暴露服务地址 -->
    <dubbo:registry address="zookeeper://127.0.0.1:2181"/>
    <dubbo:protocol name="dubbo"/>
    <dubbo:consumer timeout="3000" check="false"/>
 
    <!-- 声明需要暴露的服务接口 -->
    <dubbo:reference id="hystrixService" interface="com.sdcuike.dubbo.learning.service.HystrixService"
                     generic="true"
                     retries="0"/>
 
</beans>

不同点在于泛化的启用:generic="true"。

写个测试用例:启动服务端:

ProviderTest
package com.sdcuike.dubbo.learning.service;
 
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
import java.util.concurrent.TimeUnit;
 
/**
 * @author sdcuike
 * @date 2018/5/31
 * @since 2018/5/31
 */
public class ProviderTest {
 
    @Test
    public void test() throws Exception {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"provider.xml"});
        context.start();
 
        TimeUnit.HOURS.sleep(1);
 
    }
}

消费端测试用例:DubboGenericConsumerXmlTest,

package com.sdcuike.dubbo.learning.service;
 
import com.alibaba.dubbo.rpc.service.GenericService;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
/**
 * @author sdcuike
 * @date 2018/7/14
 * @since 2018/7/14
 */
public class DubboGenericConsumerXmlTest {
 
    GenericService hystrixService;
 
    @Before
    public void init() {
 
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"consumer.xml"});
 
        hystrixService = (GenericService) context.getBean("hystrixService");
    }
 
 
    @Test
    public void testGenerRe_参数为基本类型_参数类型传递() throws InterruptedException {
 
 
        Object result = hystrixService.$invoke("testGenerRe", new String[]{"java.lang.String"}, new Object[]{"test"});
 
        Assert.assertEquals("haha test", result.toString());
 
    }
 
    @Test
    public void testGenerRe_参数为基本类型_参数类型不传递() throws InterruptedException {
 
 
        Object result = hystrixService.$invoke("testGenerRe", null, new Object[]{"test"});
 
        Assert.assertEquals("haha test", result.toString());
 
    }
 
    @Test
    public void test_echo_无参数_有重载方法() {
 
        final Object echo = hystrixService.$invoke("echo", new String[]{}, null);
 
        Assert.assertEquals("hello no param", echo.toString());
    }
 
}

不同以往的消费端服务引用,我们这里引用的泛化接口com.alibaba.dubbo.rpc.service.GenericService。

再调用相应服务方法的时候,我们必须显示的传递方法名及参数,但对于参数类型我们可以不必传递, 但方法重载的情况下,我们必须传递

源码见:

https://github.com/sdcuike/all_learning_201806/tree/master/dubbo-learning/src/test/java/com/sdcuike/dubbo/learning/service

dubbo泛化调用-泛化调用平台 

https://blog.csdn.net/doctor_who2004/article/details/81051226

原文:https://blog.csdn.net/doctor_who2004/article/details/80961426 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值