• 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&timestamp=1489374649211

    动手开干,先建配置表。

     1 CREATE TABLE `pay_callback_config` (
     2   `id` bigint(20) NOT NULL AUTO_INCREMENT,
     3   `system_id` varchar(20) DEFAULT NULL COMMENT '业务系统标识',
     4   `registry_address` varchar(100) DEFAULT NULL COMMENT 'zk注册地址',
     5   `registry_group` varchar(50) DEFAULT NULL COMMENT 'zk注册组',
     6   `registry_version` varchar(20) DEFAULT NULL COMMENT '服务的版本号',
     7   `valid_flag` tinyint(1) DEFAULT '1' COMMENT '是否有效,1有效 0无效',
     8   `create_date` datetime DEFAULT NULL COMMENT '创建时间',
     9   PRIMARY KEY (`id`)
    10 ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='支付回调的配置表';

    对应的domain类:

     1 package xxx.domain;
     2 
     3 import java.io.Serializable;
     4 import java.util.Date;
     5 
     6 import xxx.PaymentConstants;
     7 
     8 import lombok.Data;
     9 
    10 /**
    11  * 支付回调的相关配置 对应表:pay_callback_config
    12  * 
    13  * @author yangzhilong
    14  *
    15  */
    16 @Data
    17 public class PayCallbackConfig implements Serializable{
    18     /**
    19      * 
    20      */
    21     private static final long serialVersionUID = 339298526553679045L;
    22     
    23     private Long id;
    24     /**
    25      * 业务系统标识 {@link PaymentConstants.BUSINESS_SYSTEM}
    26      */
    27     private String systemId;
    28     /**
    29      * zk注册地址
    30      */
    31     private String registryAddress;
    32     /**
    33      * zk注册组
    34      */
    35     private String registryGroup;
    36     /**
    37      * 服务的版本号
    38      */
    39     private String registryVersion;
    40     /**
    41      * 有效标识
    42      */
    43     private Boolean validFlag;
    44     /**
    45      * 创建时间
    46      */
    47     private Date createDate; 
    48 }

    Spring Boot的配置类:

     1 package xx.configuration;
     2 
     3 import java.util.List;
     4 
     5 import org.springframework.beans.factory.annotation.Autowired;
     6 import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
     7 import org.springframework.context.annotation.Bean;
     8 import org.springframework.context.annotation.Configuration;
     9 
    10 import xx.domain.PayCallbackConfig;
    11 import xx.mapper.PayCallbackConfigMapper;
    12 import xx.utils.PayCallbackUtils;
    13 import xx.utils.UselessBean;
    14 
    15 /**
    16  * 支付回调的初始化代码
    17  * 
    18  * @author yangzhilong
    19  *
    20  */
    21 @Configuration
    22 @ConditionalOnClass(PayCallbackConfigMapper.class)
    23 public class PayCallbackConfiguration {
    24     @Autowired
    25     private PayCallbackConfigMapper payCallbackConfigMapper;
    26 
    27     @Bean
    28     UselessBean uselessBean(){
    29         List<PayCallbackConfig> list = payCallbackConfigMapper.listAllVaild();
    30         if(null != list && !list.isEmpty()){
    31             for(PayCallbackConfig item : list){
    32                 PayCallbackUtils.init(item.getSystemId(), item.getRegistryAddress(), item.getRegistryGroup(), item.getRegistryVersion());
    33             }
    34         }
    35         UselessBean uselessBean = new UselessBean();
    36         return uselessBean;
    37     }
    38     
    39 }

    其中UselessBean就是一个空的类,定义这个就是利用spring对该类的初始来帮我初始化PayCallbackUtils类。

    package xx.utils;
    
    /**
     * 不会用的一个bean,只是用来在@Configuration帮忙初始化PayCallbackUtils的数据
     * 
     * @author yangzhilong
     *
     */
    public class UselessBean {
    
    }

    真正的核心类:PayCallbackUtils

      1 package xx.utils;
      2 
      3 import java.util.Map;
      4 import java.util.concurrent.ConcurrentHashMap;
      5 
      6 import com.alibaba.dubbo.config.ApplicationConfig;
      7 import com.alibaba.dubbo.config.ReferenceConfig;
      8 import com.alibaba.dubbo.config.RegistryConfig;
      9 import xx.api.payment.HuaPayCallbackService;
     10 import xx.dto.payment.HuapayCallbackDTO;
     11 
     12 public class PayCallbackUtils {
     13     // 当前应用的信息
     14     private static ApplicationConfig application = new ApplicationConfig();
     15     // 注册中心信息缓存
     16     private static Map<String, RegistryConfig> registryConfigCache = new ConcurrentHashMap<>();
     17     // 各个业务方的ReferenceConfig缓存
     18     private static Map<String, ReferenceConfig<HuaPayCallbackService>> referenceCache = new ConcurrentHashMap<>();
     19 
     20     static {
     21         application.setName("test");
     22     }
     23 
     24     /**
     25      * 获取注册中心信息
     26      * 
     27      * @param address
     28      *            zk注册地址
     29      * @param group
     30      *            dubbo服务所在的组
     31      * @return
     32      */
     33     private static RegistryConfig getRegistryConfig(String address, String group, String version) {
     34         String key = address + "-" + group + "-" + version;
     35         RegistryConfig registryConfig = registryConfigCache.get(key);
     36         if (null == registryConfig) {
     37             registryConfig = new RegistryConfig();
     38             registryConfig.setAddress(address);
     39             registryConfig.setGroup(group);
     40 
     41             registryConfigCache.put(key, registryConfig);
     42         }
     43         return registryConfig;
     44     }
     45 
     46     /**
     47      * 获取服务的代理对象
     48      * 
     49      * @param business
     50      * @param address
     51      * @param group
     52      * @return
     53      */
     54     private static ReferenceConfig<HuaPayCallbackService> getReferenceConfig(String business, String address,
     55             String group, String version) {
     56         String referenceKey = business;
     57         ReferenceConfig<HuaPayCallbackService> referenceConfig = referenceCache.get(referenceKey);
     58         if (null == referenceConfig) {
     59             referenceConfig = new ReferenceConfig<>();
     60             referenceConfig.setApplication(application);
     61             referenceConfig.setRegistry(getRegistryConfig(address, group, version));
     62             referenceConfig.setInterface(HuaPayCallbackService.class);
     63             referenceConfig.setVersion(version);
     64 
     65             referenceCache.put(referenceKey, referenceConfig);
     66         }
     67         return referenceConfig;
     68     }
     69 
     70     /**
     71      * 初始化数据
     72      * 
     73      * @param business
     74      * @param address
     75      * @param group
     76      * @param version
     77      */
     78     public static void init(String business, String address, String group, String version) {
     79         getReferenceConfig(business, address, group, version);
     80     }
     81 
     82     /**
     83      * 调用远程服务
     84      * 
     85      * @param business
     86      * @param address
     87      * @param group
     88      * @param version
     89      * @return
     90      */
     91     public static boolean invoke(String business, PayCallbackDTO dto) {
     92         ReferenceConfig<PayCallbackService> reference = getReferenceConfig(business, null, null, null);
     93         if (null != reference) {
     94             PayCallbackService callbackService = reference.get();
     95             if (null != callbackService) {
     96                 return callbackService.callback(dto);
     97             }
     98         }
     99         return false;
    100     }
    101 }

    其中HuaPayCallbackService是我定义的支付回调的接口定义,业务系统的回调服务必须实现我这个接口。

    示例代码如下:

     1 package xx.api.payment;
     2 
     3 import xx.dto.payment.PayCallbackDTO;
     4 
     5 /**
     6  * 支付异步回调统一的接口
     7  * 
     8  * @author yangzhilong
     9  *
    10  */
    11 public interface PayCallbackService {
    12     /**
    13      * 回调的接口
    14      * 
    15      * @param callbackDTO
    16      * @return 成功我就不会再回调,失败我会有重试的机制
    17      */
    18     boolean callback(HuapayCallbackDTO callbackDTO);
    19 }

    回调参数的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

  • 相关阅读:
    运维常见面试题
    python常见面试题
    常见面试题
    常用算法之‘归并排序’
    python库大全
    Springboot拦截器无效,解决办法
    Springboot 不返回页面,只反回文本
    SpringBoot 接收参数的几种常用方式(转载)
    mysql 查询每个分组的前几名
    Java中TimeZone类的常用方法
  • 原文地址:https://www.cnblogs.com/yangzhilong/p/6541959.html
Copyright © 2020-2023  润新知