当前位置: 首页 > 科技观察

编写一个灵活的系统是多么容易啊!小白也能写Java高级业务!_0

时间:2023-03-18 01:31:20 科技观察

最近公司有需要。一个短消息服务已经收到了多个第三方供应商。部分业务需要查看第三方供应商的短信包剩余数量,选择剩余数量最大的渠道进行批量发送。有些服务指定了某个短信提供者,有些场景需要根据服务的价值动态决定使用哪个提供者。场景非常复杂,变化频繁。以前的代码真的很糟糕。选择剩余金额最多的频道一一检查,然后得出结果进行比较。至于指定供应商和根据业务价值判断和选择供应商,大量的ifelse被用来嵌套各种判断。每次看到这一堆代码,真的觉得太粗糙了。关键是有些供应商还在频繁更换,新的供应商需要替换旧的供应商,加入到这一大堆代码中。商业判断条件也会不时发生变化。几次问题后,领导看不下去了,让我想办法优化一下。我理顺了逻辑,整个关系图应该是这样的,其中我把逐条检查改成了并行检查,为了省去串行检查的IO耗时问题。有一些复杂的数据库查询逻辑,我去掉判断幂等的步骤。仅选择并绘制关键步骤。叫我重构这个,慢慢写,但关键是每一步和判断逻辑还是不时变化的。这要求我的代码非常灵活。所以在设计的时候,一直很苦恼怎么设计。组会的时候,我和其他组的一些朋友开发了一个开源框架——LiteFlow。研究了这个开源框架,发现LiteFlow是国产的规则引擎,可以编排任意复杂的流程,还支持热刷新。这基本上完全符合我的需求!文档很详细也很NICE,全部学完大概需要半天时间。发现新版LiteFlow的规则是用EL表达式写的。语法总数大约10个,非常容易理解。比如这种图:在LiteFlow中用rule表示是:THEN(a,WHEN(b,THEN(c,d)),e)其中THEN代表serial,WHEN代表并行执行。这种语法一目了然。再看这张图:在LiteFlow中,规则表示是:THEN(a,WHEN(b,SWITCH(c).to(d,e)),f)其中SWITCH是关键这个词的意思是专属网关。c组件是一个java类。根据执行结果,选择执行d还是e。所以像这样嵌套多层应该是没有问题的。在LiteFlow的文档中,作者给出了非常详细的例子,还有一些复杂的例子,比如:这个复杂的例子可以写成LiteFlow表达式:THEN(A,WHEN(THEN(B,C),THEN(D,E,F),THEN(SWITCH(G).to(THEN(H,I,WHEN(J,K)).id("t1"),THEN(L,M).id("t2")),N)),Z)其表达式还可以定义子变量,上面的表达式可以写成:item1=THEN(B,C);item2=THEN(D,E,F);item3_1=THEN(H,I,WHEN(J,K)).id("t1");item3_2=THEN(L,M).id("t2");item3=THEN(SWITCH(G).to(item3_1,item3_2),N);THEN(A,WHEN(item1,item2,item3),Z);其实对比图,仔细看,你会觉得这个表达还是很清晰的。应用于我的短信系统绰绰有余。我研究了一下,花了10分钟写出了我流程的表达规则:selectBestChannel=THEN(WHEN(channel1Query,channel2Query,channel3Query,channel4Query,channel5Query,channel6Query),channelSelector).id("branch1");selectBizChannel=THEN(biz1SW,SWITCH(CH,channel3if_2to).).to(channel5,channel6).id("s3")).id("s2")).id("branch2");THEN(packageData,SWITCH(if_1).to(channel1,channel2,selectBestChannel,selectBizChannel),batchSender);我使用的是文档中提到的分变量的方式来写,这种写法比较清晰。其实我总结了一个小技巧:不管多复杂,所有的图都可以拆分成部分整体,先定义局部小变量,然后在主流程中引入这些局部变量。无论如何,我花了大约10分钟来写这张照片。至于每一个小组件。我只是按照文档,把原来的大逻辑,一个一个的改成了小逻辑。封装在不同的组件中,给出相应的Id即可。最后,它可以由LiteflowExecutor触发。LiteflowResponseresponse=flowExecutor.execute2Resp("channelSenderChain",null,BatchMessageResultContext.class);BatchMessageResultContextcontext=response.getFirstContextBean();if(response.isSuccess()){log.info("执行成功,最终选择的通道为{}",context.getFinalResultChannel());}else{log.error("执行失败",response.getCause());}很简单!!!而且非常优雅!!!我改成上面的形式后,各个小逻辑块就完全解耦了。数据的连接完全由上下文连接。研究了LiteFlow的概念,发现这个概念非常好。直接拆分原代码,强耦合。现在如果业务发生变化,我只需要重写其中一个组件即可。并且组件可以重复使用。它们之间的顺序也可以随意切换。这一切,只需要更改规则文件即可。代码完全没有动过。我仔细阅读了文档。该框架还支持完全无缝的热刷新。虽然我的代码没有用到这个特性,但是看起来确实很强大。更改规则排列甚至不需要重新启动应用程序!!!但即使我被杀了,我也不会使用这个功能。领导让我换业务,我要多报工时。如果这个上线,我将无法报告更多的时间。..