![浅谈三层结构的原理与用意_第1页](http://file2.renrendoc.com/fileroot_temp3/2021-6/4/f6d7d039-093c-4b23-a454-90ace270fa11/f6d7d039-093c-4b23-a454-90ace270fa111.gif)
![浅谈三层结构的原理与用意_第2页](http://file2.renrendoc.com/fileroot_temp3/2021-6/4/f6d7d039-093c-4b23-a454-90ace270fa11/f6d7d039-093c-4b23-a454-90ace270fa112.gif)
![浅谈三层结构的原理与用意_第3页](http://file2.renrendoc.com/fileroot_temp3/2021-6/4/f6d7d039-093c-4b23-a454-90ace270fa11/f6d7d039-093c-4b23-a454-90ace270fa113.gif)
![浅谈三层结构的原理与用意_第4页](http://file2.renrendoc.com/fileroot_temp3/2021-6/4/f6d7d039-093c-4b23-a454-90ace270fa11/f6d7d039-093c-4b23-a454-90ace270fa114.gif)
![浅谈三层结构的原理与用意_第5页](http://file2.renrendoc.com/fileroot_temp3/2021-6/4/f6d7d039-093c-4b23-a454-90ace270fa11/f6d7d039-093c-4b23-a454-90ace270fa115.gif)
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、浅谈“三层结构”的原理与用意对于有经验的 Web应用程序开发人员来说,“三层结构”一词应该不会感到陌生。其实“三层结构”的开发模式 不仅仅可以应用于 Web应用程序,在其他应用领域也是可以发挥其巨大作用的。而本文主旨是阐明三层结构的原理与用意,并说明 Bin cess的三层结构的特点。J中佃尿1JJr外观层“三层结构”指的是什么?“三层结构”一词中的“三层”是指:“外观层”、“中间层”、“数据库层”。其中:外观层:位于最外层,直接呈现在用户面前。用于显示数据,并为用户提供一种交互 式的界面。中间层:负责处理用户输入的信息,或者是将这些信息发送给数据库层进行保存,或 者是调用数据库层中的函数再次
2、读出这些数据。数据库层:仅实现对数据的保存和读取操作。为什么需要“三层结构”在一个软件系统中,如果不分以层次,那么在将来的升级维护中会遇到很大的麻烦。就像一个ASP.NET网页访问数据库一样。例如在ASP.NET后台程序文件 aspx.cs中,使用OleDbConnection和OleDbCommand来处理Access 后台数据库。而当数据库服务器从Access2000升迁到 SQLServer2000的时候,我们就必须修改原来的OleDbConnection为新的SqlConnection,OleDbCommand为新的SqlCommand来适应新的数据库服务器。但问题 是对于一个大型的商
3、业网站,要进行数据库操作的并不只有一两个页面。访问数据库的代码会散落各个页面中, 就像夜空中的星星一样。这样的维护,难度可想而知。有一个比较好的解决办法,那就是将访问数据库的代码全 部都放在一个cs文件里,这样数据库服务器一旦变换,那么只需要集中修改一个cs文件就可以了。namespace Bincess/ ListBoard.aspx.cs文件public classListBoardprivate voidBoardDataBind()将原来的访问数据库的代码全部都放在DBTask.cs程序文件中,这样只要修改这一个文件就可以适应新的数据库namespace Bincess/ DBTask
4、.cspublic classDBTaskpublic voidBoardDataBind()leDbConnection dbConn=OleDbCommand dbCmd= new OleDbCommand();new OleDbConnection();定义一个DBTask类,让它来完成所有的数据库操作。那么当数public voidTopicDataBind()OleDbConnection dbConn=new OleDbConnection。;据库服务器改换时,只要集中修 改这一个文件并重新编译即可OleDbCommand dbCmd=new OleDbCommand。;重整为na
5、mespace Bincess/ ListBoard.aspx.cs文件public classListBoardprivate voidBoardDataBind()(new DBTask().BoardDataBind();namespace Bincess/ ListTopic.aspx.cs文件public classListTopicprivate void TopicDataBind()(new DBTask().TopicDataBind();当然这是一个简单的“门面模式”的应用,恐怕也是“三层结构”的最原始模型如果数据库访问代码太多,令DBTask.cs文件过大的话,可以将函数
6、功能分组,存储到其它文件里。怎样才算是一个符合“三层结构”的Web应用程序?在一个ASP.NET Web应用程序解决方案中,并不是说有aspx文件、有dll文件、还有数据库,就是“三层结构”的Web应用程序,这样的说法是不对的。也并不是说没有对数据库进行操作,即没有“数据库层”,就不是“三层结构”的。其实三层结构是功能实现上的三层:外观层,用于显示,并为用户提供交互式操作的可能中间层,服务于外观层并调用数据库层的函数。数据库层,实现数据库的存储和读出。存储目标不一定是数据库服务器,也可以是文本文档或XML文档。在微软的ASP.NET示范实例 Duwamish7中,外观层被放置在 Web项目中,
7、中间层是放置在 BusinessFacade项目 中,而数据库层则是放置在DataAccess项目中。而微软的另一个ASP.NET示范实例PetShop中,外观层被放置在 Web项目中,中间层是放置在 BLL项目中,而数据库层则是放置在SQLServerDAL和OracleDAL两个项目中。在我的彬月论坛中,外观层是被放置在Web项目中,中间层是被放置在In terService项目中,而数据库层是被放置在 AccessTask项 目中。显然PetShop要比Duwamish7复杂的多!如果先不讨论这些,那么现在的问题就是:既然三层结构已经被分派 到各自的项目中,那么剩下来的项目是做什么的呢?
8、例如 PetShop中的Model、IDAL、DALFactory这三个项目,再例如 Duwamish7中的Com mon项目,还有就是在我的论坛中的Classes、DBTask、DALFactory三个项目。它们是做什么用的呢?我想下面的文字会慢慢让你明白的。从Nokia的手机生产线说起 一个“三层结构”的 Web应用程序,就象是 Nokia公司的手机生产线。Web层就像是公司的经理,他负责洞察市场趋势,决策产品的生产。并根据市场筹策下一步计划。In terService就像是公司的管理员,他主要负责管理下层员工,传达上级布置的生产任务给员工,并将生产 结果反馈给上级Web。AccessTa
9、sk就是公司里的工人,他们主要是负责手机产品的生产装配工作,并将生产结果反馈给上级In terService。他们并不需要知道产品将销往何处,也不用关心产品销量。只要能完成任务,就可以拿到报酬。命令方向是自上而下的,而结果反馈方向则是自下而上的。根据这个图例来简要的描述彬月论坛中的留言板显示功能,那么代码应该是: Asp:Repeater id = leaveWordRepeater Runat = SERVER/ Asp:Repeater文件发岀读取留言板信息的任务/ 其后台文件是由位于 Web层的ListLeaveWord.aspx.cs/ 任务命令交由LeaveWordService 类
10、对象的List 方法去完成。usingSystem;usingSystem.Data;usingBincess .In terService;namespace Webpublic classListLeaveWord : System.Web.UI. Page/将留言视图绑定到该重复器上 protected System.Web.Ul.WebControls.Repeater leaveWordRepeater;/其他代码/ /绑定留言视图/private voidLeaveWordDataBind()DataSet ds= new DataSet();new LeaveWordServic
11、e().List(ds);leaveWordRepeater.DataSource=ds.TablesLeaveWord .DefaultView;leaveWordRepeater.DataBind();/位于中间层的 LeaveWordService.cs调用下一层数据库层的方法来填充数据集/usingSystem;usingSystem.Data;usingBincess.AccessTask;namespace InterServicepublic classLeaveWordServicepublic voidList(DataSet ds)jfi*r/位于数据库层的LeaveWor
12、dDBTask.cs ,他真正完成将数据读出并将其填充到数据集中/usingSystem;usingSystem.Data;usingSystem.Data.OleDb;namespace AccessTaskpublic classLeaveWordDBTaskstring cmdText= SELECT * FROM LeaveWord”;OleDbConnection dbConn=new OleDbConnection( .);OleDbDataAdapter dbAdp=new OleDbDataAdapter(cmdText, dbConn);dbAdp.Fill(ds, Leav
13、eWord );这样便完成了对留言板的访问和显示,箭头所指的方向就是命令的方向。虽然这符合“三层结构”开发模式的思想,但是这却存在着重大的漏洞,或者说是重大缺陷!为什么会这么说呢?因为从中间层返回的结果是不安全的!而造成中间层返回结果不安全的原因是从数据库层返回的结果并不确切! 这会造成外观层过于脆弱,这并不是一个“强”三层结构。还是用代码来说明。假如, LeaveWordDBTask.cs文件中的List方法实现是这样的:/ 位于数据库层的 LeaveWordDBTask.cs 文件namespace AccessTaskpublic classLeaveWordDBTaskpublic v
14、oid List(DataSet ds)string cmdText= SELECT * FROM RegUser ;/ 注意这里,访问的不是LeaveWord 数据表OleDbConnection dbConn=new OleDbConnection( .);OleDbDataAdapter dbAdp=new OleDbDataAdapter(cmdText, dbConn);dbAdp.Fill(ds, LeaveWord );/ 但是也填充了 DataSet那么回逆到文件LeaveWordService.cs 的 List 函数,再回逆到 ListLeaveWord.aspx.cs 文
15、件的 LeaveWordDataBindContent 字段!函数。把数据绑定到重复器上,而在显示的时候,会提示:找不到 Asp:Repeater id = leaveWordRepeater Runat = SERVER- 在这里会出现错误提示出现这样的结果并不奇怪,因为数据库层访问的是RegUser数据表,而RegUser数据表中并没有定义 Content字段。外观层因此变得很脆弱,这也使得页面设计师和数据库编程人员产生了不应有的交涉。仅仅为了达到程序可运行目的,数据库编程人员就必须小心翼翼的写每句代码。这就像是NoKia公司的经理发布生产命令后,得到的返回结果却是生产线上的员工生产装配了
16、好几台电视?!这当然不是经理们想要的结果。但为什么会有这样结果呢?因为经理们在发布生产命令时,忘记说明产品的规格和特征了。经理一声令下:“生产!” 一 -(new LeaveWordService().List(DataSet ds) 但是却没有对产品的规格特征作详细说明?例如手机的型号、外观等等。 这里的ds就相当于所要生产的产品集合,但却没有作细部说明那么怎样才能避免这样荒唐的结果出现呢?经理在发布生产命令之前,应该规定产品的规格特征!ds)经理一声令下:“生产 3310 型号的手机产品! ”( new LeaveWordService().List(LeaveWordDataSet这里的
17、ds就相当于所要生产的产品集合,而且它有详细的规格说明!/ LeaveWordDataSet.cs 文件/using System;using System.Data;namespace Commonpublic classLeaveWordDataSet : DataSetpublic LeaveWordDataSet() :base ()DataTable table=new DataTable( LeaveWord ”);table.Columns.Add( Content , typeof (System.String);this.Tables.Add(table);那么原来的示意图应
18、该也发生一些变化:UTLeaveWord.DefaultView;相应的代码也要变化: Asp:Repeater id = leaveWordRepeater Runat = SERVER/ 其后台文件是由位于 Web层的ListLeaveWord.aspx.es文件发出读取留言板信息的任务/任务命令交由LeaveWordService类对象的List 方法去完成。using System;using System.Data;using Bincess .In terService;名称空间using Bincess.Common;/ 在彬月论坛中所使用的是 Bincess.Classesna
19、mespace Webpublic classListLeaveWord : System.Web.Ul.Page/将留言视图绑定到该重复器上protected System.Web.Ul.WebControls.Repeater leaveWordRepeater;/绑定留言视图,为了简明扼要省略了其他代码/private voidLeaveWordDataBind()LeaveWordDataSet ds=new LeaveWordDataSet();new LeaveWordService().List(ds);leaveWordRepeater.DataSource=ds.Tables
20、 leaveWordRepeater.DataBind();/ 位于中间层的 LeaveWordService.cs调用下一层数据库层的方法来填充数据集而用于显示留言板的控件,你可以参见PageCtrl/MessageView/LeaveWordView.ascx文件/usingSystem;usingSystem.Data;usingBincess.AccessTask;usingBincess.Common;/在彬月论坛中所使用的是Bincess.Classes名称空间namespace InterServiceLeaveWordServicepublic classnew LeaveWo
21、rdDBTask() .L ist(ds)/位于数据库层的 LeaveWordDBTask.cs他真正完成将数据读岀并将其填充到数据集中/usingSystem;usingSystem.Data;usingSystem.Data.OleDb;usingBincess.Common;/在彬月论坛中所使用的是Bincess.Classes名称空间namespace AccessTaskpublic classLeaveWordDBTaskCpublic voidList(LeaveWordDataSet ds)string cmdText= SELECT * FROM LeaveWordOleDb
22、Connection dbConn=new OleDbConnection(/ / .);OleDbDataAdapter dbAdp=new OleDbDataAdapter(cmdText, dbConn);dbAdp.Fill(ds,LeaveWord ”);这样,即便是将LeaveWordTask.List方法修改成访问 RegUser数据表的代码,也依然不会影响到外观层。再执行 期间系统会抛出异常,而这个异常信息肯定是再数据库层。再有,因为位于外观层的重复器控件绑定的是LeaveWordDataSet类对象,而LeaveWordDataSet类中就一定有 Content字段的定义。当
23、然,这同时也达到了规范数据库层返回结果的目的。这便是为什么在Duwamish7中会出现Common项目的原因。不知道你现在看明白了么?而Bin cess的做法是和PetShop 样,是通过类定义来达到同样的目的! PetShop是通过Modal项目,而Bin cess 是通过Classes项目。为了举例和易于理解, 我在上面的例子中使用了 Bi ncess.Common名称空间,但实际的Bin cess 论坛,却不是这样实现的。你可以到Classes目录中去查看代码。/ LeaveWordTask.cs 文件/ using namespace Bincess.AccessTask/ / Lea
24、veWordTask留言板数据库任务实现类/ public class LeaveWordTask : ILeaveWordTask类LeaveWordTask默认构造器/ /列表留言板内容/ / 留言板对象数组 public LeaveWord List()OleDbConnection dbConn=new OleDbConnection( .”);OleDbCommand dbCmd= new OleDbCommand(cmdText, dbConn);/其他代码/ LeaveWord.cs留言板类定义/ using System;namespace Bincess.Classes.Me
25、ssage/ / LeaveWord浏览板类/ public class LeaveWord : BaseMsg.再谈手机的装配方法在上一步中,经理说明了产品型号和规格。In terService层的LeaveWordService调用了 AccessTask层中的LeaveWordTask类List函数来获取留言数据。在 Bincess论坛中使用 Classes层LeaveWord类来规范化 Web层与AccessTask层的返回结果。那么在In terService和AccessTask之间有没有需要规范的呢?先别那么多的想法,先假设一个很现实的例子。假如,Bincess论坛的数据库要从
26、Access2000升迁到MS SqlServer 2000,那么只要集中修改AccessTask项目中的所有文件以时应新的数据库服务器即可。不过,可不可以让论坛同时支持Access又支持MS SqlServer 2000 ?通过一个开关,当开关指向Access 一端时,Bin cess就可以运行在 Access数据库平台上,而如果开关指向 MS SqlServer 2000时,Bin cess就运行在MS SqlServer数据库服务器上?这个办法很好! 但是怎 么实现呢?先在解决方案中新建一个项目就叫作:SqIServerTask。然后还有建立一个项目DALFactory充当开关。这个开关
27、项目中仅有一个 DBTaskDriver.cs文件,就用它来控制Bin cess到底运行载那个数据库平台上。/ 新建的SqlServerTask 项目,并添加一个 LeaveWordTask.cs 文件/ using System;using System.Collections;using System.Data.SqlClient;using Bincess.Classes.Message;using Bincess.Classes.User;namespace Bincess.SqlServerTask/ / LeaveWordTask留言板数据库任务实现类/ public classL
28、eaveWordTask/ /列表留言板内容/ / 留言板对象数组 /注意这里使用的是 SqlClient ,因为要对MS SqlServer数据库进行操作public LeaveWord List() SqlConnection dbConn=new SqlConnection( .);SqlCommand dbCmd= new OleDbCommand( SELECT * FROM LeaveWord, dbConn);/其他代码/ DALFactory.cs数据库层工厂类/usingSystem;usingSystem.Configuration;usingSystem.Reflecti
29、on;namespace Bincess.DALFactory/ / DBTaskDriver数据库任务驱动程序/ public classDBTaskDriver/获取程序集名称/private Assembly GetAssembly()/ 如果将字符串修改为“ Bincess.SqIServerTask”,/那么指向的就是 SqlServerTask项目,也就是要工作在MS SqlServer数据库服务器上了return Assembly.Load( Bincess.AccessTask);/ 当前指向的是 AccessTask 项目/也就是说当前是工作在Access数据库平台上/ /获
30、取留言板数据库任务对象/ / public ILeaveWordTask DriveLeaveWordTask()/ 如果将字符串修改为“ Bincess.SqIServerTask.LeaveWordTask”,/ 那么返回的就是 SqlServerTask 项目中的LeaveWordTask 类对象return(LeaveWordTask) this .GetAssembly().Createlnstance(Bincess.AccessTask.LeaveWordTask);/ 当前返回的是 AccessTask 项目中的LeaveWordTask 类对象值得一提的是,SqlServer
31、Task项目是位于数据库层的,那么就必须和AccessTask项目一样,与 Web曾保持同样的协议Classes!在In terService项目中的LeaveWordService也要改些代码:/ LeaveWordService.es留言板任务服务类/using System;using Bincess.Classes.Message;using Bincess.DALFactory;namespace Bincess .In terService/ / LeaveWordService 留言板服务类/ public classLeaveWordService/ /列表显示留言板信息/ /
32、 留言板对象数组 public LeaveWord List()return ( new DBTaskDriver().DriveLeaveWordTask().List();外观层,也就是Web项目,并不需要作任何修改到现在为止,我想你应该看到分层结构的巨大益处了吧?不过,就是在上面的程序中, 也存在一个漏洞或者说是缺陷。因为:(new DBTaskDriver().DriveLeaveWordTask()对象中不一定有会有 List成员函数。为什么呢?假如SqlServerTask项目中的LeaveWordTask.cs文件,是这样的程序代码:/ 新建的SqlServerTask 项目,并
33、添加一个 LeaveWordTask.cs 文件/using System;using System.Collections;using System.Data.SqlClient;/ 注意这里使用的是 SqlClient,因为要对MS SqlServer数据库进行操作using .|namespace Bincess.SqlServerTask/* . */public classLeaveWordTask/* . */public LeaveWord GetAII()/ 注意先前使用的是 List 函数名SqlConnection dbConn=new SqlConnection();Sq
34、lCommand dbCmd= new OleDbCommand( SELECT * FROM LeaveWord, dbConn);/其他代码那么通过DALFactory切换到SqlServer数据库时,会出现执行期错误:LeaveWordTask没有List方法。中间层因此变得很脆弱,这又使得中间层设计师和数据库编程人员产生了不应有的交涉。仅仅为了达到程序可运行目的,数据库编程人员就又必须小心翼翼的写对每个函数名。这就像是NoKia公司的管理员在传达上级的生产命令后,看到员工在装配线上,都是按照逆顺序来装配手机的?!即先将手机的面板和底壳扣紧,之后再装线 路板和按键。这当然是不可能装进去的
35、!因为正确的步骤是:先将线路板装在底壳上,然后再装上按键,最后扣 好面板但为什么会有这样结果呢?因为管理人原在传达生产命令后,忘记对手机的装配步骤作出说明!所以员工喜欢怎样装都成要使员工能够训练有素地,按照要求来装配产品,那么就必须对他们进行培训。那么用程序语言来描述这种现实活动是什么样的呢?或者说怎么描述呢?答案是使用接口!/ 新建一个 DBTask项目,并添加一个 ILeaveWordTask.cs接口类文件/using System;using Bincess.Classes.Message;namespace Bincess.DBTask/ / ILeaveWordTask留言板数据库任务接口类/ public interfaceILeaveWordTaskLeaveWord List();新建一个项目DBTask,然后添加ILeaveWordTask.cs接口类文件。请注意接下来的发生的细微变化!/ SqIServerTask 项目中的 LeaveWordTask.cs 文件/ using using Bincess.CIasses.Message;using Bincess.Classes.User;using Bincess.DBTask;namespace Bincess.SqlServerTaskpublic classLeaveWo
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 电子商务营销战略品牌打造的核心要素
- 知识产权贯标在商业运营中的应用
- 医院实习申请书
- 姓名改名申请书
- 2025年度医院儿科医疗服务承包合作协议下载
- 2025年度奶牛场有机肥料生产项目承包协议
- 2025年度建筑玻璃及装饰材料采购合同标准版
- 2025年度国际并购项目交割时间表合同
- 2025年度农民工劳务协议书范本(含劳动权益保护)
- 入股服装合同范本
- 罕见病诊治与病例管理制度
- 幼儿园开学前教职工安全培训
- 口腔接诊流程
- 东风汽车网上测评答案
- 企业员工信息安全意识培训
- 2024年新疆区公务员录用考试《行测》真题及答案解析
- 2024年单招职业技能测试题库及参考答案(基础题)
- 拘留所教育课件02
- 部编版五年级语文下册第四单元课时作业本有答案
- 机器视觉论文英文
- 出国高中成绩证明模板
评论
0/150
提交评论