赞
踩
【本章导读语】
实践是最好的老师。
________玛利亚.蒙台梭利
SaaS发展也有一段时间了。我国已经有不少的企业在从事这方面的研发工作。市场上已经有较成熟的SaaS平台及应用系统。本章通过具体的几个案例分析剖析SaaS系统开发的全过程,旨在取到穿针引线的作用。但这并不能效仿,有人提倡“固化、消化与优化”的研发策略,但软件是个高深的科技,没有自己的创意与研究,难以成气候。我们倡导学习、引进,则不牵强附会地照搬。一知半解只会陷入泥潭若拔不能。
随着现在人们出行的盛行,各个交通工具的发达,人们出行更加便捷。随着服务方式与质量也大大提高。订票服务系统就是更方便地满足旅客的需求,实现在家网上订票。订票服务系统采用SaaS模式,完成客户网上、手机、电话等订票,通过电信与移动业务的接入,进行订票服务、采购服务、热线服务的业务整合的全过程。
客票的无纸化、网络化已成为全球主流趋势与普通客票相比,电子票(普通纸质机票的一种电子映象,是一种电子号码记录,现在已流行采用先进的二维编码技术,简称电子票)具有更明显的优势:电子票可通过互联网或售票机等多种形式查询、预订、购买,采用电子支付方式付款,无需到客运柜台购票。
在欧美等信息化发达国家,(航空、轨道交通等)电子票已经非常普遍,旅客通过互联网、或自动售票机订票之后,仅凭电子票就可通过设在入口处的自动检票机检票入门,真正实现了购票的一站式服务。目前,我国还处于不成熟的、摸索阶段,受我国国情限制,特别是票据报销制度约束,离真正的无纸化乘车还有一段距离。
交通运输业在国民经济中占有比较重要的地位,客运业自走向市场以后,航空、铁路、各汽运公司等运输市场的竞争也愈演愈烈,旅客已经不再满足于以往单一的窗口购票方式,近年来,各客运公司正不断进行电话订票、网上订票、手机短信等服务方式尝试,但因交易诚信、支付安全等种种原因,特别是取票难的影响,缺乏一套完整的解决方案,一直未能实现全面有效的推广应用,订票服务系统更适合SaaS模式,无论从营销上不是从服务上都离开网络平台。我们的订票服务系统就是建立在服务的模式下实现客户订票、自动售票(包括:订票、取票、电子支付)的全套解决方案。
l 交互式语音应答
拨入客户服务系统的客户,首先由自动语音应答导航:“您好,欢迎您使用......”,客户听到的是专业播音员的录音,语音清晰、亲切。这些大量重复性的信息可引导到自动语音播报系统,这样就可使客服人员从大量的重复性劳动中解放出来,从而可以减少人工座席数量,也可避免情绪不佳等因素对客户的影响,为客户提供更专业、周到的服务,提升企业形象。与热线电话相比,客户服务中心运营成本更低,服务质量更高。
客户可按自己的意愿选择自动语音播报及人工座席应答;对于新客户可以选择自动语音播报,了解服务中心的业务情况、如需人工帮助可转入相关人工座席。
l 自动话务分配
自动呼叫分配系统(ACD)是客户服务中心有别于一般的热线电话系统的重要部分,在一个客户服务中心中,ACD成批的处理来话呼叫,并将这些来话按话务量平均分配,也可按指定的转接方式传送给具有相关职责或技能的各个业务代理。ACD提高了系统的效率,减少了客户服务中心系统的开销,并使公司能更好的利用客户资源。
l 自动传真群发
自动传真:客户可以通过电话按键选择某一特定的传真服务,传真服务器会自动根据客户的输入动态生成传真文件(包括根据数据库资料动态生成的报表),并自动发送传真给客户,而不需要人工的干预。
电脑传真:如果业务代理在与客户交谈时需要立即为客户发传真,她可以启动座席电脑上的桌面传真,则当前客户的资料如客户名、传真号等就会自动调出,再选择客户所需的传真内容,然后业务代理就可以点击发送按钮把传真发送出去了。
l 短信群发
短信是现代人新获得的一个重要的沟通手段,实现短信的自动收发与管理能够很方便的实现与客户的沟通,及时方便。坐席人员用鼠标就可以实现对多个客户发送及时信息或近期公司的促销信息,客户发来的信息可以保存在相关的目录下,方便后期的管理。
l 呼叫管理监控
将录音系统并接到人工座席的分机线上。电话录音系统是可以同时进行多路电话录音、监听的系统。
同时对多路语音通道录音和监听,自动备份,以及灵活的录音查询与回放。系统可以按客户需要自动对硬盘进行维护,从而保证系统的不间断、稳定工作。
l 人工坐席的应答
根据客户的需要,将进行自动语音应答(IVR)的话路转接到人工座席上,客户将和座席人员进行交谈,接受客户预定、解答客户的疑问或输入客户的信息。
座席登陆:座席临时闭席:将用户电话转接到其他座席人员。
电话会议:两个座席与用户同时通话。
强插:强行插入某个座席人员的通话
强拆:强行结束某个座席人员的通话与用户进行通话。
来电号码的显示和客户资料的弹出:业务代理面对大量的客户,迅速的获悉来电客户的身份、背景资料以及历史资料在很大程度上决定了其服务质量。通过自动被叫号码证实及自动主叫号码证实,客户服务中心将在建立路由的同时检索与其相连的中心数据库,将客户资料同步的显示在业务代理的计算机上(Pop-Screen)。方便业务代理的输入,提高了效率与正确率。
l 查询统计
需要有效的测定客户服务中心的数据,因此,客户服务中心需要能够对呼叫及响应的时间进行实时的存储、统计、输出,并且具备生成各种报表的功能。强大的统计分析功能包括对各时期(实时、天、月、年)的话务特征的统计,对各时期、各专项业务特征的统计,对各辅导员的工作特征的实时或历史的统计,对统计数据的分析。系统可以根据客户自动查询时,查询的内容,查询的时间生成节点查询数据表,积累客户喜好数据;同时可以统计每个业务代理的话务量,通话时长,以此分析业务代理的服务质量等。
l 客户资料的电脑查询及录入
人工座席可以询问客户问题,然后运行座席电脑上的专用查询软件,到数据库中查找相应数据,客户代理可以参考找到的结果,和客户进行轻松交流,同时也可以将查到的数据转化成语音,让客户自己倾听所需资料。
此部分同时提供数据采集功能,当座席人员和客户通话时或通话后,根据系统的提示,将必要的通话结果输入到数据库中,留作将来的数据挖掘之用。
订票服务系统可分为三部分即企业内网、服务平台和订票中心。企业内网提供用户网上订票、用户服务咨询、目的地查询、票价介绍等功能,同时提花企业及代理商管理员、工作人员等内部员工管理功能。服务平台是系统的核心,包括互联网平台、电信平台、移动平台的互联与接入及订票服务、采购服务、其他服务等功能。订票中心包括呼叫中心、坐席代表等热线服务及送票、计费等功能。图17-1是订票服务系统的框架设计图。
图17-1订票服务系统框架设计
订票系统的业务流程并不复杂,订票人首先通过热线系统或者网络查询进行询价,然后决定订票后就网上填单或者由服务员代理填单,最后订票系统把客户请求及客户信息发至订票管理中心。系统就自动启动监控跟踪,直至整个业务最终完成。图17-2体现了整个过程。
图17-2订票服务系统业务流程
订票服务系统的功能由以下几部分结成:
l 航班管理
航班计划管理、航班公司管理、机型管理。
l 订单管理
电话订票:通过电话预订机票。订票客户管理、机票管理。
l 代理商管理
用户注册、用户登录、机票预订、退票等。
l 服务端系统管理
电信、移动、网通接入。
投诉与建议:全天侯地接收、保存用户的各种投诉与建议的语音信息。
电话/语音通知:将重要信息通过电话、手机、传真等方式通知用户(旅客、货主等)。
旅客服务:异地付给取票。管理人员对语音记录的查询与处理。
l 数据统计与查询
航班查询:用于查询某一航班的起飞、到达时间等信息。
机票查询:查询某一航班是否还有机票。
货运查询:用于查询发运的货物的当前状况。
l 系统监控
后台管理、统计报表
自动录音:座席摘机(拿起电话)就开始录音。
自动备份:可以根据用户的设置自动备份录音文件。
自动播放:自动播放查询到的录音文件。
自动维护:如果录音磁盘空间还剩下一定空间时,自动删除最早的录音。
电话筛选录音:可以对所有通话录音,也可选择特定号码录音。
录音查询:可以按录音时段、座席姓名、座席工号、录音时长等查询录音。
监听:选择录音通道,可以听到通话内容。
网络查听:录音系统引入了先进的网络技术,使用户无论身在何处都可以通过电脑网络远程查听。
系统分为角色ServerManager(管理员)、Agent(代理商)、Users(客户)。我们按角色有不同画出系统的用例图。
图17-3用例图(ServerManager)
图17-4用例图(Agent)
图17-5用例图
销售管理系统建立在SaaS平台上,系统分为设备接入层、用户界面层、业务处理层、ASP平台探制层、数据访问层。其逻辑结构图见图17-6:
图17-6订票系统逻辑图
有了对系统的需求分析,通过上面的用例图我们进一步按系统业务逻辑得出时序图如下图所示:
图17-7时序图
图17-8是客户订票的状态图:
图17-8状态图
下面我们来分析系统的对象并设计出系统的类图,如图17-9。
图17-9类图
上面类图说明,PlaneModel:飞机型号;AirlineCompany:航空公司;Log:日志;Order:订单;OrderItem订单项;User:用户;Flight:航班;FlightSchedular:航班计划;Cabin:航位;TicketType:机票类型;FlightSchedular:航班。
最后我们设计出系统的部署图如17-10所示:
图17-10部署图
本系统具有以下几个方面的显著特点:
l 实现电话、因特网(Internet)、传真、VOIP等多种方式接入与呼出;
l 引入自动文本转语音(TTS)技术;
l 支持计算机语音板卡、排队交换机等多种语音接入方案;
l 易于和票务公司内部各种信息系统高度集成,从而在信息化管理上实现了对票务公司内部资源和外部资源的有效整合;
l 话路、客户数据、操作界面的同步转移;
l 灵活多样的独立可选模块配置;
l 系统提供了客运电子票售票应用的全方位解决方案,丰富的票务信息查询、购票、支付、取票形式适用于各种习惯旅客群体,自动售票机布放,延伸了客运公司网点,解决了购(取)票难问题,对乘客来说,操作形式多样,就近购取票,不再受区域、时间限制,保证了资金安全,对客运公司来说,为乘客提供优质服务同时,减轻窗口劳动强度,提升了客运公司的企业形象。
l 多用户网络订票服务。电信、移动、网通三者整合,统一运营管理。
销售管理系统(简称为STS)是一个建立在SaaS平台上的业务应用系统。该系统主要体现销售过程中签订订单前的全过程。包括销售计划中全程跟踪的各过环节。系统实现短信汇报、PDA上报、Gocom(即时通讯工具)上报等多种设备接入方式,通过销售计划、销售机会、销售跟踪、销售日志、多种提醒功能实现销售的跟单过程,并且通过大量的分析图分析销售的机会状态,为提供决策做出有力依据。
STS系统是以销售机会和销售活动为管理核心,帮助企业跟踪销售过程的一个系统。它能预测企业销售趋势,方便的跟踪销售人员的销售活动记录。帮助企业主更好的了解自身的销售状况。
l 功能介绍
短信上报:通过手机短信给上级及相关人上报工作日志、计划、业务执行情况、机会跟踪进展情况等。体现了按代号快速群发的思想。
PDA上报:功能如手机。
Gocom:类似MSN、QQ的聊天工具。更优越之处是直接与本公司及客户公司的组织机构挂构。并支持短信群发、邮件群发点。可直接导入销售机会信息。
销售计划:是业务人员或者团队的销售计划安排、指标任务及考核数据。
销售机会:潜在的或正在跟踪的客户及业务。
销售跟踪:销售活动的全过程,一般指售前。
销售日志:销售业务人员的工作日志、心得
销售提醒功能:按设置的方式可通过手机、电脑、Gocom等定时闹铃、弹出页面等提醒人员。
销售周报:包括周计划、上周执行情况,周总结等。
具体的功能图如图17-11。
图17-11STS系统功能图
l 系统角色
销售管理系统中具体包括业务员、业务经理、业务主管等角色。当然也有系统管理员、一般用户。不同角色具有不同功能权限。业务员1不可看到业务员2的销售机会及相关数据,业务经理1不可看到业务经理2的销售机会。当然在经授权后是允许看到的。但上级可看到下级的相关数据。下图说明了这个问题。
图17-12STS系统角色关系图
l 系统亮点
² 帮助企业进行销售趋势预测
² 系统简单易用
² outlook风格的销售活动日历页面显示
² 短信上报和短信提醒支持
² 丰富的报表展现
² 强大的订阅提醒
² 帮助企业进行销售趋势预测
² 系统简单易用:熟悉三四个页面就能使用系统
1. Outlook风格的销售活动日历
图17-13销售活动日历
2. 方便的短信上报和提醒
图17-14STS系统短信上报和提醒
3. 丰富的报表展现
图17-15STS系统角色关系图
4. 强大的提醒功能
图17-16STS提醒功能
l 传统模式的销售跟踪
业务员 缺点: 1、由于未能及时记录每天活动情况,写周报时不太准确。 2、由于未能及时记录,有时写周报的工作变成业务员的一种负担。 3、文件都是分散的,不集中,不方便进行了解和利用别的业务员的工作成果。 | 业务经理 缺点: 1、汇总工作量大。 2、不能很快定位出销售情况出现的问题。 3、工作成果不能很方便的共享给大家。 | 业务主管 缺点: 1、看的都是文字性的总结,不清晰明了。 2、不能很快找出当前出现的问题。 3、只是跟踪销售人员状况,对机会销售活动管理和销售趋势预测没有整体感觉。 |
l 使用者分析
业务员 关心: 1、上线系统对我有什么帮助,能让我学到知识或者经验。 2、系统容不容易上手,是不是需要花很多时间去学习。 | 业务经理 关心: 1、通过系统能方便快速的了解业务员的工作状况。 2、及时了解部门当前销售状况,预测部门销售趋势,是否能顺利达成销售计划。 3、大大减轻汇总工作量,通过的简单的工作或者系统自动完成就能跟主管汇报。 4、业务员离职后,新员工能通过系统快速接手工作。 5、重点项目跟进和监控。 | 业务主管 关心: 1、通过系统了解下属的工作状况。 2、及时了解公司当前销售状况,预测公司销售趋势。 3、方便的看到各种销售的汇总报表。 4、跟踪重点项目的详细销售过程。 5、对销售计划的达成是否有风险警示。 6、效益和成本问题 |
担心: 1、上线系统会不会给我平时工作带来更大的工作量。 | 担心: 1、系统上线是否增大员工的工作量。 2、系统是不太容易上手。 | 担心: 1、系统是否安全。 2、推广时间很长,见效很慢。 |
STS系统是一个简单、高效、灵活(支持多种访问)、智能(趋势预测、风险警示、自动提醒等)、安全,以销售机会和销售活动为管理核心的销售管理系统。下面我们列出系统的功能计划如图17-17。
图17-17STS项目计划
图17-18STS项目管理框架
销售机会模块
l 销售机会属性:根据销售理论体系进行添加或者修改。
l 销售机会列表页面:显示列为:销售机会、客户、负责人、所属部门、所属行业/预计签单日期、预期金额、可能性、当前阶段、未进展报警、活动。
l 销售机会填写表单:负责人的修改需要有权限控制。个人能定义销售机会的重要程度,并按此排序。销售机会成功签订或者失败签单要进行总结,总结失败原因、成功原因,并能进行统计。销售机会负责人可以授权此销售机会的查看人。
l 销售机会详细信息页面:机会阶段和日志列表:做成一颗关联树,点击“+”和“-”可以进行伸缩方便浏览。
l 填写日志页面:可以修改选择销售机会当前阶段信息。
l 销售日志列表页面:销售日志显示列表,针对日志类型,行动效果对日志标题加一些小图标进行标注,美化界面,使看日志的人更快读懂记录。
l 销售机会列表。列表显示的分为:销售机会、客户、负责人、预计签单日期、预期金额、可能性、当前阶段、未进展报警。
l 报表展示:销售漏斗替换现有的销售人员机会数分析。
l 订阅提醒
列表显示的列分为:销售机会、客户、负责人、预计签单日期、预期金额、可能性、当前阶段、未进展报警。
点击列表中的机会名称能直接链接到机会详细信息页面。
l 销售任务:公司销售任务管理。业务员分担销售任务管理,任务与实际完成和销售趋势的分析对比报表。
l 工作计划:销售人员下一周工作计划。工作计划导入工作日志功能。工作计划中涉及资源预定。
l 资源预定:资源管理。资源申请预定。资源批准。
l 系统级监控
监控信息:操作人员、所属企业、所属企业部门、机器IP、操作类型、操作描述。
报表统计:按时间/个人/企业/企业部门/机器IP/操作等维度进行监控和统计。
l 企业级监控
监控信息:操作人员、所属企业部门、机器IP、操作类型、操作描述。
报表统计:按时间/个人/企业部门/机器IP/操作等维度进行监控和统计
l 系统总体风格:支持多套风格,采用CSS控制,支持个性化定制风格,全面采用AJAX技术,解决目前页面反复刷新的问题。
l 多样的灵活的系统访问方式:短信上报进一步完善:进行销售计划的提醒,领导资源预定申请的提醒,支持WAP方式访问系统。全面支持邮件提醒机制。
l 智能化的分析引擎主动帮您分担管理销售:重点销售机会变更提醒和未进展提醒。
销售漏斗分析,销售趋势预测。销售任务和销售计划达成风险警示。销售人员工作状况分析,个人工作效率分析,个人估计风险分析。
l 系统使用排行榜功能让您轻松促进系统推广及考核:阶段预期签单金额排行榜,阶段成功签单金额排行榜,销售日志上报情况排行榜,销售日志执行情况排行榜
系统登陆使用情况统计分析。
统计维度:个人/时间/部门/访问内容
l 系统访问页面或者模块统计分析
统计维度:个人/时间/部门/访问内容
STS系统分为三层:表示层、业务逻辑层、数据访问层,如下图:
图17-19STS系统架构
表示层:STS系统的UI部分,负责使用者与整个系统的交互。在这里我们将利用ASP.Net来设计并实现webforms,在这里我们也将调用许多Web控件和相关逻辑。
业务逻辑层:STS系统的业务逻辑层与具体的销售跟踪业务所特有的逻辑相关,例如销售活动日志提醒,销售机会提醒,销售机会分析等等。如果涉及到数据库的访问,则调用数据访问层。
图17-20业务逻辑层
数据访问层:负责数据库的访问。就是实现对数据表的Select,Insert,Update,Delete的操作。(考虑ORM机制)。这个层在整个系统架构中处于底层,相对稳定,但需要在设计上综合考虑如下几个方面的要求:
(1)数据存储容量
(2)访问效率
(3)稳定性及安全性
图17-21数据访问层
以上阐述的是一个整体的系统架构,各个层次中根据实际的应用需要、业务特征和背景特征(领域性),可以相应的引入一些辅助的处理模块,如可以在数据访问层增加消息处理模块,可以处理异步插入消息日志等请求,这可以采用MSMQ(MicrosoftMessagingQueue)技术来实现。同样,在表示层可以增加CacheDependency模块以则提供缓存功能。下面我们分析各层的组成如图17-22:
图17-22STS系统架构各层的组成
l 工程设计
STS系统工程严格按分层的思想。我们分别分为STS_BL、STS_CommomDll、
STS_ControlBase、STS_DAL、STS_Monitor、STS_Proces层,如图17-23。
、
图17-23STS工程设计
表示层PL(PresentationLayer),UI设计,页面风格定义CSS/App_Themes,构建Web网站工程,系统首页default.aspx,用户页面控件userpage.ascx,用户交互界面。
l 与外部平台接口(短信,gocom,PDA)
图17-24STS外部接口图17-25STS系统物理设计
业务层BL(BusinessLayer),业务策略机制,对业务对象及策略的抽象方法,核心业务模块,销售活动对象处理,销售机会对象处理,报警及消息提醒对象处理,报表中心,接口模块。
图17-26STS工程设计
数据访问层DAL(DataAccessLayer)包括数据库引擎、数据库访问层接口、数据对象。公共组件动态库(DLL)包括数据库访问组件(独立封装,复用组件)、公共类库、控件类库。
图17-27STS系统公共组件动态库
图17-28是数据模型设计图:
图17-28STS数据模型设计
下面是关键数据表的详细说明:
表17-1SMS_Send发送表
字段 | 类型 | 长度 | Null | PK | 备注 |
id | numeric | 9 | √ | 自增长标示种子为1 | |
IdEnt | varchar | 100 | √ | 预留给调用的字段,例如用户名等 | |
SendTime | varchar | 50 | 发送时间YYYY-MM-DDhh:mm:ss | ||
ObjMobile | varchar | 4000 | 目标号码,最多400个号码,”,”分隔 | ||
Content | nvarchar | 70 | 最多70个汉字,含标点符号 | ||
Affixcode | varchar | 8 | 附加码,自由分配,最长为7位 | ||
state | varchar | 50 | √ | 短信发送状态,未发送时为空或null | |
Tag | int | 4 | 0=待发1=已发 | ||
EntID | Varchar | 20 | 企业ID |
表17-2SMS_Recv接收表
字段 | 类型 | 长度 | Null | PK | 备注 |
id | numeric | 9 | √ | 自增长标示种子为1 | |
RecvTime | varchar | 50 | 发送时间YYYY-MM-DDhh:mm:ss | ||
ObjMobile | varchar | 4000 | 回复来源手机号码 | ||
Content | varchar | 70 | 回复内容 | ||
Affixcode | varchar | 8 | 附加码,即回复的目标号码,以0开头 | ||
Tag | int | 4 | 0=待取1=已取2=插入失败数据 |
表17-3SMS_STS临时表存储应对一条短信拆成多条短信发送的情况
字段 | 类型 | 长度 | Null | PK | 备注 |
id | numeric | 9 | √ | 自增长标示种子为1 | |
mobile | varchar | 50 | |||
Affixcode | varchar | 8 | 附加码,即回复的目标号码 | ||
Content | varchar | 200 | 短信内容 | ||
Orderno | Numeric | 9 | 排序号:0为短信头,999为短信尾 | ||
Recv_id | numeric | 9 | 短信接收ID |
表17-4短信状态值:即发送表中的state值
返回值 | 说明 | |
该栏显示的状态值均为发送短信成功提交后短信网关的返回值 | 未知故障 | |
失败 | 短信发送失败 | |
成功 | 短信成功发送 | |
成功,还有短消息接收 | ||
序列号码为空和无效 | ||
网络故障 | ||
其它故障 | ||
注册企业基本信息失败,要重新注册 | ||
注册信息填写不完整 | ||
参数balance指针为空 | ||
卡号和密码为空和无效 | ||
手机号码为空或超过1000个 | 手机号码非法 | |
手机号码分隔符号不正确 | 群发短信时需用逗号隔开(EN) | |
部分号码错误已删除,其余号码被发送 | ||
短信内容为空或超长(70个汉字) | ||
附加码过长长8位 | ||
定时时间为空,或格式不正确 | ||
旧密码或新密码为空 | ||
得到标识错误 | ||
得到短信序列号(seqnum)错误 | ||
计费失败 |
协议标识 | 说明 | 协议格式 |
01 | 企业身份验证 | 标识|企业序列号|企业名称|企业密码 |
02 | 号码申请 | 标识|企业序列号|号码个数 |
03 | 短信发送 | 标识|企业序列号|即时发送|用户名|手机号码|发送内容|附加码 |
标识|企业序列号|定时发送|用户名|手机号码|发送内容|附加码|定时发送时间 | ||
04 | 下载短信 | 标识|企业序列号 |
10 | 请求服务端断开服务连接 | 10|企业序列号 |
表17-5短信协议
天宇集团凭借几十年的项目开发经验以及长期的技术积累,开发出了自主知识产权的SaaS模式的软件基础平台:天宇Ttyu平台,它的主要特点就是以业务为导向,通过点菜模式可快速构建应用软件,实现软件大超市。采用这种平台可以大大提高软件开发效率,并能快速地满足用户变化的需求,客户在线租用。
天宇Ttyu企业应用平台是一套面向企业信息化的开发WEB应用的开发平台,它完全遵循J2EE(JAVA2EnterpriseEdition)规范,这一企业应用软件平台产品所包含的组件都是作为一个有机的整体,共同开发、组装、调试和发布,从而保证了无缝的互操作性,并享有单一安装、升级和支持模式,由此简化了管理的复杂性。Ttyu平台基于大量企业级应用模式和企业级集成模式的面向企业级应用开发的框架。开发者可以为了实现解决不同的问题方便的使用、扩展、定制不同层次的组件。软件基础平台和用户的管理及业务相关度比较大,是管理、业务软件开发的通用基础平台。
图17-29天宇Ttyu平台总体框架图
天宇Ttyu平台由技术组件、业务组件、开发工具、开发方法及其它组件组成。技术组件包括界面组件、JDBC组件、缓存管理、异常管理、基本工具以及扩组件。业务组件包括业务服务平台BSP、模型驱动开发工具MDA、业务流程管理BPM、消息平台、系统集成EAI、数据集成GAI和报表组件。该平台以MVC框架为主体、基他模块为业务件插件,采用“主体+插件”的形式,集开发、组装、调试和发布于一体,保证了软件开发的无缝互操作性;并享有单一安装、升级、支持模式,简化了管理的复杂性。在高效构建的前提下,方便灵活的使用、扩展、定制不同层次的组件,各个子系统不便健壮灵活,能有机的整合在一起,而且保证了大型企业级应用的稳定性和高效的可扩展性,有效地解决了软件的“三大世界难题”“集成、适应变化、开发效率。”
标准版内含Ttyu框架(包括通用构件)、组织权限模型、WEB组件、灵活报表、打印工具等构件,支持多样的用户接口,即时通讯消息构件。
1.WEB应用技术框架
l 应用架构
图17-30天宇Ttyu平台应用架构图
l 技术架构
图17-31天宇Ttyu平台技术架构图
采用大型系统最流行的MVC模式构造,合理的分层,实现流水线分工作业,简化了管理的复杂性,降低软件开发技术含量。开发者可以为了实现解决不同的问题方便的使用、扩展、定制不同层次的构件。通过使用本框架开发程序,能使开发商简化开发过程,提高开发效率,能快速的开发和变更软件,开发出来的产品具备良好的稳定性、可扩展性和可维护性。
框架是为其他平台提供各种接口和功能服务的基础构件,扮演着至关重要的角色,起着关键的作用,是产品的中流砥柱;是采用J2EE技术的应用服务器、完全面向对象的JAVA语言开发的多层体系结构的应用系统。
丰富的构件。使得开发像搭积木一样简单。
框架的技术思想,如图17-32:
采用N-Tie思想,将三层结构的客户层,中间层,又分为多层实现,既能得到最大的灵活性,又能工具有效地实现负载平衡,得到最大的性能服务。其核心是基于服务的架构,提供访问分发、Command、资源、数据访问、展示、权限、商业构件(BO)等核心服务,满足绝大多数Web应用的需求。用户还可在此基础上选择多种可选服务,比如邮件处理、文件管理、计划、格式转换、审计、防止重复提交、安全提交等服务。
图17-32天宇Ttyu平台技术架构图
图17-33天宇Ttyu平台三层结构图
2.组织权限模型
组织权限模型为企业级应用系统提供业务公共平台,把政企应用共有的业务提炼出来,形成通用的业务信息系统,在此层面基础之上,用来构建、集成和运行政府、企业的信息系统,以减少企业级应用开发过程中重复的开发。
基于可重构的抽象对象模型,这些类既包含由应用程序开发人员继承和使用的完整方法,也包含可能由应用程序业务对象的开发人员实现的方法的抽象定义。应用程序开发人员可使用此对象模型来构建面向对象的应用程序和框架。
抽象对象模型提供下列特性:
l 自定义业务对象属性
l 可变的业务逻辑
l 统一的对象唯一标识符
l 面向对象的设计模式
l 按照对象属性的查询/筛选方案
组织机构是企业级应用的基础,任何企业级应用的业务核心数据来源。
组织机构技术特性:
l 科学合理的管理模型确保了组织结构管理在操作级的灵活性知识级的稳定性。
l 支持直线制、职能制、直线-职能制、事业部制、模拟分权制、矩阵制等组织结构模式。允许用户根据自身战略选择适合自己业务需要的组织结构模式。
l 支持组织结构规则(如上下级规则、不相容岗位等)的灵活定义。
l 提供了完备的组织结构版本管理功能,允许用户在若干年后查阅历史组织变更版本记录。
l 系统内嵌了人事事件记录功能,对于部门的设立、撤销,员工的入职、升职、加薪、改序等提供了完备的人事事件记录,在此基础上支持对职工进行职业成长性分析。
l 支持直接下级排序(如下级部门间排序、下级员工间排序)和员工的全局排序(如根据领导岗位与非领导岗位进行排序)。
l 支持从不同的维度对组织结构进行观测,如从人力资源层面、计划、考核、销售管理、采购、库存等视角进行切分。图型方式的显示。
l 支持组织结构构件的分布式部署和基于LDAPV3国际标准的组织核心级数据共享。
组织机构,定义了灵活的结构设计,绘制了灵活的抽象结构模型,提供丰富的接口,方便开发人员在此基础上根据业务需要定制开发,并能灵活扩展,以适应实际的业务需求。开发人员可以利用定义的上下级方式,方便的实现形成组织结构的树型结构。方便开发和维护。
权限模型:业务服务平台是基于RBAC(基于角色访问控制)理论设计。通过对各类操作权限设置和组织机构设置紧密配合来实现业务分工以及业务权限管理。权限配置不仅可以对组织、机构、岗位、人员进行一般性的权限配置,还可以实现权限分层管理以及权限继承等复杂的权限管理功能。
3.WEB组件
WEB组件是J2EE开发中一套完整的WEB端的控件,包括网格,树型,列表,日期等在开发中常用的控件,WEB控件采用JSP的标签TAGLIB技术,遵循J2EE规范,将复杂的客户端界面显示和JAVASCRIPT封装成控件。
WEB组件的意义在于:
l 提高WEB项目的可视化界面,提供友好的用户界面和良好的界面操作性。
l 简化开发过程,开发人员不需掌握复杂的JAVASCRIPT技术就能开发出高效友好的用户界面,提高开发效率。
l 分离显示逻辑和业务逻辑,真正实现多层结构。
l WEB端控件可和服务器端对象可直接映射,使WEB开发能以OO的方式进行。
l 组件可重用,维护性好。
l 组件技术依从主流的技术标准,具有开放性和扩展性。
4.灵活报表
报表在应用系统中占据着极其重要的地位,报表系统的好坏实际上关系到政企决策的有效性,关系到客户的满意度,也关系到应用系统的成败。目前流行的报表工具都很难完全满足国内客户应用的需要。国内客户对于报表的要求相当强烈而苛刻,对于报表的抬头、字体、格式、美观性等都有非常强烈的要求。
灵活报表工具包含报表可视化集成设计工具,提供客户自定义报表功能,用户和开发商可方便简洁的创建报表。可以用各种各样的格式发布报表,包括用Word、Excel发布、通过电子邮件、通过WEB发布。支持多种导出格式,比如PDF,Html,Word,Excel等等,支持不同平台和不同的数据库。
5.打印构件
打印构件的核心价值是提供了一个WEB环境下快速定制、免于维护且能满足各种复杂打印需求如套打的打印解决方案。
传统的打印方式都要在客户端(打印机所在机器)上写打印代码,并且需要获得打印机的参数。这样不适用于B/S结构。打印构件基本结构设计成类似PDF文件/打印的方式。即先生成可打印的XML描述文件,然后再在客户端解析并打印。XML描述文件包含描述打印/控制的指令和要打印的表格数据。
打印构件除了提供基本的文字/绘图功能外,结合客户端的打印构件,还提供自动分页,以及客户端可人工调整表格列宽、列高以及字体等功能。完整的解决了B/S开发中一个老大难问题。
6.权限模型
业务服务平台是基于RBAC(基于角色访问控制)理论设计。通过对各类操作权限设置和组织机构设置紧密配合来实现业务分工以及业务权限管理。权限配置不仅可以对组织、机构、岗位、人员进行一般性的权限配置,还可以实现权限分
层管理以及权限继承等复杂的权限管理功能。
7.日历管理与业务流水管理
提供了工作日历及财务期间管理,工作日历主要用于描述企业对工作日程的安排;为满足企业财务管理层面记账和统计的需要,进行统一的会计期间定义,
提供财务期间管理。
在用户的一些业务操作中,会需要全局唯一的标志号,如订单的订单号,许可证的许可证号等。BSP业务流水管理提供了两种形式的业务流水号,第一种系
统全局唯一的流水号,第二种按公司唯一的流水号。
8.安全管理解决方案介绍
图17-34安全管理系统在信息系统中的位置
图17-35安全管理系统的运作机制
l 全面支持ISO7498-2定义的各项安全服务:实体鉴别(EntityAuthentication)、数据保密性(DataConfidentiality)、数据完整性(DataIntegrity)、防抵赖(Non-repudiation)、访问控制(AccessControl)
l 在实体鉴别(EntityAuthentication)层面支持基于传统关系数据库的认证、基于LDAP的身份认证,支持单点登录(SSO)。支持数字证书。
l 在数据保密性(DataConfidentiality)层面支持MD5/SHA等传统的加密算法,用户可根据自身安全需要灵活扩展自己的加密算法。
l 数据完整性(DataIntegrity)层面支持数字签名和消息摘要。
l 对于防抵赖(Non-repudiation),我们提供了功能强大的审计功能。捕获安全性相关事件记录的操作。以利于用户发现系统中可能存在的问题,预防和追究非法操作。
l 访问控制层面我们支持美国国家信息技术标准委员会制定的RBAC96(基于角色的访问控制)标准和安全管理学界流行的自主访问控制标准。RBAC96实现如图:
图17-36访问控制层
l 支持集团级中央安全服务器为了满足安全管理系统部署的灵活性,我们引入了OASIS制定的XACML(eXtensibleAccessControlMarkupLanguage)2.0标准,支持安全策略制定(PAP)和安全策略决策(PDP)与安全决策执行(PEP)各子系统的分布式部署。如图:
图17-37分布式部署
l 提供界面友好、美观、丰富的界面构件:
² 树形组件(单选树、多选树、排序树、链接树、一次性取数据、分阶段取数据)
² 表格组件(支持小键盘录入、自动计算、合计、可拖动栏目)
² 菜单组件(普通菜单、outlook方式菜单、动态菜单)
² 列表组件(单选、多选下拉列表,联动下拉框)
² 分页(TAB组件)
² 图形组件:雷达图、饼图,柱形图,折线图,混合图,曲线图,事件图,三维横条图,三维饼图,三维堆积图,三维横条堆积图
² 通用的帮助框组件:根据数据模型快速定义支持小键盘和主从表结构界面的能力(比如订单录入,现场自定义)
l 高性能及可靠性、高扩展性
² 高可靠性,支持7000以上并发用户(用已上线运行案例例证高性能及可)靠性、高扩展性
² 基于MDA模型,可灵活扩展
l 可用性
² 提供统一的信息发布平台
² 支持信息格式的自由转换(邮件、短信、socket、xml、数据库等多种格式两两之间自由转换)
² 支持全文搜索的搜索引擎
l 兼容性
完全符合J2EE规范,提供标准J2EE应用包(EAR)即可,无需额外再安装任何程序
l 开放性
生成的组件以及代码可灵活修改、扩充
l 面向服务的框架
Ttyu框架的核心是基于服务的架构,提供访问分发、Command、资源、数据访问、展示、权限、商业构件等核心服务,满足绝大多数WEB应用的需求。用户还可在此基础上选择多种可选服务,比如邮件处理、文件管理、计划、格式转换、审计、防止重复提交、安全提交等服务。
下面是几个服务的介绍:
表17-6:服务列表
名称 | 介绍 |
分发服务 | 可将不同的请求分发给相应的命令来处理。 |
模版服务 | 定义了页面端显示的外观布局,模版支持XML,HTML,WML等多种显示方式,可根据用户不同而个性化桌面定义。 |
命令服务 | 可根据配置文件取得对应的命令处理,可以根据需要替换命令的实现方式,灵活组织多个命令为一个宏命令。 |
资源管理服务 | 将软件的图片、脚本、文件、类等多种资源有效的统一管理。 |
连接服务 | 可提供访问连接池,数据库映射,数据持续化,多种数据库访问接口,UUID。 |
安全服务 | 提供灵活的权限接口,可以通过LDAP、数据库、其他主机认证等多种认证方式 |
商业构件服务 | 可以调用支持一定接口的商业构件,商业构件可以由开发商根据不同的开发策略灵活实现。比如可以实现为JDBC,CICS,EJB,WebServices。 |
令牌服务 | 可产生令牌环,防止重复提交,防止非法交易。 |
缓存服务 | 系统将常用的对象缓存起来,减轻数据库服务器和应用服务器的压力。 |
审计服务 | 对所有系统操作进行审计记录。 |
服务架构采用最流行的插件的思想,所有的服务都是插件,可以根据需求采取不同的实现,也可根据需求添加新的服务,所有这些都不需要更改已有的程序。系统中使用了多种设计模式,比如命令模式,助手模式、策略模式,Adpater模式,使系统得到很好的柔性。
l 贯穿始终的WebServices
WebServices不仅是企业级应用Web框架的基础,而深入贯穿其中。要想利用WebServices实现业务目标,仅凭对SOAP和WSDL这样的标准提供支持还远远不够。此外,还需要具有运行时框架来完成松散偶合的集成,以及一个能够支持异步会话、业务级消息的架构,从而生成、部署、集成、编排和表达企业级的网络服务。
LSWAF中所支持的WebServices包括:
² 门户框架——用于支持WebServices的表达和消费
² 集成框架——用于围绕业务流程对WebServices进行协调管理
² 运行时框架——用于实现可靠的、可伸缩的和高可用性的部署
² 集成开发框架——使所有开发人员都有能力轻松、快速地创建、部署和测试企业级的WebServices凭借企业级应用Web框架,IT部门能够快速、可靠地实施以WebServices为基础、面向服务的体系结构。该架构的覆盖范围横跨浏览器和核心业务信息系统,并延伸到整个业务“生态系统"中的众多合作伙伴和客户
l 事件消息驱动的业务流程
互联网是由分布式、松散耦合的计算系统定义的。无论是客户投标还是政企之间的通信,都涉及到数据和事件在应用系统间的连续流动。要实现这种交换,系统需要在异步、异构资源间高度可靠的通信。
Ttyu框架提供了基于JavaMessagingService(JMS)的强大的、灵活的、紧密集成的、基于J2EEJMS(JavaMessagingServices)DE消息处理平台,用作消息处理系统的主干。
JavaMessagingServices的强大功能源自其与企业级应用Web框架群集的集成,和保持数据库、文件或基于内存方式的数据处理一致性和异步消息分的能力。当前,政企都在部署必须能够全天候运行的电子政务、电子商务系统。系统的瘫痪就意味着机遇的丧失。为了维护这些系统,系统管理员需要适当的工具来启动和关闭服务器,选择并监控资源配置,检查并纠正问题,监测并评估系统性能,以及部署Web应用、EJB、WebServices和其它资源。
l 系统管理与监测
Ttyu框架带来了功能强大、可扩展的、基于Web的管理控制台(ManagementConsole),可为管理员提供部署、配置并监测其应用的工具。管理服务采用JMX(JavaManagementExtension)标准实现,管理控制台支持JMX(JavaManagementExtension)标准,为管理资源提供了工具。通过管理控制台,管理员可以配置资源,部署应用系统或构件,监测资源使用情况(例如服务器负载、JavaVirtualMachine内存使用情况或数据库连接池负载),查看日志消息,关闭服务器或执行其它管理活动。
除了这些基本的系统管理任务外,LSWAF的开放的JMX框架让客户和合作伙伴能集成管理解决方案,并引用可编程的方法管理应用。在一个群集部署环境中,用户可看到整个群集范围内的应用,并能够管理每个节点。另外,SNMP界面可轻松实现与其他管理解决方案的集成。
l 模型驱动、开发快速:
缩短项目周期、节省人力、降低成本。开发效率提高80%以上,合理的分层,实现流水线分工作业。
l 基于B/S的图形化、可视化定制:
可视化的界面屏蔽了专业的技术细节,友好的界面使非软件专业的行业业务人员也可以轻松自如地定义自己所需的软件。
l 构件松耦合、高度的灵活性:
平台基于接口的实现,形成构件间的公耦合,每个构件都能轻松调换,增强了系统的录活性。
l 高效率、高可靠性
集成了丰富的通用的子功能模型,子模型的代码都经过了严格的压力测试,能最大限度地保证系统的运行效率以及运行时的性能。
l 扩展性
通过简单的定制就可以很方便地实现业务的定制,并随时可以根据业务需求的变化,调整应用系统的功能。
l 通用性:
标准化,支持行业标准和通用接口。
l 集成性:
强大的系统整合能力,实现不同系统之间及相同系统中统一身份通验证、统一用户管理、统一权限设置、统一业务流程,保证系统间的信息流转通畅、规范、僦各资源数据库的整体解决方案有机融合。满足用户系统集成、消除信息孤岛。
l 开放性:
全面支持J2EE标准、XML标准规范和各种应用服务器技术,为用户提供优秀的扩展性、跨应用和跨平台,具有更完善的开放性。
l 安全性:
提供了强大的组织机构以及权限管理能力,为用户的网络应用安全保驾护航。
l 易用性:
采用标准的浏览器作为用户的操作界面,增强了易用性。使用者经过短期的培训便可掌握如何构建企业应用,迅速地为企业创造价值。
天宇Ttyu平台软件定位于为企业级应用提供基础核心技术\业务平台,为信息化建设、整合的企业\政府单位提供稳定坚实的平台软件;全力支持各行业的应用软件开发商,在不同行业领域为客户提供真正适合中国行业客户需求的应用解决方案。
技术经验能够作为技术构件沉淀下来,成熟、变化较小的、普遍使用的业务逻辑同样能够作为构件保存下来,通用业务逻辑构件作为业务构件平台的一部分积累下来,辅助开发工具,实现企业级应用开发的最大程度的灵活定制。天宇技术研究中心开发的平台产品,基于构件化思想,其丰富的功能构件可以为不同行业随需应变的提供不同的解决方案。
该平台产品的构件化思路不是简单的“搭积木”,而是以基础构件为核心、其他构件为业务插件的“主体+插件”形式,这样搭建出来的各个子系统不但健壮灵活,能有机的整合在一起,还保持了足够的灵活性和可扩展性,方便升级维护,从而保证了大型企业级应用的稳定性和高效的可扩展性。
图17-38积木式构造
l 开发快速
缩短周期、节省人力、降低成本。集成开发工具使得开发人员通过配置就能完成70%左右的工作,开发效率得到大幅度的提高。合理的分层,实现流水线分工作业,降低软件开发技术含量,软件工厂不再是梦想。
l 构件化
提供大量面向高层应用的构件,可任意组合,如同积木一般,在底层基础架构之上构建出不同行业应用产品,常用应用使用框架提供的功能,特殊应用可扩展,提供多样化解决方案。
l 系统运行的健壮性和可靠性
所有模块都经过严格测试和多年经验积累和实践检验,构建产品质量高,健壮稳定;上千用户的访问及具备失败恢复的能力;经过多个不同行业的多个项目的检验。
l 智能化
可视化操作工具,操作简便,自动处理,减少人为操作错误的可能性。
l 通用性
标准化,支持行业标准和通用接口,通用型强。
l 高扩展性
各构件之间的接口、协作方式都经过良好的设计,并在随着产品的进化而不断的得到优化;开放的可扩展性,使政企能够充分利用目前和将来在技术上的投资,通过最佳的方法来实现应用基础结构,从而降低风险;可扩展性利于降低长期运营维护成本。
l 适合企业级应用
为客户提供一个统一、简单、基于标准、易于扩充的基础软件平台,客户需要构建应用、整合应用、扩展应用,都可以在这个平台上实行。
l 良好的开放性
跨行业、跨应用和跨平台
l 良好的集成性
在以构件为基础开发的产品非常容易集成。可以使多个应用程序数据得到共享,提高应用程序的集成性。
l 构件松耦合
平台基于接口的实现,构件之间没有紧密地联系,形成构件间的松耦合,每个构件都能轻松调换,对平台没有任何影响,增强了系统的健壮性和灵活性。
当前软件行业最大的瓶颈是软件的不能重用,这需要一个基于一个统一框架的应用,提高软件复用率。
采用框架技术进行软件开发的主要特点包括:领域内的软件结构一致性好;建立更加开放的系统;重用代码大大增加,软件生产效率和质量也得到了提高;软件设计人员要专注于对领域的了解,使需求分析更充分;存储了经验,可以让那些经验丰富的人员去设计框架和领域构件,而不必限于低层编程;允许采用快速原型技术;有利于在一个项目内多人协同工作;大粒度的重用使得平均开发费用降低,开发速度加快,开发人员减少,维护费用降低,而参数化框架使得适应性、灵活性增强。
Ttyu平台适应多个行业,包括银行、烟草、税务、政府等企事业单位。技术平台总体框架如图17-39。
图17-39Ttyu平台适用多客户的技术架构
基于Ttyu框架的解决方案
天宇Ttyu框架经过多年的大型项目的锤炼和考验,已经形成了各个行业成熟的解决方案。它是基于J2EE的三层结构(表现层、业务逻辑层和数据层)框架。采用B/S架构,客户端只要采用IE即可访问系统,所以对客户端机器配置要求很低,可以充分利用现有资源。Ttyu框架包括技术框架以及业务框架和插件。技术框架包括WEB组件、JDBC组件、缓存管理、异常管理、基本工具以及扩展组件;业务框架由专业人士通过对各种权限管理模型以及当前各种组织机构的分析以及未来发展趋势的深入分析,从而集成了权限管理模型和组织机构模型以及日志管理等各个行业通用的业务模块;业务插件包括元数据、工作流、消息平台、系统集成EAI、数据集成GAI和报表组件。
l Ttyu框架系统集成
天宇的Ttyu框架的EAI、单点登录模块以及门户平台可以实现已有系统的系统集成。
l Ttyu框架数据集成
Ttyu框架的数据集成工具GAI可以安全的实现不同系统之间的数据交还。
l Ttyu框架的web组件
Ttyu框架的web组件实现数据展现的美观大方,方便易用,数据交互高性能。
l Ttyu框架的开发工具
Ttyu框架提供的代码生成机以及元数据,可以实现基本代码的根据数据结构自动生成,减少基本代码的重复编写、调试,极大提高开发进度以及规范性。
l Ttyu框架的业务服务平台
Ttyu框架的业务服务平台包括用户可以自己灵活制定的组织机构规则、灵活修改组织机构以及符合国际安全标准的基于角色控制的权限管理模块。
l Ttyu框架的工作流
Ttyu框架还提供了图形化的流程和表单定制,客户可以方便的定制表单、流程,以及启动流程。真正实现网上办公的流程化,规范化。
l Ttyu框架的灵活报表
Ttyu框架的灵活报表简单易用,用户可以灵活配置满足自己需求的报表,更方便数据分析以及辅助决策。
l Ttyu框架的移植性
Ttyu框架经过多年的大量的大型项目的锤炼,已经可以实现各种操作系统、中间件、数据库的移植,可以保证历史数据的直接使用,提高业务数据的利用率。单机以及群集的移植。可以充分利用客户现有资源进行使用,保护客户已有的软硬件投资,降低客户的成本。
l Ttyu框架的稳定性
Ttyu框架经过多年的大量的大型项目的考验,具有良好的稳定性,可以实现系统7×24小时的连续工作能力。
图17-40Ttyu平台基于框架的解决方案
图17-41Ttyu平台产品
天宇技术研究中心开发的Ttyu平台产品,基于构件化思想,以基础构件为核心、其他构件为业务插件的“主体+插件”形式,为不同行业随需应变的提供不同的解决方案。
技术的沉淀、合理的分层是平台产品专业化的保障,遵循ISO17799、ISO7498-2、RBAC、XACML、WFMC、OMG等国际化标准是平台产品优秀品质的体现。
天宇Ttyu平台产品以其构件化思路、良好的健壮性、可靠性以及人性化的易用性赢得了众多企业级应用,为客户带来了巨大的利益,同时也协助天宇在各个行业都具有强有力的竞争实力!
多年多行业大型应用的经验积累,成熟的通用模型,为系统提供稳定可靠的应用基础
采用模型驱动理念与先进的开发方法构建应用系统,增强快速实施战略部署能力整合与保护原有的信息化基础,解决“信息孤岛”,提高系统的集成、数据资源的共享,降低系统建设投入。
提供业务管理全程一体化方案,解决复杂业务管理流程的梳理、整合、实现完整业务信息及时有效的展现、管理和跟踪。
灵活的可维护、较强的用户自主性,降低业务系统变更难度,为执行力的响应提供保障。
提供了基于行业标准的业务模型,让客户能够建立灵活、可重复使用的应用关联来应对特定的行业问题。
推动信息化的长远规划,支撑业务发展与创新
Crab是一个物流报关领域SaaS应用软件,主要实现了从工厂或货运代理公司到中国海关报申报系统之间业务流程,其中主要实现了订单,申报,定箱,配车等比较复杂的功能。
就像LitwareHR一样,Crab同样利用微软新的技术来构建SaaS应用,利用多种技术去实现SaaS体系结构中的难点和要点。但与Crab与LitwareHR又有所区别,LitwareHR仅仅是一个案例程序,而Crab在第一期的产品中也将作为案例程序进行使用,但在这个发布后Crab将作为一个真正的SaaS软件进行运营。我们希望Crab不仅可以体现卓越的技术价值可以给读者带来一定的的技术参考价值,并且希望它在商业应用上也对读者有一定的参考价值.。
本案例Crab所面向读者是目前希望把原有单Tenant应用系统向Multi-Tenant类型系统进行转型的ISV的软件架构师,另外本案例中的大部分服务基于WCF进行封装,对于希望了解.NET3.0和SOA架构的程序员也有比较好的学习作用。注意:本案例的重点并不是介绍SaaS的商业模式,其重点是如何利用最近新的微软技术搭建一个Multi-Tenant的SaaS应用,并介绍如何去解决一些在SaaS应用开发中的常见问题。
这个1.0Crab的版本的应用并没有体现特别多的商业逻辑,主要是基于微软SaaS架构白皮书Multi-TenantDataArchitecture实现基于元数据的Multi-Tenant架构,Crab中只实现了SaaS应用成熟度模型的第三个层次(Configurable,Multi-Tenant-Efficient),并且利用Name-ValuePairs的模式实现了Multi-tenant的元数据架构。在1.0的版本中我们并没实现成SaaS应用成熟度模型的第四个层次(Scalable,Configurable,Multi-Tenant-Efficient),但我们会考虑在下面的Crab版本中加入第四个成熟度模型的实现。
这个案例应用是一个Web应用与一个智能客户端应用的结合。UI自定义,数据自定义等基于元数据实现的特征均在Web应用中实现,智能客户端主要实现的是用户自定义工作流的工作。该案例应用不以实现复杂的业务逻辑为目的,其主要目的是利用微软的最新技术(例如:WCF,WF,SQL2005,ADAM)等实现基于微软平台的Multi-Tenant的应用架构系统。在设计中,我们把很多模块服务设计的更加松耦合,使之成为一个通用的面向SOA的SaaS应用,同时我们会考虑在下面的Crab版本中加入新的SOA概念例如EnterpriseServiceBus等。
l 系统需求
Crab的系统要求是WindowsXPProfessionalSP2以上版本(包括WindowsXPProfessionalSP2),.NETFramework2.0和.NETFramework3.0。在编译和运行Crab之前,请确保以下系统或组件已被安装:WindowsXPProfessionalSP2或以上版本IIS5.0或以上版本SQLServer2005ExpressEdition,SQLServer2005(推荐)MicrosoftVisualStudio2005TeamEdition(推荐),或MicrosoftVisualStudio2005ProfessionalEdition.NETFramework3.0VisualStudio2005extensionfor.NETFramework3.0(WindowsWorkflowFoundation)VisualStudio2005extensionfor.NETFramework3.0(WCF),November2006CTPEnterpriseLibraryfor.NETFramework2.0活动目录应用模式(ADAM)SP1SaaS.NETAjaxv1.0
l 安装向导
1)打开Setup目录
2)运行Crab.msi(部署CrabWeb应用,CrabWCF服务,数据库和ADAM实例)
3)运行Provision.bat(创建ADAM实例和初始化信息)
要完成整个安装过程,请采用默认方式和默认值,具体请参照Readme(在Setup目录中)。
图17-42安装完成
解压缩Crab.zip,然后分别运行CrabHost.msi(部署CrabWCF服务)和CrabApp.msi(部署CrabWeb应用,数据库和ADAM实例)。要完成整个安装过程,请采用默认方式和默认值,具体请参照Readme(在Crab.zip中)。
验证部署
在安装完成之后,请验证安装是否正确。您要做以下的验证:
图17-43一个名称为SaaS的服务已经被创建
图17-44五个数据库已经被创建
下面我们将全面介绍该案例的架构设计,介绍案例的每一个模块的功能,以及模块之间如何进行交互。
l 概念逻辑视图
概念视图是对于架构关键元素和这些元素之间的关系的高层次的总览。
概念视图是一个高度概括的架构元素和关系的概括。Crab是一个基于元数据实现的Multi-Tenant物流应用软件。其中主要含一个叫CrabApp的Server端应用,提供WebAPIs给前端的WebClient和SmartClient的调用。此处要着重说明一点,很多朋友都认为SaaS指的都是Web应用,但我们说WebClient只是SaaS应用的一种形式,SmartClient应用同样适用于SaaS应用,我们在该案例中就演示了如何利用SmartClient来实现WinForm的Multi-Tenant应用。Crab的商Formatted:Indent:Firstline:0ch业逻辑主要围绕国际货运出口管理,并且结合系统特点在该系统中实现了Provisioning和Security等功能模块。
注意:Crab系统并没有实现所有的复杂的商业逻辑。Crab作为SaaS的例子,目前的版本,并不是完整的商业应用,Crab有选择地实现了一部分解决方案。
l 逻辑视图
图17-45Crab逻辑视图
Crab.Web包含了Web页面,MasterPage,用户输入验证等页面逻辑和业务逻辑的用户接口
Crab.Web.Security包含Membership和用户授权的自定义Provider。
Crab.WorkflowClient,该项目实现了基于SmartClient的Workflow设计器。
Crab.Service.Proxy包含Crab系统所有的WCF的服务的客户端代理。
Crab.Runtime.Services包含数据模型,授权,认证,Provisioning,业务流程自定义的WCF服务Crab.Business.Services包含了海运出口商业逻辑的WCF服务。
Crab.DataModel,该项目提供了元数据和实体逻辑的实现,Crab.Runtime.Services和Crab.Business.Services都需要使用Crab.DataModel。
l 实现视图
实现视图描述了类和接口在文件系统和Microsoft®VisualStudio®开发系统中是如何组织成目录,项目和程序集的。
VisualStudio源代码组织源代码中每个项目都有自己的命名空间。
图17-46源代码
源代码中每个项目都有自己的命名空间,每个项目一个命名空间和每个程序集一个命名空间。
图17-47应用场景
Contoso:Contoso是一家中型的电子产品出口加工企业,有500多个员工,该公司可以独立报关。
Fabrikam:Fabrikam是一家国际货运代理公司,该公司属于小型企业,企业只有10个员工,该公司正处于快速发展阶段。
Crab:Crab是一家独立软件提供商,该公司开发并运营Crab物流系统。
图17-48应用场景架构
Crab是一个物流应用系统。在应用底层是一个SingleInstanceMulti-Tenant的数据模型,我们采用NamePair-Value的方式进行基于元数据概念的数据存储。在Application层,我们利用了多种微软的新技术来进行设计,在处理工作流方面,我们采用WindowsWorkflowFoundation设计顺序工作流来实现该应用的主要业务逻辑;采用WindowsCommunicationFoundation进行基于通讯和数据安全的处理;采用ADAM进行对于用户账户和用户角色权限的存储;模拟一个STS(SecurityTokenService)来实现基于Directory服务的用户的认证和授权。在CrabApp中提供主要的WebAPIs提供给WebClient和SmartClient进行调用。在UI方面利用了SaaS.NET2.0中的WebParts和Themes等技术提供了灵活的设置和相对丰富的用户体验。我们同模拟两个公司Contoso和Fabrikam来模拟这个Multi-Tenant应用。其中我们会演示如何基于Tenant进行数据模型自定义,如何实现可配置的工作流,并且会根据用户权限提供不同的UI表现,提供更加良好的用户体验。通过以上场景描述,我们可以利用Crab完成两个完整的物流应用流程,从而体现Crab的整个技术架构和商业逻辑。
l 架构要点
与传统的Single–Tenant的定制化软件相比,Multi-Tenant的SaaS应用无论在架构上还是实现上都存在着不小挑战。在本段中将向大家描述在实现Multi-Tenant的技术架构中,将会遇到哪些挑战,但是由于篇幅和案例架构所限,我们不会介绍所有的挑战,只会结合Crab中的代码介绍一部份实现。
Multi-TenantArchitecture所需要面对的三头怪
我们在做Multi-Tenant应用架构的时候主要会遇到的3个挑战就是Configurability,Scalability,Multi-TenantEfficiency,我们把这三个技术挑战叫做三头怪(thethreeheadedmonster)。
1. 可配置性
在架构的应用设计中,完全灵活的配置和完全不可配置是SaaS应用架构设计的两个极端。当然,无论我们采才用哪种设计思路都会有利有弊。完全不可配置的方案可以使我们的应用实现起来比较容易,但它失去了可配置的应用可以带来的丰富用户体验。对于SaaS应用程序而言,我们有很可以进行用户自定义的内容,例如:工作流,商业规则,UI及数据模型等,我们可以通过对这些内容进行自定义的方式帮助用户提高用户体验。
2. 安全性
当我们需要为用户提供更高灵活性的时候,某些情况下用户希望可以上传自己的代码,但是我们在运行客户代码的时候需要特别注意。因为这些第三方代码可能会引入Bug和其它安全隐患。在处理客户代码的时候我们应该提供一个Sand-Box的概念模型给需要Upload自己代码的用户。只有对我们完全信任的用户才允许Upload自己代码进行运行,但即使是对完全信任的用户,我们仍旧需要通过Runtime的SecurityPolicy进行控制。
3. 资源利用的平衡
当在运营SaaS应用的时候,需要考虑CPU和I/O的服务器反应速度的等问题,特别是在我们增加扩展代码后,更加需要考虑到各租户服务的所消耗资源的平衡性,从而确保我们应用整体有良好的SLA(ServiceLevelAgreement)。
4. Provisioning
如何去运营一个高质量的SaaS应用对于ISV来说应该是个不小的挑战。如何处理像:监控,计费,结算,SLA的保障及Provisioning这些问题都不是ISV所熟悉的领域。在Crab中,我们为用户展示了一个如何在我们的ADAM和SQLServer中实现Provisioning这样的工作。
Crab中的Provisioning实现主要分为两部分,一是在ADAM中为不同的Tenant创建OU和默认用户,二是在DB中为不同Tenant生成默认的数据模板。
5. Multi-Tenant效率
在实现Multi-Tenant的应用中很重要的一个考虑就是如何最大化共享计算资源,基于这样的考虑使得在我们的设计与实现上都带来了很多复杂性。在这些挑战中我们主要需要考虑的内容有:如何保证安全性,如何进行数据存储,如何对应用进行系统优化。
图17-50时序图
l BusinessWorkflowModel
Crab的业务流程是用.NetFramework3.0WorkflowFoundation实现的。当创建出口委托单的时候,顺序工作流“ExportProcess”会被创建并启动。当ExportProcess的实例被创建之后,工作流等待Submit事件。当用户输完所有信息之后,触发Submit事件,等待经理审核,经理可选择Reject,Approve或Cancel来处理审核请求。Crab默认的工作流在Approve之后工作就运行结束。Crab提供Review和SendEmail两个基本的Activity供用户扩展工作流。
² 数据库设计
图17-51工作流数据库设计
所有的业务流程都在表格WorkflowDefinition中定义。PersistanceStore和TrackingStore是WorkflowFoundation持久化和追踪信息的数据库,在Crab系统中,这两个数据库合并到了同一个物理数据库CrabWorkflowStore中。
表17-7:CrabWorkflowStore
字段名 | 类型 | 说明 |
Id | UniqueIdentifier(notnull) | 工作流定义的唯一标识 |
TenantId | UniqueIdentifier(null) | 工作流流定义的租户。NULL表示是默认工作流。 |
WorkflowType | Int32(notnull) | 工作流类型 |
Xoml | NText(notnull) | 工作流定义 |
Rules | NText(null) | 工作流业务规则 |
² 工作流定义服务类
图17-52工作流定义服务类
表17-8WorkflowService
方法 | 说明 |
WorkflowDefinitionGetWorkflowDefinition(intworkflowType) | 获取工作流的定义。WorkflowDefinition中包含了Xoml和Rules |
VoidUpdateWorkflowDefinition(intworkflowType,stringxoml,stringrules) | 更新工作流定义 |
byte[]GetWorkflowGraphic(GuidprocessId) | 获取工作流实例的图片字节流(图片格式:png) |
byte[]GetWorkflowDefinitionGraphic(intworkflowType) | 获取工作流定义的图片字节流(图片格式:png) |
² 编辑工作流定义
在Admin/Customization/CustomizeWorkflow.SaaSx页面中,租户管理员可以查看当前的工作流定义的图片,也可以打开EditWorkflow的超链接来编辑工作流的定义。打开EditWorkflow的超链接会启动一个SmartClient的工作流编辑器。
获取工作流的定义:
publicstaticWorkflowDefinitionGetWorkflowDefinition(GuidtenantId,intworkflowType)
{
Databasedb=DatabaseFactory.CreateDatabase(Constants.Database.TenantMetadata);
using(DbCommandcommand=db.GetStoredProcCommand("crab_GetWorkflowDefinition"))
{
db.AddInParameter(command,"TenantId",DbType.Guid,tenantId);
db.AddInParameter(command,"WorkflowType",DbType.Int32,workflowType);
using(IDataReaderreader=db.ExecuteReader(command))
{
if(reader.Read())
{
WorkflowDefinitiondefinition=newWorkflowDefinition();
definition.Id=(Guid)reader["Id"];
definition.WorkflowType=(int)reader["WorkflowType"];
definition.Xoml=(string)reader["Xoml"];
definition.Rules=(string)reader["Rules"];
returndefinition;}}}
returnnull;}
然后,通过SmartClient修改完工作流之后,调用WorkflowProxy.UpdateWorkflowDefinition把Xoml和Rules更新到服务器:
publicstaticvoidUpdateWorkflowDefinition(GuidtenantId,intworkflowType,stringxoml,stringrules)
{
Databasedb=DatabaseFactory.CreateDatabase(Constants.Database.TenantMetadata);
using(DbCommandcommand=db.GetStoredProcCommand("crab_UpdateWorkflowDefinition"))
{
db.AddInParameter(command,"TenantId",DbType.Guid,tenantId);
db.AddInParameter(command,"WorkflowType",DbType.Int32,workflowType);
db.AddInParameter(command,"Xoml",DbType.String,xoml);
db.AddInParameter(command,"Rules",DbType.String,rules);
db.ExecuteNonQuery(command);}}
² 展现工作流
Crab工作流系统通过WorkflowFoundation的工作流组件WorkflowDesginerLoader来获取工作流的图片。图片以png格式保存。
获取工作流定义的图片WorkflowService.GetWorkflowDefinitionGraphic(…):
publicstaticbyte[]GetWorkflowDefinitionGraphic(GuidtenantId,intworkflowType)
{
…
using(serializationManager.CreateSession())
{
TextReaderreaderText=newStringReader(definition.Xoml);
using(XmlReaderreader=XmlReader.Create(readerText))
{
rootActivity=(Activity)serializer.Deserialize((IDesignerSerializationManager)serializationManager,reader);}}
returnViewer.GetWorkflowImageBinary(rootActivity,null);}
Viewer.GetWorkflowImageBinary的实现方式:
…
IRootDesignerrootDesigner=designerHost.GetDesigner(designerHost.RootComponent)asIRootDesigner;
if(rootDesigner!=null)
{
MemoryStreamms=newMemoryStream();
WorkflowViewworkflowView=rootDesigner.GetView(ViewTechnology.Default)asWorkflowView;
workflowView.SaveWorkflowImage(ms,ImageFormat.Png);
results=ms.GetBuffer();}
在Web页面上展现工作流,Crab新建了一个WorkflowImage.SaaSx的网页(实际上是一个动态图片),在Page_Load中把图片回送到浏览器,展现工作流的页面CustomizeWorkflow.aspx加了一个<img/>控件,把图片控件的src指向WorkflowImage.aspx。以下是WorkflowImage.aspx动态生成工作流图片的代码:
protectedvoidPage_Load(objectsender,EventArgse)
{
Response.ClearContent();
Response.ContentType="image/png";
byte[]binaries=WorkflowProxy.GetWorflowDefinitionGraphic(0);
if(binaries!=null&&binaries.Length!=0)
{
Response.AddHeader("Content-Length",binaries.Length.ToString());
Response.BinaryWrite(binaries);}
else{
Response.AddHeader("Content-Length","0");}
Response.Flush();
Response.End();}
² 创建委托单
工作流通过流程服务创建。流程服务负责启动工作流运行时。委托单通过流程服务的OpenExportProcess启动:
staticpublicGuidOpenExportProcess(GuidtenantId,ShippingExportDCdc)
{
if(GetExportProcessbyContractId(dc.Id)!=null)
returnGuid.Empty;Dictionary<string,object>parameters=newDictionary<string,object>();
parameters.Add("TenantId",tenantId);
parameters.Add("ObjectId",dc.Id);parameters.Add("Number",dc.Number);
stringtextUpn=AuthenticationLogic.GetUpnByUserId((Guid)dc.Creator);
parameters.Add("Creator",textUpn);
WorkflowDefinitionworkflowDef=WorkflowLogic.GetWorkflowDefinition(tenantId,(int)ProcessTypes.ShippingExport);
parameters.Add("InternalWorkflowType",(int)ProcessTypes.ShippingExport);
System.Xml.XmlReaderxomlReader=System.Xml.XmlReader.Create(newStringReader(workflowDef.Xoml));
System.Xml.XmlReaderrulesReader=string.IsNullOrEmpty(workflowDef.Rules)?null:
System.Xml.XmlReader.Create(newStringReader(workflowDef.Rules));
WorkflowInstanceworkflowInstance=Runtime.CreateWorkflow(xomlReader,rulesReader,parameters);
workflowInstance.Start();
RunWorkflowInScheduler(workflowInstance.InstanceId);
returnworkflowInstance.InstanceId;}
² 工作流规则
在Crab系统的Workflow模块中,支持简单的规则自定义,我们实现了自动审核的规则设置。实现方法是在ReviewActivity中加两个属性,FieldName和FieldValue,比如自动审核的条件是Fieldname=ExportSiteFieldValue=Shanghai那么当业务逻辑对象中的FieldName为ExportSite,FieldValue为Shanghai时,ReviewActivity被提交之后就会被自动审核通过。
l SmartClient认证
由于SmartClient运行在终端用户的客户端,WCF的调用要跨越互联网,这就有了安全性的问题。匿名用户可以通过匿名方式来调用WorkflowService的方法,为了解决这个问题,Crab系统为SmartClient添加了一个安全的WorkflowService的服务WorkflowServiceSC,WorkflowServiceSC和WorkflowService一样,都继承于IWorkflow,但不同的是WorkflowServiceSC的所有方法在调用前都必须进行用户验证:
if(!RequestContext.Current.IsAuthenticated)
thrownewInvalidOperationException("Insufficientprivilege!");
RequestContext.IsAuthenticated方法的实现为:
publicboolIsAuthenticated
{
get{
returnAuthenticationLogic.ValidateUser(TenantName,Username,Password);}
}
用户名,密码使用WCF扩展加载在WCF的SOAP包中,WCF扩展的配置如下:
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behaviorname="headersMapping">
<attachContext/>
</behavior>
</endpointBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<addname="attachContext"type="Crab.Runtime.Services.AttachContextBehavior,Crab.Runtime.Services,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null"/>
</behaviorExtensions>
</extensions>
</system.serviceModel>
在SOAP包被发送之前,TenantName,Username,Password被加载到WCFSOAP扩展:
classTenantHeaderInspector:IClientMessageInspector
{
….
publicobjectBeforeSendRequest(refSystem.ServiceModel.Channels.Messagerequest,System.ServiceModel.IClientChannelchannel)
{
MessageHeader<string>header=newMessageHeader<string>(TenantContext.TenantName);
request.Headers.Add(header.GetUntypedHeader(Constants.Headers.TenantNameHeaderName,Constants.Headers.TenantNameHeaderNamespace));
header=newMessageHeader<string>(TenantContext.Username);
request.Headers.Add(header.GetUntypedHeader(Constants.Headers.UsernnameHeaderName,Constants.Headers.UsernameHeaderNamespace));
header=newMessageHeader<string>(TenantContext.Password);
request.Headers.Add(header.GetUntypedHeader(Constants.Headers.PasswordHeaderName,Constants.Headers.PasswordHeaderNamespace));
returnnull;}}
}
注意:为了加强安全性,请使用HTTPS协议,这样SOAP包就可以被加密。
关于WebServicesSecurity,请参照LitwareHR的实现,LitwareHR采用了标准的WebServicesSecurity。
l Users&Roles
Crab使用ADAM(全称是ActiveDirectoryApplicationMode,即活动目录应用模式,后面简写为ADAM)存储认证和授权信息,认证的操作也由ADAM完成。身份数据库(CrabIdentity)存储租户档案信息和用户的映射信息(ID和用户名的映射)。ADAM的信息和身份数据库中的信息共同完成Crab系统的用户管理。
关于ADAM(ActiveDirectoryApplicationMode)
ADAM和ActiveDirectory使用相同的体系结构,甚至使用相同的代码库。ADAM提供与目录客户端和其它的ADAM实例进行通信的目录服务接口。ADAM为客户端提供了轻型的目录访问协议(LDAP)接口,以进行身份验证和生成目录服务请求。ADAM提供了远程过程调用(RPC)接口以与其它的ADAM服务器进行复制,以及进行管理。ADAM具有的功能有:
² 目录用户身份验证
² 执行数据请求
² 目录服务器间的数据同步
² 数据管理
ADAM不需要DNS服务或文件复制服务(FRS)。客户端可以使用运行ADAM的计算机的名称或Internet协议(IP)地址,以及ADAM实例所用的通信端口号来直接对ADAM进行寻址。由于ADAM不需要或依赖于域,因此进行ADAM复制时不需要使用FRS。图是ADAM的控制台:
数据库设计
租户档案信息和用户的影射信息存储在CrabIdentity数据库中:
图17-53工作流定义服务类
表17-9Tenant(租户表)
字段名 | 类型 | 说明 |
Id | UniqueIdentifier(notnull) | 这是租户表的主键 |
Name | Nvarchar(50)(notnull) | 这是租户的唯一名称 |
DisplayName | Nvarchar(256)(notnull) | 租户的显示名称 |
Approved | Bit(notnull) | 是否已经通过了审核,审核之后就转为正式会员 |
CreateDate | Datetime(notnull) | 创建日期 |
EndDate | Datetime(notnull) | 有效期限 |
LicenseCount | Int(notnull) | 租户可以创建的最多用户数 |
Contact | Nvarchar(50)(null) | 联系人 |
Phone | Nvarchar(50)(null) | 电话 |
Fax | Nvarchar(50)(null) | 传真 |
Mobile | Nvarchar(50)(null) | 移动电话 |
| Nvarchar(50)(null) | 邮件 |
Website | Nvarchar(50)(null) | 公司主页 |
City | Nvarchar(50)(null) | 城市 |
Address | Nvarchar(50)(null) | 联系地址 |
ZipCode | Nvarchar(50)(10) | 邮政编码 |
表17-10TenantUser(用户映射表)
字段名 | 类型 | 说明 |
Id | UniqueIdentifier(notnull) | 这是租户表的主键 |
TenantId | UniqueIdentifier(notnull) | 指向Tenant表格的Id字段的外键 |
Upn | Nvarchar(256)(notnull) | 唯一的用户名,和ADAM中的User类型的结点的UserPrincipleName |
l 服务
Crab系统封装了ProvisionService,AuthenticationService和AuthorizationService作为WCF服务。
图17-55服务
用户首先注册Tenant。调用ProvisionService.CreateTenant方法创建新的租户:
Tenanttenant=ProvisionProxy.CreateTenant(TenantName,Description,…);
后台实现:
publicboolValidateUser(stringtenantName,stringusername,stringpassword)
{
stringconnectionString=GetTenantConnectionString(tenantName);
stringupn=ToUpn(tenantName,username);
using(LdapConnectionldap=CreateNewLdapConnection(connectionString))
{
NetworkCredentialcredentials=newNetworkCredential(upn,password);
try
{
ldap.Bind(credentials);returntrue;}
catch(LdapExceptionex)
{
if(ex.ErrorCode!=0x31)
{throw;}
returnfalse;}}}
l 与ASP.NET2.0Membership的结合
Crab实现了ASP.NET2.0的MembeshipProvider和RoleProvider,在Web端使用ASP.NET2.0Membership进行认证和授权。
图17-56逻辑视图
Crab.Web.Security包含了对MembeshipProvider的封装
图17-57封装MembeshipProvider
Asp.Net2.0Membership的设计模式基于Provider模式的。Provider模式的好处是可以把数据的存储抽象出来,数据可以存储在SqlServer数据库中,也可以存储在Oracle数据库中,或者可以存储在XML文件中,只需要修改配置文件就可以确定使用什么存储方式。下图描述了Asp.NET采用的Provider模式和各个模块之间的关系:
图17-58Provider之间的关系
用户名认证:
图17-58用户名认证
用户授权:
图17-59用户授权
Web.Config配置:
<membershipdefaultProvider="TenantMembershipProvider">
<providers>
<clear/>
<addapplicationName="/"requiresUniqueEmail="false"minRequiredPasswordLength="1"minRequiredNonalphanumericCharacters="0"name="TenantMembershipProvider"type="Crab.Web.Security.WCFTenantMembershipProvider,Crab.Web.Security"/>
</providers>
</membership>
<roleManagerenabled="true"cacheRolesInCookie="true"defaultProvider="TenantRoleProvider">
<providers>
<clear/>
<addapplicationName="/"name="TenantRoleProvider"type="Crab.Web.Security.WCFTenantRoleProvider,Crab.Web.Security"/>
</providers>
</roleManager>
l 数据库设计
图17-60Metadata数据库设计
数据模型由实体预定义元数据,实体实例数据,和租户扩展元数据组成。元数据由DataNodes和DataProperties表格组成。DataNodes和DataProperties构成了数据字典,DataNodes通过ParentId连接成一棵树,DataProperties用来描述DataNodes的属性,实体和字段的定义都对应到DataNodes。NodeType用来区分DataNodes是用来描述实体还是实体的字段。每个DataNodes的行都有TenantId,TenantId为NULL代表系统预定义的元数据。TenantId不为NULL代表是用户扩展的元数据。同样,在DataProperties表格中,TenantId为NULL,代表系统预定义的节点属性,TenantId不为NULL代表某个Tenant扩展的结点属性。
在Crab系统中,我们用到了两种NodeType:Entity和EntityField。NodeType为1表示是Entity,NodeType为2代表EntityField。用户可以根据现有的框架做二次开发,定义更多的元数据类型。
表17-11DataNodes(元数据结点表)
字段名 | 类型 | 说明 |
TenantId | UniqueIdentifier(null) | 拥有元数据结点的租户 |
Id | UniqueIdentifier(notnull) | 元数据结点的唯一标识 |
ParentId | UniqueIdentifier(null) | 元数据结点的父结点 |
NodeType | Int32(notnull) | 元数据结点的类型(实体/字段) |
Name | Nvarchar(50)(notnull) | 结点的名字,(ParentId,Name)的组合必须是唯一的 |
表17-12DataProperties(元数据结点属性表)
字段名 | 类型 | 说明 |
TenantId | UniqueIdentifier(null) | 拥有结点属性的租户 |
Id | UniqueIdentifier(notnull) | 结点属性的唯一标识 |
ParentId | UniqueIdentifier(null) | 拥有属性的结点ID,这是DataNodes表的外键,指向DataNodes表的Id字段 |
PropertyType | Int32(notnull) | 这是属性的类型,(ParentId,PropertyType)的组合必须唯一 |
Value | Nvarchar(256)(null) | 属性的值 |
表17-13ExtensionValues(扩展字段值表)
字段名 | 类型 | 说明 |
RecordId | UniqueIdentifier(notnull) | 实体实例的唯一标识 |
FieldId | UniqueIdentifier(notnull) | 扩展字段的唯一标识。(RecordId,FieldId)的组合必须唯一 |
Value | Nvarchar(256)(null) | 元数据结点的父结点 |
l 向实体添加扩展字段
第一步:从表现层调用MetadataService的客户端APIMetadataProxy.AddEntityFieldDef
protectedvoidbtnAdd_Click(objectsender,EventArgse)
{
EntityFieldDefnewField=MetadataProxy.AddEntityFieldDef(
newGuid(drpDataEntities.SelectedItem.Value),
txtName.Text.Trim(),
txtCaption.Text.Trim(),
(DataTypes)int.Parse(drpDataType.SelectedItem.Value),
string.IsNullOrEmpty(txtLength.Text.Trim())?0:int.Parse(txtLength.Text.Trim()));}
第二步:MetadataService的逻辑代码
staticpublicEntityFieldDefAddEntityFieldDef(GuidentityDefId,stringfieldName,stringcaption,DataTypesdataType,intlength)
{
FieldMetadatametadata=MetadataManager.NewDataNode((int)DataNodeTypes.Field)asFieldMetadata;metadata.Initialize(
Guid.NewGuid(),fieldName,(int)DataNodeTypes.Field,entityDefId);
try
{
FieldMetadatametadata=MetadataManager.NewDataNode((int)DataNodeTypes.Field)asFieldMetadata;
metadata.Initialize(Guid.NewGuid(),fieldName,(int)DataNodeTypes.Field,entityDefId);
metadata.Caption=caption;
MetadataManager.CreateDataNode(metadata);
}
catch(Exceptionex)
{
thrownewMetadataException(ex.Message,ex);
}
returnFieldMetadataToFieldDef(metadata);
}
第三步:数据访问层
publicoverrideDataNodeCreateDataNode(DataNodenode)
{
if(node==null)thrownewArgumentNullException("node");
if(string.IsNullOrEmpty(node.Name))thrownewArgumentNullException("node.Name");
if(!CheckUnique(node.ParentId,node.Name))thrownewArgumentException("node.Name");
if(node.Id==Guid.Empty)node.Id=Guid.NewGuid();StringBuildersb=newStringBuilder();
sb.AppendLine(SqlEntityHelper<DataNode>.GenerateInsertScripts(node));
foreach(DataPropertydataPropertyinnode.Properties)sb.AppendLine(SqlEntityHelper<DataProperty>.GenerateInsertScripts(dataProperty));
stringbatchScripts=sb.ToString();
SqlHelper.ExecuteNonQuery(ConnectionString,CommandType.Text,batchScripts);
node.LoadChildNodes();
returnnode;
}
表17-14ExportContratEntity共享字段
表17-15ExportContratEntity扩展字段
l 数据模型的配置文件
configSections>
<sectionname="datamodel"type="Crab.DataModel.Configuration.DataModelSection,Crab.DataModel"/>
</configSections>
<!--Metatdataconfiguration-->
<datamodeldefaultProvider="SqlMetadataProvider">
<providers>
<addname="SqlMetadataProvider"type="Crab.DataModel.Provider.SqlMetadataProvider,Crab.DataModel"connectionStringName="TenantMetadata"/>
</providers>
<typemappings>
<clear/>
<addkey="1"type="Crab.DataModel.EntityMetadata,Crab.DataModel"/>
<addkey="2"type="Crab.DataModel.FieldMetadata,Crab.DataModel"/>
</typemappings>
</datamodel>
l Tenant视图
在Crab系统中,实体是通过元数据的描述信息生成动态的SQL脚本而获取的。实体字段元数据中包含了字段的名称和数据库表格中的列名。假设ShippingExportContract有两个扩展字段VehicleNo和BoxNo,假设字段VehicleNo的Id为Id0,BoxNo的Id为Id1,Tenant的Id为T1,那么生成的查询实体ShippingExportContract的脚本如下:
那么生成的查询实体ShippingExportContract的脚本如下:
SELECTP.IdASID,P.NumberASNumber,E0.ValueASVehicleNo,E1.ValueASBoxNo
FROMShippingExportContractASP
LEFTOUTERJOINExtensionValuesASE0ANDE0.FieldId=Id0
ONP.Id=E0.RecordIdLEFTOUTERJOINExtensionValuesASE1ANDE1.FieldId=Id1ONP.Id=E1.RecordId
WHEREP.TenantId=T1
如果要实现Tenant视图(Tenant只能看见属于自己的实体),需要在WHERE字句中加入:P.TenantId=…
这种方式比较简单,但缺点是SQL脚本需要动态生成,执行效率较低,而且查询语句一定要加入TenantId作为过滤条件来实现Tenant视图。另一种方式是在添加/删除自定义字段的时候创建/修改View,假设Tenant的名字为Contoso,创建视图的语句如下:
CREATEVIEWShippingExportContract_ContosoAS
SELECTP.IdASID,P.NumberASNumber,E0.ValueASVehicleNo,E1.ValueASBoxNoFROMShippingExportContractASP
LEFTOUTERJOINExtensionValuesASE0ANDE0.FieldId=Id0ONP.Id=E0.RecordId
LEFTOUTERJOINExtensionValuesASE1ANDE1.FieldId=Id1ONP.Id=E1.RecordId
WHEREP.TenantId=T1
之后TenantContoso所有查询实体ShippingExportContract的操作都可以直接查询视图ShippingExportContract_Contoso。这种方式的优点是比第一种方式安全,不会因为漏写了Tenant过滤条件而导致查询到了其它的Tenant的信息,另外不需要没次动态生成查询语句,效率较高。缺点是每次添加/删除自定义字段都要执行数据库DDL语句,在数据中建立了太多了Tenant相关的视图会导致数据库的架构过于复杂。
本章通过四个实例详细地阐述了SaaS开发的整个过程。SaaS开发包括SaaS平台,SaaS业务系统。订票服务系统、销售管理系统、Crab偏重于业务系统的开发,天宇Ttyu平台则主要是平台的开发。
理论与实际相结合,是解决问题的最佳方法。我们应该撑握扎实的理论知识,但绝对要有动手的能力,实战是至关重要的。不公司公司有不同的产品,有不同的开发技术、不同的开发模式、不同的业务范畴,天底下没有哪个产品是最牛的,但每个产品又各有自己特色,我们可学之应用,取长补短,最终开发出最佳的产品来。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。