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文件目录如下图 ...
随机推荐
- git clone报错:“server certificate verification failed. CAfile: /etc/ssl/certs/ca-certificates.crt CRLfile: none”
I can push by clone project using ssh, but it doesn't work when I clone project with https. it shows ...
- [转]缓慢但胜在稳健,HBase大势已成
CSDN Hbase : http://www.csdn.net/tag/hbase 在NoSQL数据库领域,统治产品无疑当属MongDB和DataStax Enterprise(一个领先的Apach ...
- CSS 强制换行和禁止换行强制换行 和禁止换行样式
强制换行 1.word-break: break-all; 只对英文起作用,以字母作为换行依据. 2.word-wrap: break-word; 只对英文起作用,以单词作为换行依据. ...
- Java工程Properties配置文件注释中文,会自动转换为其他编码方式问题解决 中文乱码
properties文件中想注释中文,但是写出来后却是 :# /4djf/234/4354/r23df/324d 这种效果 是因为字符编码默认没有设置造成的,以前总是安装插件解决此问题, 但是却牺牲 ...
- Java NIO ServerSocketChannel
A Java NIO ServerSocketChannel is a channel that can listen for incoming TCP connections, just like ...
- 样条之埃特金(Aitken)逐步插值函数
核心代码: ////////////////////////////////////////////////////////////////////// // 埃特金逐步插值 //////////// ...
- [leetcode]ZigZag Conversion @ Python
原题地址:https://oj.leetcode.com/problems/zigzag-conversion/ 题意: The string "PAYPALISHIRING" i ...
- Word Ladder leetcode java
题目: Given two words (start and end), and a dictionary, find the length of shortest transformation se ...
- 三种简洁的经典高效的DIV+CSS制作的Tab导航简析
在网页中应用选项卡可以使网页显得更紧凑,结合AJAX技术可以使页面在有限的空间内展现更多的内容.本文主要介绍几种简洁的选项卡效果的实现(不涉及滑动门和AJAX),附有实例,无图片,兼容性较好,方便大家 ...
- 矩阵中的旋转(Rotation)
参考的是<游戏和图形学的3D数学入门教程>,算是读书笔记吧. 目录 [隐藏] 1.2D中的旋转 2.3D中的旋转 2.1绕x轴旋转: 2.2绕Y轴旋转 2.3绕Z轴旋转 1.2D中的旋转 ...