dubbo服务框架作为内部RPC(远程过程调用协议)时,无法承担对外输出的功能,这个时候我们就需要一个由外部到内部的转换框架使得外部请求能够来调用我们的dubbo服务,我们可以把它称为服务网关或者开放平台。
dubbo框架是支持泛化调用的,使用通用的GenericService接口invoke需要调用的方法。下面是具体代码:
package com.ebanma.cloud.datainsight.rpc;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
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 com.alibaba.dubbo.config.utils.ReferenceConfigCache;
import com.alibaba.dubbo.rpc.service.GenericService;
import com.ebanma.cloud.datainsight.dto.InParams;
import com.zebra.xconfig.client.XConfig;
/**
* @author liyi
* created on 2018/06/13
*/
@Service
public class DubboGeneralizationService{
private static final Logger logger = LoggerFactory.getLogger(DubboGeneralizationService.class);
private ApplicationConfig application;
private RegistryConfig registry;
private static DubboGeneralizationService instance = new DubboGeneralizationService();
//获取DubboGeneralizationService实例
public static DubboGeneralizationService getInstance() {
return instance;
}
//实例化该对象后立即初始化dubbo配置信息
private DubboGeneralizationService(){
//配置dubbo的application信息
ApplicationConfig applicationConfig = new ApplicationConfig();
applicationConfig.setName(XConfig.getValue("data-insight.app.name","data-insight"));
//配置dubbo的注册中心信息,我的信息都配置在xconfig里面,从里面拿数据,你们可以根据自己的配置修改就可以了
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setProtocol(XConfig.getValue("base-dubbo.registry.protocol","data-insight"));
registryConfig.setAddress(XConfig.getValue("base-dubbo.registry.address"));
registryConfig.setGroup(XConfig.getValue("base-dubbo.group"));
registryConfig.setClient(XConfig.getValue("base-dubbo.registry.client"));
registryConfig.setId("zookeeper_registry_inner");
this.application = applicationConfig;
this.registry = registryConfig;
}
/**
* @author liyi created on 2018/06/12
* @param interfaceClass 接口名
* @param methodName 方法名
* @param parameters 参数列表
* @return
*/
public Object genericInvoke(String interfaceName,String serviceVersion, String methodName, List<InParams> InParams){
ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>();
reference.setApplication(application);
reference.setRegistry(registry);
reference.setInterface(interfaceName);//声明接口名
reference.setGeneric(true);//声明为泛化接口
reference.setAsync(false);
if(StringUtils.isNotEmpty(serviceVersion)) {
reference.setVersion(serviceVersion);
}
/**
* @author liyi created on 2018/06/12
* ReferenceConfig实例很重,封装了与注册中心的连接以及与提供者的连接,
* 需要缓存,否则重复生成ReferenceConfig可能造成性能问题并且会有内存和连接泄漏。
* API方式编程时,容易忽略此问题。这里使用dubbo内置的简单缓存工具类进行缓存
*/
ReferenceConfigCache cache = ReferenceConfigCache.getCache();
GenericService genericService = cache.get(reference);
//设置参数和参数类型
String[] parameterTypes = new String[InParams.size()];
Object[] parameterValues = new Object[InParams.size()];
if(InParams != null && !InParams.isEmpty()) {
int index = 0;
for (InParams inParam : InParams) {
parameterTypes[index] = inParam.getParamType();
parameterValues[index] = inParam.getParamValue();
index++;
}
}
return genericService.$invoke(methodName, parameterTypes, parameterValues);
}
}
然后在实现类里面调用genericInvoke方法就可以了:
public JSONObject doInsight(String insigtConditionJSON) {
InsigtCondition ic = JSON.parseObject(insigtConditionJSON,InsigtCondition.class);
List<InParams> InParams = ic.getArgs();
DubboGeneralizationService dubboGeneralizationService = DubboGeneralizationService.getInstance();
Object obj;
try {
obj = dubboGeneralizationService.genericInvoke(ic.getInterfaceName(),ic.getVersion(), ic.getMethodName(), InParams);
return JSON.parseObject(obj.toString());
} catch (BizRuntimeException e) {
System.err.println(e.getMessage());
return JSON.parseObject(e.getMessage());
}
}
下面是我的两个dto类用来传参数:
package com.ebanma.cloud.datainsight.dto;
import java.util.List;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ApiModel
public class InsigtCondition{
private String oemCode;
@ApiModelProperty(value = "透视条目ID", required = true)
private Long itemId;
@ApiModelProperty(value = "API唯一标识,如:ebanma.cloud.avn.comm.getVehicleFlow", required = true)
private String uniqueName;
@ApiModelProperty(value = "API接口名,包名+类名,如:com.zxq.iov.cloud.sp.comm.api.IAvnApi", required = true)
private String interfaceName;
@ApiModelProperty(value = "方法名,如:getVehicleFlow", required = true)
private String methodName;
@ApiModelProperty(value = "API版本", required = true)
private String version;
@ApiModelProperty(value = "参数列表List")
private List<InParams> args;
public String getOemCode() {
return oemCode;
}
public void setOemCode(String oemCode) {
this.oemCode = oemCode;
}
public Long getItemId() {
return itemId;
}
public void setItemId(Long itemId) {
this.itemId = itemId;
}
public String getUniqueName() {
return uniqueName;
}
public void setUniqueName(String uniqueName) {
this.uniqueName = uniqueName;
}
public String getInterfaceName() {
return interfaceName;
}
public void setInterfaceName(String interfaceName) {
this.interfaceName = interfaceName;
}
public String getMethodName() {
return methodName;
}
public void setMethodName(String methodName) {
this.methodName = methodName;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public List<InParams> getArgs() {
return args;
}
public void setArgs(List<InParams> args) {
this.args = args;
}
}
InParams DTO:
package com.ebanma.cloud.datainsight.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ApiModel(description="参数列表")
public class InParams{
@ApiModelProperty(value = "参数名", required = true)
private String paramName;
@ApiModelProperty(value = "参数值", required = true)
private String paramValue;
@ApiModelProperty(value = "参数类型", required = true)
private String paramType;
public String getParamName() {
return paramName;
}
public void setParamName(String paramName) {
this.paramName = paramName;
}
public String getParamValue() {
return paramValue;
}
public void setParamValue(String paramValue) {
this.paramValue = paramValue;
}
public String getParamType() {
return paramType;
}
public void setParamType(String paramType) {
this.paramType = paramType;
}
}