首先简单说一下 Dubbo 是什么呢?不懂的同学百度一下去吧!
在 Dubbo 里面有两个概念:
1:Provider 暴露服务的服务提供方 (接口提供方)
2:Consumer 调用远程服务的服务消费方 (接口调用方)
下面是应用 A 依赖应用 B 的 UserService 接口,在工程里面代码的配置
Dubbo 的应用是以 spring 注入服务,首先应用 B 要发布一个接口
一、应用 B 发布一个 UserService 接口
1.首先有一个 UserServce 接口类
package com.test.service;
public interface UserService{
public User getUser(User user);
}
2.来一个 DTO 的 User 类
public class User{
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
3.接口类和参数类创建好之后,通过 spring 发布接口,接口发布到 zookeeper 里面,我这里没有写接口的实现,这里用不到
<!-- 提供方应用名称信息,这个相当于起一个名字,我们dubbo管理页面比较清晰是哪个应用暴露出来的 -->
<dubbo:application name="dubbo_provider"></dubbo:application>
<!-- 使用zookeeper注册中心暴露服务地址 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181" check="false" subscribe="false" register=""></dubbo:registry>
<!-- 要暴露的服务接口 -->
<dubbo:service interface="com.test.service.UserService" ref="userService" />
二、应用 A 引用应用 B 发布的 UserService 接口
1.dubbo 服务框架要求接口调用方和接口提供方的 java 接口文件和参数类型保持一直,所以我们需要服务端提供发布的接口类和参数类,通常服务端会通过 Maven 发布接口的 Jar 包共服务调用方 (这里的应用 A) 使用,并且参数类要进行序列化可以,入参通过序列化之后到服务端在反序列化,序列化这块大家百度不细说
2.假设我们的应用 A 引入的应用 A 提供的 jar 包
3.通过 spring 注册接口引用的接口
<dubbo:application name="dubbo_consumer"></dubbo:application>
<!-- 使用zookeeper注册中心暴露服务地址 -->
<dubbo:registry address="zookeeper://192.168.74.129:2181" check="false"></dubbo:registry>
<!-- 要引用的服务 -->
<dubbo:reference interface="com.test.service.UserService" id="userService"></dubbo:reference>
那么我们采取另外一个方式,filter 过滤器,filter 是放在客户端的 (应用 A),通过拦截请求,如何配置 filter 参考http://blog.csdn.net/mj158518/article/details/47379799
配置 filter 之后呢应用 A 的请求首先会到 filter 里面
public class CustomConsumerFilter implements Filter {
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
Result result = null; //首先定义一个返回对象;
String interfaceName = invoker.getUrl().getPath(); //获取接口名称
String methodName = invocation.getMethodName(); //获取方法名称
Object[] arguments =invocation.getArguments(); //获取参数,我举的例子是一个参数,实际可能有多个参数,多种类型,
String paramJson =JSON.toJSONString(arguments, SerializerFeature.WriteClassName);//这里面可能有泛型,所以入参在序列化时要上json
List<String> paramTypes = reflectTools.getMethodParameterType(interfaceName, methodName); //获取所有的入参类型,这块要自己写反射处理
String methodReturnType = reflectTools.getMethodTypeReturnString(interfaceName, methodName); //获取被调用方法返回类型,这块要自己写反射处理
//上面两行可以拿到入参类型和返回值的类型,是因为我们在客户端只用里面有参数类
//下面定义一个httpclient,用于发送Http请求,首先我们发送一个请求,确认这个接口的这个方法是否在我们测试平台存在了
Map paramMap = new HashMap();
paramMap.put("interfaceName", interfaceName);
paramMap.put("methodName", methodName);
String r = requestClient.send(paramMap, "getInterfaceInfo");
//如果不存在,调用真实的接口获取返回值,
result = invoker.invoke(invocation); //调用真实接口
//然后把接口信息存在我们的测试平台
}
}
具体的代码我就不写了,下面弄个逻辑图吧,里面各种类型处理,用户选择匹配 MOCK 返回数据等,太多了代码
测试平台,用户选择匹配
测试平台,用户配置 MOCK 返回数据,这里面的关键字,决定用户需要什么样的返回数据,MOCK 数据不是死的是可以配置的
那么大家用这种方式会发现,需要把我们的 filter 包放到应用 A 里面,并且配置 spring 的接口文件,相信大家都有自动部署,可以在部署过程中,直接扫描 spring.xml 找出接口,默认全部加上 filter,同时把我们的 filter 包也放到应用的 lib 下,做到用户不感知,达到自动 MOCK 的生态
上面细节的东西不是很多,主要是讲一种思路,这个文章懂 dubbo 的人可能更容易理解,欢迎大家讨论