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 testSet(Set set);
 
    Object testMap(Map map);
 
    int[] testArray(int[] array);
 
    String[] testArray2(String[] strings);
 
    Date testDate(Date date);
 
    List testList(List 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 testList(List list) {
        return list;
    }
 
 
    @Override
    public Set testSet(Set set) {
        return set;
    }
 
    @Override
    public Object testMap(Map map) {
        return map;
    }
 
    @Override
    public int[] testArray(int[] array) {
        return array;
    }
 
    @Override
    public String[] testArray2(String[] strings) {
        return strings;
    }
} 
  

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

 服务端的配置和普通的没区别:provider.xml





    
    
 
    
    
    
    
 
    
    
 
    
    
 
 


消费端的配置就有些不同了,consumer.xml



 
 
    
    
 
    
    
    
    
 
    
    
 

不同点在于泛化的启用: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

你可能感兴趣的:(Dubbo)