1.1. 该方案的优势
在支持互联网应用中,BS和三层CS结构到底谁更合适?是一直以来争论不休的问题。笔者认为这个问题应该根据不用的应用情况而定,对于E商这种连锁行业的业务系统,笔者认为三层CS结构会更加合适。
| BS结构 | CS结构 | 三层CS结构 |
跨地域、跨网络 | 可以 | 不可以,只可以用于局域网,跨网络应用时需要额外的投入,且应用效果不理想 | 可以 |
操作性 | 不好,网页的操作方式对于大数量的操作效果不理想 | 好 | 好,在客户端方面与CS结构的客户端操作效果完全一致 |
服务器的压力 | 非常大,所有的计算都在服务器上,所以服务器压力非常大 | 小,客户端分担了部分计算压力 | 小,与CS结构完全一致 |
网络传输 | 速度慢,因为html的页面有大量的冗余信息,必然会导致网络流量大的问题 | 快,因为只需要传输数据 | 快,因为只需要传输数据 |
本方案另外一个显著的特点是:该方案采用了三层CS结构,且在服务器端采用了Java服务器,客户端采用了.net的开发技术,可以说是各取其所长。Java技术长于服务器,服务器的稳定性业界公认,常用于大型的系统,但java技术在客户端的开发则劣势明显。微软的.net开发框架则恰恰相反,微软的中间件服务器,也就是IIS,其稳定性和安全性一直为业界所诟病,一般只用于中小型企业的业务系统,对于大型高并发的系统应用,则有点勉为其难。
所以,本方案在服务器但仍采用java服务器,可以与现有DRP采用同样的服务器平台,服务器的统一可以保证数据平台的扩展性和数据统一性。对于客户端我们采用了.net的开发框架,保证了客户端良好的操作性,保证了用户的良好使用感受和高效的工作效率。对于服务器和客户端的通信,则由我们自行开发了通信接口,既保证了通信效率,也增强了报密性和安全性。
| Java技术 | .net | 本方案 |
服务器 | 强,稳定性和安全性都经过了实践的检验 | 差,微软的中间件服务器的稳定性一致为业界诟病 | 服务器采用java技术 |
客户端 | 差,客户端开发一直是java的弱项 | 强,微软一直擅长于用户界面的开发 | 客户端采用微软.net技术 |
1.2. 系统整体结构
系统为基于业界主流的三层架构技术:
l 数据库:支持SQL Server、Oracle等多种数据库。
l 应用服务器:可采用WebLogic、Tomcat等J2EE中间件,提供业务逻辑实现,数据存取,以及与外系统交互的各种接口。
l 客户端:采用基于.net 2.0的winform客户端作为业务操作终端。
系统结构框图:
1.3. 系统中的对象
系统中数据存取涉及四种不同类型的对象:
PO: 全称为presentation object,即表现层对象。通常在客户端使用,用于界面控件的数据绑定。一个PO对象可能包含一个或多个VO对象,或者是VO对象的线性集合。PO对象出于展现数据的需要,往往还要添加各种冗余字段和计算字段。另外,PO对象通常使用事件与界面控件进行交互,以通知界面控件刷新。在.net平台上,一般使用DataSet、DataTable和DataRow对象作为PO对象(请参考.net framework类库的System.Data命名空间)。
VO: 全称为value object,即值对象,是仅仅包含数据的一种对象。通常用于业务层之间的数据传递,从数据库读取数据,以及将自身数据写入数据库等。与数据库表的设计有密切关系。VO又常常被称为“实体类”或“数据实体”。
DO: 全称为data access object,即数据访问对象,此对象用于访问数据库。通常和VO结合使用,DO中包含了各种数据库的操作方法。通过它的方法,结合VO的数据对数据库进行相关的操作.。
BO:全称为business object,即业务逻辑处理对象。此对象用于处理具体的业务逻辑。通常,BO有一定的继承层次,以提取一些公用的操作(如记录日志等)。BO通常实现唯一接口,接收客户端请求,调用DO更新数据,并以VO或VO集合的形式返回处理结果。
这三者分工不同,在简单的小系统里面,可能有时会重合。但在大一点的系统里面,三者分工明确系统可拓展性,可维护性的好处,远远超出了前期编写代码时所付的代价。
1.4. 数据存取技术
系统采用成熟的大型关系型数据库管理系统作为数据存储后端,同时使用基于面向对象思想的编程技术。
由于关系型模型和面向对象模型之间存在结构上的错配,因此需要采用ORM技术对数据在数据库和中间层之间进行转换。iBatis是目前业界流行的一种ORM解决方案,其简单、灵活、可靠的特点使得其得到了广泛应用。
1.4.1. ORM
对象关系映射(Object Relational Mapping,简称ORM)是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。 简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将java/.net程序中的对象自动持久化到关系数据库中。
1.4.2. iBatis
iBATIS是一个混合式的ORM解决方案(hybrid solution),借鉴了多种操作关系数据库的方法的理念。
iBATIS的优点:
l 简单,学习成本低,容易掌握
l 生产效率高,易于自动化
l 性能
l 提供对数据库连接池、数据缓存、事务的统一管理
l 分工明确,程序员和DBA可以各司其职,分工合作
l 官方同时提供对java和.net平台的支持
1.4.3. 代码生成
代码生成的概念:
通过指定若干输入参数,使用特定的软件工具,使得计算机能自动地、批量地生成程序源代码的过程。常用的代码生成工具有“MyGeneration”、“CodeSmith”等。通常代码生成工具都是基于模板和模板引擎技术,执行时,使用动态脚本语言根据输入参数的不同,自动替换模板中的某些部分,从而生成大量逻辑相似的源代码。使用jsp或asp.net脚本技术,也可以很方便的制作适用于特定目的的小型代码生成器。
为什么要使用代码生成技术:
l 代码生成非常高效。因为一旦制作好了合适的模板,设定了输入参数,计算机可以在数秒内生成数万至数十万行的源代码,效率是人工编码的成千上万倍。
l 有利于代码的标准化。通过合理规划和制作模板,使得生成的源代码的逻辑非常相似,代码的结构、接口、处理过程容易标准化、通用化。通过修改模板,便可以批量地升级所有的生成代码。
l 有利于提高代码质量。一方面,代码的标准化使得性能调优变得更加容易。另一方面,减少了由于人工编写而带来的各种失误。
l 提高代码适应能力。比如数据库字段的增减在项目开发初期可能是比较频繁的,如果由人工维护相应的数据存取代码,则非常容易错漏字段。通过使用代码生成工具,只要轻轻点击“重新生成”,便可使得代码同步于外界环境的变化,减少了错误发生的可能。
代码生成的适用场合:
由于不存在“万能”的代码模板,代码生成一般适用于处理过程和处理逻辑比较标准的场合。通过使用基于iBatis的ORM框架,数据存取层的逻辑和编写过程变得容易标准化,从而使数据存取层的代码生成成为可能。
本系统中,数据存取层的VO、DO及相关的iBatis XML映射文件将应用代码生成技术。
生成单表VO、DO:
这是最简单的情况,代码生成器将为指定的表生成对应的VO对象和DO对象。VO对象包含了数据库表的所有字段,并且添加了必要的辅助字段和辅助方法。由于VO对象不包含业务逻辑处理,因此其所有数据域(Field)都是public的,目的是使代码更精炼。DO对象提供了对关联VO的四种基本操作:Select、Insert、Update、Delete。通过函数重载,为Select方法添加条件、分页和排序的选项。
生成多表连接的VO、DO:
需要为此VO指定基本表。DO为基本表生成与单表VO类似的四种基本操作。对于关联的其他表,需要指定连接的类型(join类型)和外键,代码生成器会生成含join关键字的联合查询SQL及对应的SelectWith方法(With表示该查询涉及多个表)。通过函数重载,为SelectWith添加条件、分页和排序的选项。
条件检索和条件删除:
数据库设计中,常常有物理主键和逻辑主键不完全一样的情况。比如物理主键可能采用GUID,而逻辑主键可能是单据号,或者若干字段的组合。代码生成器允许我们通过指定逻辑主键字段,生成相应的SelectBy、DeleteBy方法族。在多表连接时,还将生成SelectWithBy方法族用于联合检索。
条件更新:
在需要进行批量更新,或者需要使用逻辑主键进行更新的场合,可以为代码生成器指定条件字段(通常对应于外键字段或逻辑主键字段),使其自动生成UpdateBy方法族。
部分检索:
通常,在制作查询界面时,并不需要罗列所有的字段,只要显示若干主要的字段即可。或者,一些说明型或者二进制型的复杂字段,不需要在查询结果中显示(通常是在单据界面显示这些复杂字段)。这个时候,为了提高响应速度和减小网络流量,可以指定代码生成器生成只检索若干指定字段的查询。代码生成器将创建相应的SQL语句,使得数据库只返回选定的字段,从而优化了性能。
部分更新:
在审核型的业务操作中,通常只对有限的几个字段进行更新:主键、状态字段和时间戳。这时我们可以指定需要更新哪些字段,则代码生成器将创建相应的Update语句,使得只有指定的字段获得更新,从而优化了性能。
数据分页:
在三层或多层架构的软件系统中,由于受客户端到服务器的带宽限制,数据分页是很常见的一种操作,其目的是一次只返回“一页”数据。通过在SQL语句中添加ROWNUM关键字,可以很容易地使分页过程自动化。
直接执行动态SQL:
在实际的业务处理中,总是存在有难以标准化处理的情况,因此在系统中添加了对直接执行动态SQL的支持。该动态SQL可以是无返回值的(如Insert、Update或Delete操作,以及存储过程调用),也可以是有返回值的(如Select操作)。返回值将以Hashtable(哈希表)结构返回。
1.5. 中间层
中间层即应用服务层,部署于应用服务器上。中间层的主要作用是:
l 响应客户端请求,处理业务逻辑,返回响应数据
l 执行数据库存取操作
l 通过部署Web Service,提供外系统接口
基于灵活性和可扩展性考虑,中间层采用MVC和Front Controller设计模式。
1.5.1. MVC模式:
MVC(Model-View-Controller)模式是目前大型多层应用系统中主流的架构模式。MVC模式基于用户输入将域的建模、显示和操作分为三个独立的类:
l 模型。模型用于管理应用程序域的行为和数据,并响应为获取其状态信息(通常来自视图)而发出的请求,还会响应更改状态的指令(通常来自控制器)。在系统中,模型对应PO和VO类对象。模型部分需要在客户端和中间层之间传递数据。
l 视图。视图用于管理信息的显示。在系统中,视图部分部署在客户端,对应于.net WinForm 客户端的各种窗体、控件。
l 控制器。控制器用于解释用户的鼠标和键盘输入,以通知模型和/或视图进行相应的更改。控制器部署在中间层,包括一个前端控制器对象和一系列处理具体业务逻辑的命令对象。
使用MVC模式的优点:
l 同时支持多种客户端。客户端与中间层间使用XML进行通讯,中间层无需关心客户端是winform、webform还是PDA。
l 适应更改。用户界面要求的更改往往比业务规则快。将客户端的逻辑与中间层相分离,使得界面更改不会影响到中间层和数据库。
详细技术资料,请参考“附件3:MVC模式”
1.5.2. Front Controller(前端控制器)模式:
系统选择Front Controller模式作为系统MVC架构下的控制器结构。
Front Controller 模式具有下列优点:
l 集中化控制。Front Controller 用于协调向 Web 应用程序发出的所有请求,易于实施全应用程序范围的策略,如安全性和使用情况跟踪。
l 线程安全。控制器为每个请求创建新的命令对象(业务逻辑处理对象),从而避免了线程安全问题。
l 简化配置。只需要在 Web 服务器中配置一个前端控制器便可执行各种调度。
详细技术资料,请参考“附件4:Front Controller模式”
1.6. 通讯技术
1.6.1. 系统中各个模块的通讯架构:
1.6.2. Web Service:
Web Service是基于HTTP通讯协议和XML技术的一套分布式应用程序通讯框架。Web Service包含的主要技术有:
l XML和XSD: 可扩展的标记语言XML 是Web Service平台中表示数据的基本格式。除了易于建立和易于分析外,XML主要的优点在于它既与平台无关,又与厂商无关。XML是由万维网协会 (W3C)创建,W3C制定的XML SchemaXSD 定义了一套标准的数据类型,并给出了一种语言来扩展这套数据类型。Web Service平台是用XSD来作为数据类型系统的。当你用某种语言如VB.NET或C# 来构造一个Web Service时,为了符合Web Service标准,所有你使用的数据类型都必须被转换为XSD类型。如想让它使用在不同平台和不同软件的不同组织间传递,还需要用某种东西将它包装起 来。这种东西就是一种协议,如 SOAP。
l SOAP:SOAP即简单对象访问协议(Simple Object Access Protocol),它是用于交换XML编码信息的轻量级协议。它有三个主要方面:XML-envelope为描述信息内容和如何处理内容定义了框架,将 程序对象编码成为XML对象的规则,执行远程过程调用(RPC)的约定。
l Web Service描述语言-WSDL。WSDL 就是用机器能阅读的方式提供的一个正式描述文档而基于XML的语言,用于描述Web Service及其函数、参数和返回值。因为是基于XML的,所以WSDL既是机器可阅读的,又是人可阅读的。
l UDDI:UDDI 的目的是为电子商务建立标准;UDDI是一套基于Web的、分布式的、为Web Service提供的、信息注册中心的实现标准规范,同时也包含一组使企业能将自身提供的Web Service注册,以使别的企业能够发现的访问协议的实现标准。
l 远程过程调用RPC与消息传递
1.6.3. 对象序列化技术:
在面向对象系统中,数据的操作都是通过对象完成的。在分布式应用中,需要通过对象序列化技术,将对象转换为可以通过网络传递的字节流,传送到远端。远端使用反序列化技术,将网络字节流还原为对象,完成数据传递。
通常的对象序列化技术有两种:
1. 二进制序列化:以二进制格式记录对象的所有数据域的值。序列化的结果为字节数组。
2. XML序列化:以XML文本的形式记录对象的所有数据域的文本值。非字符串类型的数据域将需要转换为对应的文本。序列化的结果为字符串,在网络上传送的实际是该字符串对应某个特定字符集(如GB2312)的字节流。
性能上二进制序列化要高一些,但是受特定技术平台的限制。XML序列化由于存在XML和文本解析的过程,性能要低一些,但是可以跨技术平台使用,而且可读性较好。
考虑到本系统需要跨越java和.net平台,以及将来可能需要部署各种对外接口,基于标准化和统一化考虑,本系统决定采用XML序列化技术。
1.1. 附:ORM技术
对象关系映射(Object Relational Mapping,简称ORM)是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。 简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将java程序中的对象自动持久化到关系数据库中。本质上就是将数据从一种形式转换到另外一种形式。 这也同时暗示着额外的执行开销;然而,如果ORM作为一种中间件实现,则会有很多机会做优化,而这些在手写的持久层并不存在。 更重要的是用于控制转换的元数据需要提供和管理;但是同样,这些花费要比维护手写的方案要少;而且就算是遵守ODMG规范的对象数据库依然需要类级别的元数据。
对象-关系映射,是随着面向对象的软件开发方法发展而产生的。面向对象的开发方法是当今企业级应用开发环境中的主流开发方法,关系数据库是企业级应用环境中永久存放数据的主流数据存储系统。对象和关系数据是业务实体的两种表现形式,业务实体在内存中表现为对象,在数据库中表现为关系数据。内存中的对象之间存在关联和继承关系,而在数据库中,关系数据无法直接表达多对多关联和继承关系。因此,对象-关系映射(ORM)系统一般以中间件的形式存在,主要实现程序对象到关系数据库数据的映射。
面向对象是从软件工程基本原则(如耦合、聚合、封装)的基础上发展起来的,而关系数据库则是从数学理论发展而来的,两套理论存在显著的区别。为了解决这个不匹配的现象,对象关系映射技术应运而生。
让我们从O/R开始。字母O起源于"对象"(Object),而R则来自于"关系"(Relational)。几乎所有的程序里面,都存在对象和关系数据库。在业务逻辑层和用户界面层中,我们是面向对象的。当对象信息发生变化的时候,我们需要把对象的信息保存在关系数据库中。
当你开发一个应用程序的时候(不使用O/R Mapping),你可能会写不少数据访问层的代码,用来从数据库保存,删除,读取对象信息,等等。你在DAL中写了很多的方法来读取对象数据,改变状态对象等等任务。而这些代码写起来总是重复的。
对象关系映射成功运用在不同的面向对象持久层产品中,如:Torque,OJB,Hibernate,TopLink,Castor JDO, TJDO 等。
一般的ORM包括以下四部分:
一个对持久类对象进行CRUD操作的API;
一个语言或API用来规定与类和类属性相关的查询;
一个规定mapping metadata的工具;
一种技术可以让ORM的实现同事务对象一起进行dirty checking, lazy association fetching以及其他的优化操作。