从决定读ApacheOFBiz源码到现在不知不觉一年就过去了。这一年因为各种原因,导致源码读得断断续续。其实最大的问题还是因为无法深刻得理解里面的一些东西,导致热情骤减。直到最近,公司在开发的一个“应用快速开发平台”引发了我的一些思考,所以决定再把源码拿出来重新阅读。到最近对其架构设计近乎迷恋。
个人认为对于ApacheOFBiz的剖析可以分成三大块来进行:技术、业务、数据库设计。这三块个个都是非常顶尖的水准,每个方向深入进去都可以学到很多东西。之前只是对OFBiz各个部分的单独解析,现在是时候写一篇文章来串讲它的各个部分。当然,这篇主要还是涉及到OFBiz的技术这一块。
框架简介
这张图是OFBiz的整体框架图。从图中可以看到OFBiz的所有app都构建在其framework之上。而其framework的核心就是ServiceEngine(服务引擎)以及EntityEngine(实体引擎)。其实体引擎对于数据库的种类以及拓扑结构的支持都非常健全。它支持本地数据库与远端数据库并存并且支持多达8种主流数据库。
OFBiz技术串讲
下面以一个客户端请求的处理过程来看OFBiz各个组件是如何交互以及衔接的。
(5)OFBiz的viewhandler通过模板引擎绑定页面元素与数据后,渲染出最终的输出流,通过http响应给客户端浏览器。弊端:动态语言(弱类型语言)固有的类型安全性的缺失以及纯解释执行性能跟Java这种解释+编译型语言还是无法比拟。
优势:大量传统行业,不需要那么高的性能要求;即便需要也可以用提升硬件来改善;脚本语言在编程效率、逻辑简洁性都是Java冗长的代码所望其项背的;脚本语言更贴近人类语言的表达,更适合实现DSL,来表述业务逻辑(而且OFBiz的下一步目标也将增强对Groovy实现DSL的支持)。
页面渲染
Apache OFBiz使用XML+Widget的布局,来将页面切分成一个个Widget以增强各个widget的灵活性以及复用性。
这些widget可以互相嵌套形成一个decorator-widget产生模板,在widget可以直接编写html标签,或者引用各种服务端模板引擎支持的模板文件(比如freemaker)。
前端的内容通常是HTML+数据。widget并没有忽略数据这部分。只是一种布局技术,它最终会由webcontainer转化为html,只不过数据的处理(CRUD)通常位于服务器端。而这些动作都被抽象成为了widget中的“action”。一个screen通常包含各种其他组件widget的引用,这些组件widget可以是:form,screen,menu等。
权限检查
OFBiz中采用的是角色+安全组的授权模型。
从图中可以看出常用的几个权限有:_ADMIN(管理员权限),_VIEW(浏览权限,为最小权限),_CREATE(创建权限),_UPDATE(编辑权限),_DELETE(删除权限)。因此如果controller.xml中配置了授权检查时,将会进行上图的权限检查流程。一个请求在处理之前,会检查其是否需要先进行登录。如果登录验证通过,会获取该会员的security
group。而security group又是security permission的集合。进而可以判断用户是否有某个操作的权限。
请求事件
因为OFBiz使用了公共代理的servlet,因此对每个请求而言,其处理逻辑就没有独享的servlet了。这里OFBiz引入了Event的机制来处理每个请求需要执行的特定的操作逻辑。
每收到一个请求,如果有特殊的处理,就触发一个event。上图是event的触发机制。它的配置在controller.xml文件下的request-map配置项内。
服务引擎
OFBiz执行服务基于其自身实现的服务引擎框架。该服务引擎借鉴了《CoreJ2EE
Pattern》里的“BusinessDelegate”模式。
调用程序通过服务引擎框架调用服务后,服务引擎首先将调用服务的参数提取并构建服务调用的上下文。然后选择合适的dispatcher,它其实就是businessdelegate。由他选择合适的引擎来执行服务。OFBiz会先判断服务有没有“特殊性”,比如它是否是异步的?是否是递归执行的。如果是,那么会选择它内置的JobScheduler来执行。还有它是否是带SECA(ServiceEvent
Control
Action)的?如果是SECA,那么会先执行SECA然后选择已配置的特定引擎来执行真正的目标服务,而在这个过程中会有一个Map来充当执行的上下文,用于存储中间结果、错误信息以及最终结果。执行完成之后,上下文对象会在调用栈中层层回退,并将最终的执行结果返回给调用端。