优雅的实现接口统一调用!

优雅的实现接口统一调用!实现上面的接口 通过单例工厂的模式 doublecheck 的模式实现 并且加悲观锁 避免一个工作线程多次创建工厂实例 SpringContex getBean 获取 servcie 实例

大家好,欢迎来到IT知识分享网。

有些时候我们在进行接口调用的时候,比如说一个 push 推送接口,有可能会涉及到不同渠道的推送。

比如做结算后端服务的,会与金蝶财务系统进行交互,那么我结算后端会涉及到多个结算单类型,如果每一个种类型的结算单都去暴露一个 contoller 接口给前端提供,而且其实对接第三方的接口,有些接口是共通的。

前端涉及到的问题
  • 需要调用后端多个 controller,不同接口传不同的参数,如果遇到后端接口修改,会涉及到多个页面的修改,耦合度很高;
  • 需要对多个按钮设置权限配置。
后端涉及到的问题
  • 需要每个业务接口,都去写一个对接第三方接口的 push 推送方法,无形中增加很多重复的代码,耦合度也很高;
  • 如果涉及到第三方服务接口改造,后端接口也需要进行更改,会修改大量代码。

二、如何解决

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

大致的流程图就是这样的:

图片

三、具体实现

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

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

Feign 接口实现类:

@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;     } } 

枚举类定义:

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 推送方法。

图片

图片

这是我之前设计的关于接口统一调用的流程,当然其实还是包括对接第三方重复调用的问题、调用结果缓存、调用超时解决、失败降级的一些策略,作为抛砖引玉。

最后说一句(求关注!别白嫖!)

如果这篇文章对您有所帮助,或者有所启发的话,求一键三连:点赞、转发、在看。

关注公众号:woniuxgg,在公众号中回复:笔记  就可以获得蜗牛为你精心准备的java实战语雀笔记,回复面试、开发手册、有超赞的粉丝福利!

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/119548.html

(0)
上一篇 2025-11-04 18:00
下一篇 2025-11-04 18:15

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信