图片 来源:juejin.cn/post/7276261829726191676

👉 欢迎加入小哈的星球 ,你将获得: 专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡 /  赠书福利

新项目:仿小红书(微服务架构)正在更新中… , 全栈前后端分离博客项目 2.0 版本完结啦, 演示链接http://116.62.199.48/">http://116.62.199.48/ 。全程手摸手,后端 + 前端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,直到项目上线。目前已更新了255小节,累计40w+字,讲解图:1716张,还在持续爆肝中.. 后续还会上新更多项目,目标是将Java领域典型的项目都整一波,如秒杀系统, 在线商城, IM即时通讯,Spring Cloud Alibaba 等等,戳我加入学习,已有1300+小伙伴加入(早鸟价超低)

图片

  • 一、耦合问题

  • 二、如何解决

  • 三、具体实现

  • 四、总结


一、耦合问题

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

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

  • 需要对多个按钮设置权限配置。

后端涉及到的问题
  • 需要每个业务接口,都去写一个对接第三方接口的 push 推送方法,无形中增加很多重复的代码,耦合度也很高;

  • 如果涉及到第三方服务接口改造,后端接口也需要进行更改,会修改大量代码。

二、如何解决

  1. 创建对接第三方服务的微服务,暂定为 tps 服务,该服务只作为一个后端微服务,与第三方服务进行对接,并且合理封装调用参数,将公共参数提出进行封装;

  2. 后端其余业务系统对接这个独立的微服务,比如订单、结算、供应商系统对接这个服务,由 tps 服务统一提供对接接口,其余服务实现这个 tps 提供的 feign 接口;

  3. 业务系统只需要关注 service 层业务的实现,无需处理对接的业务逻辑。

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

图片

图片

三、具体实现

Tps 服务

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

<span></span><code>//对接第三方服务接口<br>public&nbsp;interface&nbsp;IKingdeeManagementService&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;Boolean&nbsp;push(KingdeePushCO.Request&nbsp;request);<br>}<br></code>

Feign 接口实现类:

<span></span><code>@Slf4j<br>@Service<br>public&nbsp;class&nbsp;KingdeeManagementServiceImpl&nbsp;implements&nbsp;IKingdeeManagementService&nbsp;{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;@Autowired<br>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;ApplicationContext&nbsp;applicationContext;<br>&nbsp;&nbsp;&nbsp;&nbsp;@Autowired<br>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;KingdeeThirdSettingService&nbsp;kingdeeThirdSettingService;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;@Override<br>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;Boolean&nbsp;push(KingdeePushCO.Request&nbsp;request)&nbsp;{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;KingdeeBusinessPushServiceEnum&nbsp;kingdeePushServiceEnum&nbsp;=&nbsp;KingdeeBusinessPushServiceEnum.getKingdeePushServiceEnumByType(request.getBusinessType());<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IKingdeeBusinessPushService&nbsp;kingdeePushService&nbsp;=&nbsp;null;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kingdeePushService&nbsp;=&nbsp;(IKingdeeBusinessPushService)&nbsp;applicationContext.getBean(kingdeePushServiceEnum.getClazz());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;catch&nbsp;(BeansException&nbsp;e)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;log.error(<span>"当前类型暂未实现,请联系开发"</span>);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;new&nbsp;ServiceException(<span>"当前类型暂未实现,请联系开发"</span>);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;R&lt;Boolean&gt;&nbsp;result&nbsp;=&nbsp;null;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;=&nbsp;kingdeePushService.pushKingdee(request);<br><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>return</span>&nbsp;<span>true</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}<br></code>

枚举类定义:

<span></span><code>public&nbsp;enum&nbsp;KingdeeBusinessPushServiceEnum&nbsp;{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;Class&nbsp;clazz;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;Integer&nbsp;<span>type</span>;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;String&nbsp;interFaceName;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;KingdeeBusinessPushServiceEnum(Class&nbsp;clazz,&nbsp;Integer&nbsp;<span>type</span>,&nbsp;String&nbsp;interFaceName)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.clazz&nbsp;=&nbsp;clazz;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.type&nbsp;=&nbsp;<span>type</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.interFaceName&nbsp;=&nbsp;interFaceName;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;RECEIPT_VOUCHER(IJaKingdeeBillClient.class,&nbsp;KingdeeBusinessTypeConstant.RECEIPT_VOUCHER,&nbsp;KingdeeSettingEnum.INTERFACE_TYPE_JA_RECEIPT_VOUCHER.getCode()),&nbsp;;<br>}<br></code>

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

图片

图片

四、总结

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

👉 欢迎加入小哈的星球 ,你将获得: 专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡 /  赠书福利

新项目:仿小红书(微服务架构)正在更新中… , 全栈前后端分离博客项目 2.0 版本完结啦, 演示链接http://116.62.199.48/">http://116.62.199.48/ 。全程手摸手,后端 + 前端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,直到项目上线。目前已更新了255小节,累计40w+字,讲解图:1716张,还在持续爆肝中.. 后续还会上新更多项目,目标是将Java领域典型的项目都整一波,如秒杀系统, 在线商城, IM即时通讯,Spring Cloud Alibaba 等等,戳我加入学习,已有1300+小伙伴加入(早鸟价超低)

图片

<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com"><img data-fileid="100015743" data-imgfileid="100051300" data-ratio="0.08658008658008658" data-src="https://mmbiz.qpic.cn/mmbiz_gif/TNUwKhV0JpTGQqtlGfEHkjibtshlaDwVKzjqq2pnpmYC14bKxDtSuhpWZWfVcicj5PFsoSMzuzicKIWZbsBpGXiaicg/640?wx_fmt=gif&amp;wxfrom=5&amp;wx_lazy=1&amp;tp=webp" data-type="gif" data-w="462" data-width="100%" data-original-style="outline: 0px;background-size: 16px;border-radius: 8px;font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;word-spacing: 2px;display: block;visibility: visible !important;width: 577.977px !important;" data-index="12" src="https://mmbiz.qpic.cn/mmbiz_gif/TNUwKhV0JpTGQqtlGfEHkjibtshlaDwVKzjqq2pnpmYC14bKxDtSuhpWZWfVcicj5PFsoSMzuzicKIWZbsBpGXiaicg/640?wx_fmt=gif&amp;wxfrom=5&amp;wx_lazy=1&amp;tp=webp" _width="577.977px" data-order="0" alt="图片"></section><pre><pre><pre data-style="letter-spacing: 0.544px; font-size: 16px; color: rgb(63, 63, 63); word-spacing: 1px; line-height: inherit;"><section powered-by="xiumi.us" data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-original-bgcolor="rgb(255, 255, 255)" data-darkmode-color="rgb(230, 230, 230)" data-darkmode-original-color="rgb(0, 0, 0)" data-style="margin-right: 0.5em; margin-left: 0.5em; white-space: normal; font-family: -apple-system-font, system-ui, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif; color: rgb(0, 0, 0); letter-spacing: 0px; word-spacing: 2px;" data-mpa-template-id="1250" data-mpa-color="#ffffff" data-mpa-category="divider"><p data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-original-bgcolor="rgb(255, 255, 255)" data-darkmode-color="rgb(106, 104, 111)" data-darkmode-original-color="rgb(106, 104, 111)">1.&nbsp;<a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU4MDUyMDQyNQ==&amp;mid=2247522465&amp;idx=1&amp;sn=49da64cae0a62b0c2beac8e0ad2b420e&amp;chksm=fd574827ca20c1314c036377d7698e1fe12a7e716a15a0cfb56d5870f209c3dded22dd848d26&amp;scene=21#wechat_redirect" textvalue="我的私密学习小圈子~" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1">我的私密学习小圈子~</a></p><p data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-original-bgcolor="rgb(255, 255, 255)" data-darkmode-color="rgb(138, 138, 138)" data-darkmode-original-color="rgb(89, 89, 89)"><span>2.&nbsp;<a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU4MDUyMDQyNQ==&amp;mid=2247534922&amp;idx=1&amp;sn=6bfb7ca2b8997f1887ec2a7d1890622e&amp;chksm=fd5799ccca2010da51a080f85274b0a349716a002dcadf0da247df280a537732d8b95c0d6c0a&amp;scene=21#wechat_redirect" textvalue="分布式链路追踪:TraceIdFilter + MDC + Skywalking" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" data-linktype="2">分布式链路追踪:TraceIdFilter + MDC + Skywalking</a><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU4MDUyMDQyNQ==&amp;mid=2247530313&amp;idx=1&amp;sn=5adf4981de7f0abbcb1bde27ee74ae56&amp;chksm=fd57a7cfca202ed9351c8954bce05f159584f0219de7bd3ff12362e3c98b1cc752802bbe3db2&amp;scene=21#wechat_redirect" textvalue="堪称最优秀的Docker可视化管理工具——Portainer你真的会用吗?" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1"></a></span></p><p data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-original-bgcolor="rgb(255, 255, 255)" data-darkmode-color="rgb(138, 138, 138)" data-darkmode-original-color="rgb(89, 89, 89)"><span>3.&nbsp;<a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU4MDUyMDQyNQ==&amp;mid=2247534922&amp;idx=2&amp;sn=4ffb5b1be2a19ee74c8358e2f9e105e3&amp;chksm=fd5799ccca2010daa8fac1c60811af84ae8e2b6eca60ea2a49d68c154078e104f26df7e54924&amp;scene=21#wechat_redirect" textvalue="微服务架构中10个常用的设计模式" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" data-linktype="2">微服务架构中10个常用的设计模式</a><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU4MDUyMDQyNQ==&amp;mid=2247531213&amp;idx=2&amp;sn=f4d4ae2ffc511109f0917b8e15217e65&amp;chksm=fd57aa4bca20235d13f288853171b10e40ebd9ce272880c36de9a40a2d136d32a665ac4ca2a6&amp;scene=21#wechat_redirect" textvalue="常见踩坑点:双层 for 循环千万别这样写了!" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1"></a></span></p><p data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-original-bgcolor="rgb(255, 255, 255)" data-darkmode-color="rgb(106, 104, 111)" data-darkmode-original-color="rgb(106, 104, 111)">4.&nbsp;<a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU4MDUyMDQyNQ==&amp;mid=2247534774&amp;idx=2&amp;sn=09125d0e2d8f106e1cad7cfdbe3207a2&amp;chksm=fd579830ca20112641818283bdf9e4d3fc08078494d853e4b88531cf59dad83f1144f66003d6&amp;scene=21#wechat_redirect" textvalue="Hutool 中的这些工具类,太实用了!" linktype="text" imgurl="" imgdata="null" data-itemshowtype="11" tab="innerlink" data-linktype="2">Hutool 中的这些工具类,太实用了!</a><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU4MDUyMDQyNQ==&amp;mid=2247531127&amp;idx=1&amp;sn=82474072ee5c6ca729f17ec75ded9e72&amp;chksm=fd57aaf1ca2023e7c9960deabf609a3b75a2da35fa0717aea6ef958025948da270dc08930007&amp;scene=21#wechat_redirect" textvalue="SpringBoot:一个注解就能帮你下载任意对象" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1"></a></p></section><p data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-original-bgcolor="rgb(255, 255, 255)" data-darkmode-color="rgb(168, 168, 168)" data-darkmode-original-color="rgb(62, 62, 62)" data-style="margin-right: 0.5em; margin-left: 0.5em; white-space: normal; font-family: -apple-system-font, system-ui, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif; letter-spacing: 0px; word-spacing: 2px; color: rgb(62, 62, 62); text-align: center;"><img data-fileid="100015744" data-imgfileid="100051301" data-ratio="0.5555555555555556" data-s="300,640" data-type="gif" data-w="639" data-src="https://mmbiz.qpic.cn/sz_mmbiz_gif/knmrNHnmCLEVGGmicJODkfibhcqyUwmTSC8CUvAMG78wPemfibvQ502uFs9jlziaLP50YcTs4rL9hQuzX32PAUOPHA/640?wx_fmt=gif&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1&amp;tp=webp" data-original-style="outline: 0px;border-radius: 8px;background-position: center center;background-repeat: no-repeat;background-color: rgb(238, 237, 235);background-size: 22px;border-width: 1px;border-style: solid;border-color: rgb(238, 237, 235);visibility: visible !important;width: 601px !important;" data-index="13" src="https://mmbiz.qpic.cn/sz_mmbiz_gif/knmrNHnmCLEVGGmicJODkfibhcqyUwmTSC8CUvAMG78wPemfibvQ502uFs9jlziaLP50YcTs4rL9hQuzX32PAUOPHA/640?wx_fmt=gif&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1&amp;tp=webp" _width="601px" crossorigin="anonymous" alt="图片"></p><pre data-style="letter-spacing: 0.544px; text-size-adjust: auto; word-spacing: 2px; color: rgb(89, 89, 89);"></pre></pre></pre></pre>
<pre data-style="letter-spacing: 0.544px; text-size-adjust: auto; word-spacing: 2px; color: rgb(89, 89, 89);"><p data-style="margin-top: 5px; margin-bottom: 5px; white-space: normal; color: rgb(62, 62, 62); letter-spacing: 0.544px; font-family: &quot;Helvetica Neue&quot;, Helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif; font-size: 14px; line-height: normal;"><span>最近面试BAT,整理一份面试资料</span><span>《<strong>Java面试BATJ通关手册</strong>》</span><span>,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。</span></p><p data-style="margin-top: 15px; margin-bottom: 15px; letter-spacing: 0.544px; white-space: pre-line; line-height: 30px; color: rgb(74, 74, 74); font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;"><span>获取方式:点“</span><span>在看</span><span>”,关注公众号并回复&nbsp;</span><span>Java</span><span>&nbsp;领取,更多内容陆续奉上。</span></p></pre><pre><p data-tool="mdnice编辑器"><span>PS:因公众号平台更改了推送规则,如果不想错过内容,记得读完点一下</span><strong>“<span>在看</span>”</strong><span>,加个</span><strong>“<span>星标</span>”</strong><span>,这样每次新文章推送才会第一时间出现在你的订阅列表里。</span></p><p data-tool="mdnice编辑器"><span>点<strong>“在看”</strong>支持小哈呀,谢谢啦</span></p></pre>