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文件目录如下图 ...
随机推荐
- HTML5 本地文件操作之FileSystemAPI整理(二)
一.文件目录操作 1.DirectoryEntry对象 属性: 1.isFile: 操作对象的是否为文件,DirectoryEntry对象固定其值为false 2.isDirectory: 操作对象是 ...
- Java命令学习系列(四)——jstat
jstat(JVM Statistics Monitoring Tool)是用于监控虚拟机各种运行状态信息的命令行工具.他可以显示本地或远程虚拟机进程中的类装载.内存.垃圾收集.JIT编译等运行数据, ...
- [转]PHP用mysql数据库存储session
From : http://www.php100.com/html/webkaifa/PHP/PHPyingyong/2010/0226/4002.html 大部分使用php的人一旦应用到sessio ...
- Swift3.0:PhotoKit的使用
一.介绍 iOS8之前使用AssetsLibrary来获取相册资源,iOS新引入框架PhotoKit框架,也即Photos.framework 二.PhotoKit的基本构成包括如下几项: PHAss ...
- 生成学习算法(Generative Learning algorithms)
一.引言 前面我们谈论到的算法都是在给定\(x\)的情况下直接对\(p(y|x;\theta)\)进行建模.例如,逻辑回归利用\(h_\theta(x)=g(\theta^T x)\)对\(p(y|x ...
- 【VC++积累】之八、PreTranslageMessage;TranslageMessage;GetMessage和PeekMessage的区别
先来看windows消息机制: 首先系统(也就是windows)把来自硬件(鼠标,键盘等消息)和来自应用程序的消息 放到一个系统消息队列中去. 而应用程序需要有自己的消息队列,也就是线程消息队列,每一 ...
- Linux修改终端显示前缀及环境变量
Linux终端前面默认显示一长串,如: [work@aaa.baidu.com dir]$ 这是由PS1环境变量决定的: [work@aaa.baidu.com dir]$ echo $PS1 [\u ...
- 使用numba加速python程序
前面说过使用Cython来加速python程序的运行速度,但是相对来说程序改动较大,这次就说一种简单的方式来加速python计算速度的方法,就是使用numba库来进行,numba库可以使用JIT技术即 ...
- MFC中设备描述表dc的使用
以下代码我是在View类中实现的: /** 利用平台SDK实现画线功能 // 首先获得窗口的设备描述表 HDC hdc; hdc = ::GetDC( m_hWnd ); //调用的是平台SDK的成员 ...
- java 获取指定日前的前一天
/** * @Author: * @Description:更加输入日期,获取输入日期的前一天 * @Date: * @strData:参数格式:yyyy-MM-dd * @return:返回格式:y ...