如何优雅的实现接口统一调用

耦合问题

有些时候我们在进行接口调用的时候,比如说一个push推送接口,有可能会涉及到不同渠道的推送,以我目前业务场景为例,我做结算后端服务的,会与金蝶财务系统进行交互,那么我结算后端会涉及到多个结算单类型,如果每一个种类型的结算单都去暴露一个contoller接口给前端提供,而且其实对接第三方的接口,有些接口是共通的;

前端涉及到的问题
  • 需要调用后端多个controller,不同接口不同的传参数,如果遇到后端接口修改,会涉及到多个页面的修改,耦合度很高;
  • 需要对多个按钮设置权限配置;

后端涉及到的问题

  • 需要每个业务接口,都去写一个对接第三方接口的push推送方法,无形中增加很多重复的代码,耦合度也很高;
  • 如果涉及到第三方服务接口改造,后端接口也需要进行更改,会修改大量代码;

如何解决

  1. 创建对接第三方服务的微服务,站定为tps服务,该服务只作为一个后端微服务,与第三方服务进行对接,并且合理封装调用参数,将公共参数提出进行封装;
  2. 后端其余业务系统对接这个独立的微服务,比如订单、结算、供应商系统对接这个服务,由tps服务统一提供对接接口,其余服务实现这个tps提供的feign接口;
  3. 业务系统只需要关注service层业务的实现,无需处理对接的业务逻辑;

大致的流程图就是这样的

具体实现

Tps服务

Tps服务暴露feign接口,前端统一通过Tps提供的接口进行调用

java 复制代码
//对接第三方服务接口
public interface IKingdeeManagementService {
    Boolean push(KingdeePushCO.Request request);
}

Feign接口实现类

java 复制代码
@Slf4j
@Service
public class KingdeeManagementServiceImpl implements IKingdeeManagementService {

    @Autowired
    private ApplicationContext applicationContext;
    @Autowired
    private KingdeeThirdSettingService kingdeeThirdSettingService;

    @Override
    public Boolean push(KingdeePushCO.Request request) {

        KingdeeBusinessPushServiceEnum kingdeePushServiceEnum = KingdeeBusinessPushServiceEnum.getKingdeePushServiceEnumByType(request.getBusinessType());

        IKingdeeBusinessPushService kingdeePushService = null;
        try {
            kingdeePushService = (IKingdeeBusinessPushService) applicationContext.getBean(kingdeePushServiceEnum.getClazz());
        } catch (BeansException e) {
            log.error("当前类型暂未实现,请联系开发");
            throw new ServiceException("当前类型暂未实现,请联系开发");
        }
            R<Boolean> result = null;
            result = kingdeePushService.pushKingdee(request);


        return true;
//    }
    }
}

枚举类定义

java 复制代码
public enum KingdeeBusinessPushServiceEnum {

private Class clazz;

private Integer type;

private String interFaceName;

KingdeeBusinessPushServiceEnum(Class clazz, Integer type, String interFaceName) {
    this.clazz = clazz;
    this.type = type;
    this.interFaceName =interFaceName;
}
RECEIPT_VOUCHER(IJaKingdeeBillClient.class,KingdeeBusinessTypeConstant.RECEIPT_VOUCHER, KingdeeSettingEnum.INTERFACE_TYPE_JA_RECEIPT_VOUCHER.getCode()),
;
}

分别有clazz、type、interFaceName属性,

  • clazz定义为feign接口,业务系统提供的服务接口;
  • type前端需要传的参数,不同的Integer值代表,不同的feign接口映射;
  • interFaceName第三方接口枚举,表示需要具体调哪个第三方接口;

业务系统

拿bms服务举例说明: 继承Tps服务的feign接口,重写push方法;

Feign接口实现,通过factory工厂类初始化,不同的service实现类;

JaKingdeeFactoryUtil 工厂工具类,获取工厂实例,这里其实也可以使用枚举映射,避免以后接口太多,需要写很多case when;

JaKingdeeServiceFactory是个接口,提供方法;

实现上面的接口,通过单例工厂的模式double check的模式实现,并且加悲观锁,避免一个工作线程多次创建工厂实例,SpringContextUtils./getBean/获取servcie实例,业务层只需要实现service接口,实现不同业务逻辑的push推送方法;

总结

这是我之前设计的关于接口统一调用的流程,当然其实还是包括对接第三方重复调用的问题、调用结果缓存、调用超时解决、失败降级的一些策略,如果还有更好的接口统一调用方式欢迎大家评论区留言讨论;

相关推荐
isolusion7 分钟前
Springboot的创建方式
java·spring boot·后端
zjw_rp36 分钟前
Spring-AOP
java·后端·spring·spring-aop
木子Linux39 分钟前
【Linux打怪升级记 | 问题01】安装Linux系统忘记设置时区怎么办?3个方法教你回到东八区
linux·运维·服务器·centos·云计算
Oneforlove_twoforjob1 小时前
【Java基础面试题033】Java泛型的作用是什么?
java·开发语言
不惑_1 小时前
小白入门 · 腾讯云轻量服务器部署 Hadoop 3.3.6
服务器·hadoop·腾讯云
TodoCoder1 小时前
【编程思想】CopyOnWrite是如何解决高并发场景中的读写瓶颈?
java·后端·面试
向宇it1 小时前
【从零开始入门unity游戏开发之——C#篇24】C#面向对象继承——万物之父(object)、装箱和拆箱、sealed 密封类
java·开发语言·unity·c#·游戏引擎
小蜗牛慢慢爬行1 小时前
Hibernate、JPA、Spring DATA JPA、Hibernate 代理和架构
java·架构·hibernate
阿甘知识库1 小时前
宝塔面板跨服务器数据同步教程:双机备份零停机
android·运维·服务器·备份·同步·宝塔面板·建站
星河梦瑾2 小时前
SpringBoot相关漏洞学习资料
java·经验分享·spring boot·安全