dubbo支持泛化调用
1、开发工程中 有时候想要测试dubbo接口 需要自定义用例,比较麻烦
2、无法调用服务器上的dubbo测试
3、无法随意调用多版本的服务
由于dubbo支持泛化调用 所以这些问题就迎刃而解了
/*
* Copyright 1999-2011 Alibaba Group.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.dubbo.rpc.service;
/**
* 通用服务接口
*
* @author william.liangf
* @export
*/
public interface GenericService {
/**
* 泛化调用
*
* @param method 方法名,如:findPerson,如果有重载方法,需带上参数列表,如:findPerson(java.lang.String)
* @param parameterTypes 参数类型
* @param args 参数列表
* @return 返回值
* @throws Throwable 方法抛出的异常
*/
Object $invoke(String method, String[] parameterTypes, Object[] args) throws GenericException;
}
package com.test.consumer;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.bytecode.Wrapper;
import com.alibaba.dubbo.rpc.service.GenericService;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.NotFoundException;
import javassist.bytecode.CodeAttribute;
import javassist.bytecode.LocalVariableAttribute;
import javassist.bytecode.MethodInfo;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.zookeeper.ClientCnxn;
import com.alibaba.dubbo.common.utils.StringUtils;
import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ReferenceConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ReflectionUtils;
import static java.lang.Class.forName;
/**
* Created by on 2017/10/23.
*/
public class DubboCallbackUtil {
private static Logger logger = LogManager.getLogger(DubboCallbackUtil.class);
// 当前应用的信息
private static ApplicationConfig application = new ApplicationConfig();
// 注册中心信息缓存
private static Map<String, RegistryConfig> registryConfigCache = new ConcurrentHashMap<>();
// 各个业务方的ReferenceConfig缓存
private static Map<String, ReferenceConfig> referenceCache = new ConcurrentHashMap<>();
static {
application.setName("consumer-test");
}
/**
* 获取注册中心信息
*
* @param address zk注册地址
* @param group dubbo服务所在的组
* @return
*/
private static RegistryConfig getRegistryConfig(String address, String group, String version) {
String key = address + "-" + group + "-" + version;
RegistryConfig registryConfig = registryConfigCache.get(key);
if (null == registryConfig) {
registryConfig = new RegistryConfig();
if (StringUtils.isNotEmpty(address)) {
registryConfig.setAddress(address);
}
if (StringUtils.isNotEmpty(version)) {
registryConfig.setVersion(version);
}
if (StringUtils.isNotEmpty(group)) {
registryConfig.setGroup(group);
}
registryConfigCache.put(key, registryConfig);
}
return registryConfig;
}
private static ReferenceConfig getReferenceConfig(String interfaceName, String address,
String group, String version) {
String referenceKey = interfaceName;
ReferenceConfig referenceConfig = referenceCache.get(referenceKey);
if (null == referenceConfig) {
try {
referenceConfig = new ReferenceConfig<>();
referenceConfig.setApplication(application);
referenceConfig.setRegistry(getRegistryConfig(address, group, version));
Class interfaceClass = forName(interfaceName);
referenceConfig.setInterface(interfaceClass);
if (StringUtils.isNotEmpty(version)) {
referenceConfig.setVersion(version);
}
referenceConfig.setGeneric(true);
//referenceConfig.setUrl("dubbo://10.1.50.167:20880/com.test.service.HelloService");
referenceCache.put(referenceKey, referenceConfig);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return referenceConfig;
}
public static Object invoke(String interfaceName, String methodName, List<Object> paramList, String address, String version) {
ReferenceConfig reference = getReferenceConfig(interfaceName, address, null, version);
if (null != reference) {
GenericService genericService = (GenericService) reference.get();
if (genericService == null) {
logger.debug("GenericService 不存在:{}", interfaceName);
return null;
}
Object[] paramObject = null;
if (!CollectionUtils.isEmpty(paramList)) {
paramObject = new Object[paramList.size()];
for (int i = 0; i < paramList.size(); i++) {
paramObject[i] = paramList.get(i);
}
}
Object resultParam = genericService.$invoke(methodName, getMethodParamType(interfaceName, methodName), paramObject);
return resultParam;
}
return null;
}
public static String[] getMethodParamType(String interfaceName, String methodName) {
try {
//创建类
Class<?> class1 = Class.forName(interfaceName);
//获取所有的公共的方法
Method[] methods = class1.getMethods();
for (Method method : methods) {
if (method.getName().equals(methodName)) {
Class[] paramClassList = method.getParameterTypes();
String[] paramTypeList = new String[paramClassList.length];
int i = 0;
for (Class className : paramClassList) {
paramTypeList[i] = className.getTypeName();
i++;
}
return paramTypeList;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
package com.test.consumer.controller;
import com.test.consumer.DubboCallbackUtil;
import com.test.consumer.dto.request.CallRequest;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.Map;
/**
* Created by on 2017/10/20.
*/
@RestController
@RequestMapping(value = "/consumer")
public class ConsumerController {
@RequestMapping(value = "/callJson")
@ResponseBody
public Object call(@RequestBody CallRequest request) {
return DubboCallbackUtil.invoke(request.getInterfaceName(), request.getMethod(), request.getParam(), request.getAddress(), request.getVersion());
}
}
具体源码可以参考