dubbo实现动态调用
2024-10-19 02:27:52
在支付网关的业务中,在用户支付成功/失败后需要异步通知业务方,这个时候业务方是一个变数,支付网关可以定义一个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
最新文章
- 6_Win7下Chrome主页被流氓网站hao123.com劫持后的解决方法。
- Linux shell循环
- DOM 之 SAX操作
- Java类的初始化过程及清理
- 小技巧--让JS代码只执行一次
- Linux进程间通信IPC学习笔记之消息队列(SVR4)
- CSS3秘笈复习:第九章&;第十章
- LeetCode OJ 86. Partition List
- vuejs学习笔记(1)--属性,事件绑定,ajax
- (5)ES6解构赋值-函数篇
- 自动删除文件脚本(Linux shell脚本)
- mysql的order by注入
- Spring之BeanFactory和FactoryBean接口的区别
- Quartz+TopShelf实现定时任务
- Swoole PHP windows composer
- KVM虚拟化图
- 阿里大于发送短信(java)
- metrics 开发监控实现jdbc
- DPDK helloworld 源码阅读
- Vue-router浅识
热门文章
- java 常用集合list与Set、Map区别及适用场景总结
- QT中使用MinGW 编译的protobuf库--包含库的生成和使用
- [leetcode]Regular Expression Matching @ Python
- VS2010整合NUnit进行单元测试
- iOS开发-UIButton浅谈
- 【图片识别】Java中使用tess4J进行图片文字识别(支持中文)(转)
- Kafka:ZK+Kafka+Spark Streaming集群环境搭建(六)针对spark2.2.1以yarn方式启动spark-shell抛出异常:ERROR cluster.YarnSchedulerBackend$YarnSchedulerEndpoint: Sending RequestExecutors(0,0,Map(),Set()) to AM was unsuccessful
- [Spring Boot] Use Component Scan to scan for Bean
- redis-dev
- redis 中 set 和 hset 有什么不同,什么时候使用 hset 什么时候使用set?