dubbo实现动态调用
在支付网关的业务中,在用户支付成功/失败后需要异步通知业务方,这个时候业务方是一个变数,支付网关可以定义一个interface,各个业务方来实现这个接口。
支付网关配置一个回调配置表,表中包含:group、ZK的注册地址等dubbo调用必须要的参数值。
dubbo在ZK上的注册信息示例:
dubbo://192.168.18.234:20883/com.wy.payment.service.CutPaymentService?anyhost=true&application=installment&default.timeout=30000&dubbo=2.5.3&interface=com.wy.payment.service.CutPaymentService&methods=updateRepaymentPlan,updatePaymentOrderStatus,selectOrderByCondition,createRepaymentPlan,selectPayWaterByBid,cutPayment&pid=31913&revision=0.0.1-SNAPSHOT&side=provider×tamp=1489374649211
动手开干,先建配置表。
CREATE TABLE `pay_callback_config` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`system_id` varchar(20) DEFAULT NULL COMMENT '业务系统标识',
`registry_address` varchar(100) DEFAULT NULL COMMENT 'zk注册地址',
`registry_group` varchar(50) DEFAULT NULL COMMENT 'zk注册组',
`registry_version` varchar(20) DEFAULT NULL COMMENT '服务的版本号',
`valid_flag` tinyint(1) DEFAULT '' COMMENT '是否有效,1有效 0无效',
`create_date` datetime DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='支付回调的配置表';
对应的domain类:
package xxx.domain; import java.io.Serializable;
import java.util.Date; import xxx.PaymentConstants; import lombok.Data; /**
* 支付回调的相关配置 对应表:pay_callback_config
*
* @author yangzhilong
*
*/
@Data
public class PayCallbackConfig implements Serializable{
/**
*
*/
private static final long serialVersionUID = 339298526553679045L; private Long id;
/**
* 业务系统标识 {@link PaymentConstants.BUSINESS_SYSTEM}
*/
private String systemId;
/**
* zk注册地址
*/
private String registryAddress;
/**
* zk注册组
*/
private String registryGroup;
/**
* 服务的版本号
*/
private String registryVersion;
/**
* 有效标识
*/
private Boolean validFlag;
/**
* 创建时间
*/
private Date createDate;
}
Spring Boot的配置类:
package xx.configuration; import java.util.List; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import xx.domain.PayCallbackConfig;
import xx.mapper.PayCallbackConfigMapper;
import xx.utils.PayCallbackUtils;
import xx.utils.UselessBean; /**
* 支付回调的初始化代码
*
* @author yangzhilong
*
*/
@Configuration
@ConditionalOnClass(PayCallbackConfigMapper.class)
public class PayCallbackConfiguration {
@Autowired
private PayCallbackConfigMapper payCallbackConfigMapper; @Bean
UselessBean uselessBean(){
List<PayCallbackConfig> list = payCallbackConfigMapper.listAllVaild();
if(null != list && !list.isEmpty()){
for(PayCallbackConfig item : list){
PayCallbackUtils.init(item.getSystemId(), item.getRegistryAddress(), item.getRegistryGroup(), item.getRegistryVersion());
}
}
UselessBean uselessBean = new UselessBean();
return uselessBean;
} }
其中UselessBean就是一个空的类,定义这个就是利用spring对该类的初始来帮我初始化PayCallbackUtils类。
package xx.utils; /**
* 不会用的一个bean,只是用来在@Configuration帮忙初始化PayCallbackUtils的数据
*
* @author yangzhilong
*
*/
public class UselessBean { }
真正的核心类:PayCallbackUtils
package xx.utils; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ReferenceConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import xx.api.payment.HuaPayCallbackService;
import xx.dto.payment.HuapayCallbackDTO; public class PayCallbackUtils {
// 当前应用的信息
private static ApplicationConfig application = new ApplicationConfig();
// 注册中心信息缓存
private static Map<String, RegistryConfig> registryConfigCache = new ConcurrentHashMap<>();
// 各个业务方的ReferenceConfig缓存
private static Map<String, ReferenceConfig<HuaPayCallbackService>> referenceCache = new ConcurrentHashMap<>(); static {
application.setName("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();
registryConfig.setAddress(address);
registryConfig.setGroup(group); registryConfigCache.put(key, registryConfig);
}
return registryConfig;
} /**
* 获取服务的代理对象
*
* @param business
* @param address
* @param group
* @return
*/
private static ReferenceConfig<HuaPayCallbackService> getReferenceConfig(String business, String address,
String group, String version) {
String referenceKey = business;
ReferenceConfig<HuaPayCallbackService> referenceConfig = referenceCache.get(referenceKey);
if (null == referenceConfig) {
referenceConfig = new ReferenceConfig<>();
referenceConfig.setApplication(application);
referenceConfig.setRegistry(getRegistryConfig(address, group, version));
referenceConfig.setInterface(HuaPayCallbackService.class);
referenceConfig.setVersion(version); referenceCache.put(referenceKey, referenceConfig);
}
return referenceConfig;
} /**
* 初始化数据
*
* @param business
* @param address
* @param group
* @param version
*/
public static void init(String business, String address, String group, String version) {
getReferenceConfig(business, address, group, version);
} /**
* 调用远程服务
*
* @param business
* @param address
* @param group
* @param version
* @return
*/
public static boolean invoke(String business, PayCallbackDTO dto) {
ReferenceConfig<PayCallbackService> reference = getReferenceConfig(business, null, null, null);
if (null != reference) {
PayCallbackService callbackService = reference.get();
if (null != callbackService) {
return callbackService.callback(dto);
}
}
return false;
}
}
其中HuaPayCallbackService是我定义的支付回调的接口定义,业务系统的回调服务必须实现我这个接口。
示例代码如下:
package xx.api.payment; import xx.dto.payment.PayCallbackDTO; /**
* 支付异步回调统一的接口
*
* @author yangzhilong
*
*/
public interface PayCallbackService {
/**
* 回调的接口
*
* @param callbackDTO
* @return 成功我就不会再回调,失败我会有重试的机制
*/
boolean callback(HuapayCallbackDTO callbackDTO);
}
回调参数的DTO:
package xx.gateway.dto.payment; import java.io.Serializable; import lombok.Data;
import lombok.EqualsAndHashCode; @Data
@EqualsAndHashCode(callSuper = false)
public class PayCallbackDTO implements Serializable {
/**
*
*/
private static final long serialVersionUID = -3475086707314113975L;
/**
* 支付状态 {@link xx.PaymentConstants.PAY_STATUS}
*/
private String payStatus;
/**
* 支付失败的原因
*/
private String payErrorInfo;
/**
* 业务系统订单id
*/
private String businessOrderId;
/**
* 支付流水id
*/
private String payFlowId;
/**
* 支付渠道返回的code
*/
private String channelRetCode;
/**
* 金额,单位:元
*/
private String money;
}
本文参考DUBBO官方文档实现:http://dubbo.io/API+Config-zh.htm
dubbo实现动态调用的更多相关文章
- SpringBoot整合Dubbo,并实现dubbo实现动态调用
在一些业务场景中,CP定单提交过来,需要提交到不同的通道进行业务处理 本文通过Dubbo以定义一个interface,各个通道方来实现这个接口.通过group来区分不同的通道 有需要的同学可以下载 示 ...
- 使用接口的方式调用远程服务 ------ 利用动态调用服务,实现.net下类似Dubbo的玩法。
分布式微服务现在成为了很多公司架构首先项,据我了解,很多java公司架构都是 Maven+Dubbo+Zookeeper基础上扩展的. Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按 ...
- 动态调用WebService
WebService内容 using Microsoft.CSharp;using System;using System.CodeDom;using System.CodeDom.Compiler; ...
- c# 动态调用WCF方法笔记!
//动态调用wcf方法 string url = "http://localhost:54379/ServiceWCF.svc"; IDoubleService proxy = W ...
- C# 动态调用DLL库
最近经常用到C#动态调用类库,简单的做下记录方便以后查询. 使用下面的几行代码就可以简单实现DLL类库的调用了 using System.Reflection; // 引入该命名空间 // 获取roc ...
- Atitit 动态调用webservice与客户端代理方式调用
Atitit 动态调用webservice与客户端代理方式调用 方式1: 使用call.invoke 直接调用WSDL,缺点:麻烦,不推荐--特别是JAVA调用.NET的WS时,会有不少的问题需要解 ...
- C#动态调用WCF接口,两种方式任你选。
写在前面 接触WCF还是它在最初诞生之处,一个分布式应用的巨作. 从开始接触到现在断断续续,真正使用的项目少之又少,更谈不上深入WCF内部实现机制和原理去研究,最近自己做一个项目时用到了WCF. 从这 ...
- 11月10日上午ajax基础知识、用ajax做登录页面、用ajax验证用户名是否可用、ajax动态调用数据库
1.ajax的基础知识 ajax是结合了jquery.php等几种技术延伸出来的综合运用的技术,不是新的内容.ajax也是写在<script>标签里面的. 如果使用ajax一定是要有1个处 ...
- C# 调用WebService的3种方式 :直接调用、根据wsdl生成webservice的.cs文件及生成dll调用、动态调用
1.直接调用 已知webservice路径,则可以直接 添加服务引用--高级--添加web引用 直接输入webservice URL.这个比较常见也很简单 即有完整的webservice文件目录如下图 ...
随机推荐
- HTML 5 <script> async 属性简单设置代码异步执行
HTML5中 script标签支持脚本的异步执行async.脚本将会异步运行: <script type="text/javascript" src="demo_a ...
- Holt Winter 指数平滑模型
1 指数平滑法 移动平均模型在解决时间序列问题上简单有效,但它们的计算比较难,因为不能通过之前的计算结果推算出加权移动平均值.此外,移动平均法不能很好的处理数据集边缘的数据变化,也不能应用于现有数据集 ...
- 【转】搜狗开源内部项目管理平台Cynthia意欲何为
FROM : http://blog.csdn.net/dj0379/article/details/38356825 目前,在项目管理与缺陷管理系统上,中国的中小开发团队基本都在使用国外产品,在理念 ...
- HDOJ 4869 Turn the pokers
最后的结果中正面向上的奇偶性是一定的,计算出正面向上的范围low,up 结果即为 C(m.low)+ C(m.low+2) +.... + C(m,up) ,用逆元取模 Turn the pokers ...
- 样条之拉格朗日Lagrange(一元全区间)插值函数
这是使用拉格朗日插值函数生成的样条曲线.在数值分析中,拉格朗日插值法是以法国十八世纪数学家约瑟夫·拉格朗日命名的一种多项式插值方法.许多实际问题中都用函数来表示某种内在联系或规律,而不少函数都只能通过 ...
- go语言之进阶篇方法的继承
1.方法的继承 示例: package main import "fmt" type Person struct { name string //名字 sex byte //性别, ...
- log4net修改数据库连接字符串和写自定义信息
最近项目需要用log4net来写日志,因为整个平台式在sharepoint上,我们需要记录具体是哪个子站点发生的日志,因此需要再原来的log表里面添加一个自定义信息列.由于平台的安全性要求,我们需要对 ...
- 如何同步两台Linux机器的时间?
除了用NTP服务器之外,下面的命令可以做到让几台机器的时间都跟一台机器同步. date --set="$(ssh root@10.245.110.101 date)" 参考资料 = ...
- Hadoop vs Spark性能对比
http://www.cnblogs.com/jerrylead/archive/2012/08/13/2636149.html Hadoop vs Spark性能对比 基于Spark-0.4和Had ...
- 主机无法访问虚拟机的apache解决办法
1.前言 今天学习搭建wordpress,apache服务器安装在虚拟机的Centos上.配置好以后,发现在虚拟机上可以访问,但在windows主机上不能访问.于是百度.google一下,终于解决问题 ...