Tomcat 架构原理解析到架构设计借鉴 (10)

陷入细节,不看全局:我还没弄清楚森林长啥样,就盯着叶子看 ,看不到全貌和整体设计思路。所以阅读源码学习的时候不要一开始就进入细节,而是宏观看待整体架构设计思想,模块之间的关系。

还没学会用就研究如何设计:首先基本上框架都运用了设计模式,我们最起码也要了解常用的设计模式,即使是“背”,也得了然于胸。在学习一门技术,我推荐先看官方文档,看看有哪些模块、整体设计思想。然后下载示例跑一遍,最后才是看源码。

看源码深究细节:到了看具体某个模块源码的时候也要下意识的不要去深入细节,重要的是学习设计思路,而不是具体一个方法实现逻辑。除非自己要基于源码做二次开发。

正确方式

定焦原则:抓主线(抓住一个核心流程去分析,不要漫无目的的到处阅读)。

宏观思维:从全局的视角去看待,上帝视角理出主要核心架构设计,先森林后树叶。切勿不要试图去搞明白每一行代码。

断点:合理运用调用栈(观察调用过程上下文)。

带着目标去学

比如某些知识点是面试的热点,那学习目标就是彻底理解和掌握它,当被问到相关问题时,你的回答能够使得面试官对你刮目相看,有时候往往凭着某一个亮点就能影响最后的录用结果。

又或者接到一个稍微复杂的需求,学习从优秀源码中借鉴设计思路与优化技巧。

最后就是动手实践,将所学运用在工作项目中。只有动手实践才会让我们对技术有最直观的感受。有时候我们听别人讲经验和理论,感觉似乎懂了,但是过一段时间便又忘记了。

实际场景运用

简单的分析了 Tomcat 整体架构设计,从 【连接器】 到 【容器】,并且分别细说了一些组件的设计思想以及设计模式。接下来就是如何学以致用,借鉴优雅的设计运用到实际工作开发中。学习,从模仿开始。

责任链模式

在工作中,有这么一个需求,用户可以输入一些信息并可以选择查验该企业的 【工商信息】、【司法信息】、【中登情况】等如下如所示的一个或者多个模块,而且模块之间还有一些公共的东西是要各个模块复用。

这里就像一个请求,会被多个模块去处理。所以每个查询模块我们可以抽象为 处理阀门,使用一个 List 将这些 阀门保存起来,这样新增模块我们只需要新增一个阀门即可,实现了开闭原则同时将一堆查验的代码解耦到不同的具体阀门中,使用抽象类提取 “不变的”功能。

具体示例代码如下所示:

首先抽象我们的处理阀门, NetCheckDTO是请求信息

/** * 责任链模式:处理每个模块阀门 */ public interface Valve { /** * 调用 * @param netCheckDTO */ void invoke(NetCheckDTO netCheckDTO); }

定义抽象基类,复用代码。

public abstract class AbstractCheckValve implements Valve { public final AnalysisReportLogDO getLatestHistoryData(NetCheckDTO netCheckDTO, NetCheckDataTypeEnum checkDataTypeEnum){ // 获取历史记录,省略代码逻辑 } // 获取查验数据源配置 public final String getModuleSource(String querySource, ModuleEnum moduleEnum){ // 省略代码逻辑 } }

定义具体每个模块处理的业务逻辑,比如 【百度负面新闻】对应的处理

@Slf4j @Service public class BaiduNegativeValve extends AbstractCheckValve { @Override public void invoke(NetCheckDTO netCheckDTO) { } }

最后就是管理用户选择要查验的模块,我们通过 List 保存。用于触发所需要的查验模块

@Slf4j @Service public class NetCheckService { // 注入所有的阀门 @Autowired private Map<String, Valve> valveMap; /** * 发送查验请求 * * @param netCheckDTO */ @Async("asyncExecutor") public void sendCheckRequest(NetCheckDTO netCheckDTO) { // 用于保存客户选择处理的模块阀门 List<Valve> valves = new ArrayList<>(); CheckModuleConfigDTO checkModuleConfig = netCheckDTO.getCheckModuleConfig(); // 将用户选择查验的模块添加到 阀门链条中 if (checkModuleConfig.getBaiduNegative()) { valves.add(valveMap.get("baiduNegativeValve")); } // 省略部分代码....... if (CollectionUtils.isEmpty(valves)) { log.info("网查查验模块为空,没有需要查验的任务"); return; } // 触发处理 valves.forEach(valve -> valve.invoke(netCheckDTO)); } } 模板方法模式

需求是这样的,可根据客户录入的财报 excel 数据或者企业名称执行财报分析。

对于非上市的则解析 excel -> 校验数据是否合法->执行计算。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpjzfz.html