`
ihuashao
  • 浏览: 4711650 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

对“三层结构”的深入理解——怎样才算是一个符合“三层结构”的Web应用程序?

阅读更多

“三层结构”是什么?

  “三层结构”一词中的“三层”是指:“表现层”、“中间业务层”、“数据访问层”。其中:

n 表 现 层:位于最外层(最上层),离用户最近。用于显示数据和接收用户输入的数据,为用户提供一种交互式操作的界面。

n 中间业务层:负责处理用户输入的信息,或者是将这些信息发送给数据访问层进行保存,或者是调用数据访问层中的函数再次读出这些数据。中间业务层也可以包括一些对“商业逻辑”描述代码在里面。

n 数据访问层:仅实现对数据的保存和读取操作。数据访问,可以访问数据库系统、二进制文件、文本文档或是XML文档。

<shapetype id="_x0000_t75" stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600"><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-family: 'Times New Roman'; mso-fareast-font-family: 宋体; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><shapetype id="_x0000_t75" stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600"><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/Dream6000/1.GIF"><stroke joinstyle="miter"></stroke><formulas><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></formulas><path o:connecttype="rect" gradientshapeok="t" o:extrusionok="f"></path><lock aspectratio="t" v:ext="edit"></lock></shapetype><shape id="_x0000_i1025" style="WIDTH: 274.5pt; HEIGHT: 149.25pt" o:ole="" type="#_x0000_t75"><imagedata o:title="" src="file:///C:%5CDOCUME~1%5CDREAM6~1%5CLOCALS~1%5CTemp%5Cmsohtml1%5C01%5Cclip_image001.emz"></imagedata></shape></span><stroke joinstyle="miter"></stroke><formulas><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></formulas><path o:connecttype="rect" gradientshapeok="t" o:extrusionok="f"></path><lock aspectratio="t" v:ext="edit"></lock></shapetype><shape id="_x0000_i1025" style="WIDTH: 274.5pt; HEIGHT: 149.25pt" o:ole="" type="#_x0000_t75"><imagedata o:title="" src="file:///C:%5CDOCUME~1%5CDREAM6~1%5CLOCALS~1%5CTemp%5Cmsohtml1%5C01%5Cclip_image001.emz"></imagedata></shape>

<shapetype id="_x0000_t75" stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600"><stroke joinstyle="miter"></stroke><formulas><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></formulas><path o:connecttype="rect" gradientshapeok="t" o:extrusionok="f"></path><lock aspectratio="t" v:ext="edit"></lock></shapetype><shape id="_x0000_i1025" style="WIDTH: 274.5pt; HEIGHT: 149.25pt" o:ole="" type="#_x0000_t75"><imagedata o:title="" src="file:///C:%5CDOCUME~1%5CDREAM6~1%5CLOCALS~1%5CTemp%5Cmsohtml1%5C01%5Cclip_image001.emz"></imagedata></shape>

  对依赖方向的研究将是本文的重点,数值返回方向基本上是没有变化的。


在一个

  如果只以分层的设计角度看,Duwamish7要比PetShop3.0复杂一些!而如果较为全面的比较二者,PetShop3.0则显得比较复杂。但我们先不讨论这些,对PetShop3.0Duwamish7的研究,并不是本文的重点。现在的问题就是:既然“三层结构”已经被分派到各自的项目中,那么剩下来的项目是做什么的呢?例如PetShop3.0中的“Model”、“IDAL”、“DALFactory”这三个项目,再例如Duwamish7中的“Common”项目,还有就是在Bincess.CN彬月论坛中的“Classes”、“DbTask”、这两个项目。它们究竟是做什么用的呢?

对“三层结构”的深入理解——从一家小餐馆说起

  一个“三层结构”的Web应用程序,就好象是一家小餐馆。

n 表 现 层,所有的.aspx页面就好像是这家餐馆的菜谱。

n 中间业务层,就像是餐馆的服务生。

n 数据访问层,就像是餐馆的大厨师傅。

n 而我们这些网站浏览者,就是去餐馆吃饭的吃客了……

<shape id="_x0000_i1032" style="WIDTH: 217.5pt; HEIGHT: 229.5pt" o:ole="" type="#_x0000_t75"><imagedata o:title="" src="file:///C:%5CDOCUME~1%5CDREAM6~1%5CLOCALS~1%5CTemp%5Cmsohtml1%5C01%5Cclip_image021.emz"></imagedata></shape>

我们去一家餐馆吃饭,首先得看他们的菜谱,然后唤来服务生,告诉他我们想要吃的菜肴。服务生记下来以后,便会马上去通知大厨师傅要烹制这些菜。大厨师傅收到通知后,马上起火烧菜。过了不久,服务生便把一道一道香喷喷的、热气腾腾的美味端到我们的桌位上——

而我们访问一个基于asp.net技术的网站的时候,首先打开的是一个aspx页面。这个aspx页面的后台程序会去调用中间业务层的相应函数来获取结果。中间业务层又会去调用数据访问层的相应函数来获取结果。

为什么需要“三层结构”?——初探,就从数据库的升迁开始

一个站点中,访问数据库的程序代码散落在各个页面中,就像夜空中的星星一样繁多。这样一动百动的维护,难度可想而知。最难以忍受的是,对这种维护工作的投入,是没有任何价值的……

有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“门面模式”的应用。如果把一个网站比喻成一家大饭店,那么“门面模式”中的“门面”,就像是饭店的服务生,而一个网站的浏览者,就像是一个来宾。来宾只需要发送命令给服务生,然后服务生就会按照命令办事。至于服务生经历了多少辛苦才把事情办成?那个并不是来宾感兴趣的事情,来宾们只要求服务生尽快把自己交待事情办完。我们就把ListLWord.aspx.cs程序就看成是一个来宾发出的命令,而把新加入的LWordTask.cs程序看成是一个饭店服务生,那么来宾发出的命令就是:

“给我读出留言板数据库中的数据,填充到DataSet数据集中并显示出来!”

而服务生接到命令后,就会依照执行。而PostLWord.aspx.cs程序,让服务生做的是:

“把我的留言内容写入到数据库中!”

而服务生接到命令后,就会依照执行。这就是TraceLWord2!可以在CodePackage/TraceLWord2目录中找到——

把所有的有关数据访问的代码都放到LWordTask.cs文件里,LWordTask.cs程序文件如下:

#001 using System;

#002 using System.Data;

#003 using System.Data.OleDb; // 需要操作 Access 数据库

#004 using System.Web;

#005

#006 namespace TraceLWord2

#007 {

#008 /// <summary>

#009 /// LWordTask 数据库任务类

#010 /// </summary>

#011 public class LWordTask

#012 {

#013 // 数据库连接字符串

#014 private const string DB_CONN=@"PROVIDER=Microsoft.Jet.OLEDB.4.0;

DATA Source=C:\DbFs\TraceLWordDb.mdb";

#015

#016 /// <summary>

#017 /// 读取数据库表 LWord,并填充 DataSet 数据集

#018 /// </summary>

#019 /// <param name="ds">填充目标数据集</param>

#020 /// <param name="tableName">表名称</param>

#021 /// <returns>记录行数</returns>

#022 public int ListLWord(DataSet ds, string tableName)

#023 {

#024 string cmdText="SELECT * FROM [LWord] ORDER BY [LWordID] DESC";

#025

#026 OleDbConnection dbConn=new OleDbConnection(DB_CONN);

#027 OleDbDataAdapter dbAdp=new OleDbDataAdapter(cmdText, dbConn);

#028

#029 int count=dbAdp.Fill(ds, tableName);

#030

#031 return count;

#032 }

#033

#034 /// <summary>

#035 /// 发送留言信息到数据库

#036 /// </summary>

#037 /// <param name="textContent">留言内容</param>

#038 public void PostLWord(string textContent)

#039 {

#040 // 留言内容不能为空

#041 if(textContent==null || textContent=="")

#042 throw new Exception("留言内容为空");

#043

#044 string cmdText="INSERT INTO [LWord]([TextContent]) VALUES(@TextContent)";

#045

#046 OleDbConnection dbConn=new OleDbConnection(DB_CONN);

#047 OleDbCommand dbCmd=new OleDbCommand(cmdText, dbConn);

#048

#049 // 设置留言内容

#050 dbCmd.Parameters.Add(new OleDbParameter("@TextContent", OleDbType.LongVarWChar));

#051 dbCmd.Parameters["@TextContent"].Value=textContent;

#052

#053 try

#054 {

#055 dbConn.Open();

#056 dbCmd.ExecuteNonQuery();

#057 }

#058 catch

#059 {

#060 throw;

#061 }

#062 finally

#063 {

#064 dbConn.Close();

#065 }

#066 }

#067 }

#068 }

如果将数据库从Access 2000修改为SQL Server 2000,那么只需要修改LWordTask.cs这一个文件。如果LWordTask.cs文件太大,也可以把它切割成几个文件或“类”。如果被切割成的“类”还是很多,也可以把这些访问数据库的类放到一个新建的“项目”里。当然,原来的ListLWord.aspx.cs文件应该作以修改,LWord_DataBind函数被修改成:

...

#046 private void LWord_DataBind()

#047 {

#048 DataSet ds=new DataSet();

#049 (new LWordTask()).ListLWord(ds, @"LWordTable");

#050

#051 m_lwordListCtrl.DataSource=ds.Tables[@"LWordTable"].DefaultView;

#052 m_lwordListCtrl.DataBind();

#053 }

...

原来的PostLWord.aspx.cs文件也应作以修改,Post_ServerClick函数被修改成:

...

#048 private void Post_ServerClick(object sender, EventArgs e)

#049 {

#050 // 获取留言内容

#051 string textContent=this.m_txtContent.Value;

#052

#053 (new LWordTask()).PostLWord(textContent);

#054

#055 // 跳转到留言显示页面

#056 Response.Redirect("ListLWord.aspx", true);

#057 }

...

  从前面的程序段中可以看出,ListLWord.aspx.csPostLWord.aspx.cs这两个文件已经找不到和数据库相关的代码了。只看到一些和LWordTask类有关系的代码,这就符合了“设计模式”中的一种重要原则:“迪米特法则”。“迪米特法则”主要是说:让一个“类”与尽量少的其它的类发生关系。TraceLWord1中,ListLWord.aspx.cs这个类和OleDbConnectionOleDbDataAdapter都发生了关系,所以它破坏了“迪米特法则”。利用一个“中间人”是“迪米特法则”解决问题的办法,这也是“门面模式”必须遵循的原则。下面就引出这个LWordTask门面类的示意图:

<shape id="_x0000_i1036" style="WIDTH: 484.5pt; HEIGHT: 126pt" o:ole="" type="#_x0000_t75"><imagedata o:title="" src="file:///C:%5CDOCUME~1%5CDREAM6~1%5CLOCALS~1%5CTemp%5Cmsohtml1%5C01%5Cclip_image003.emz"></imagedata></shape>

ListLWord.aspx.csPostLWord.aspx.cs两个文件对数据库的访问,全部委托LWordTask类这个“中间人”来办理。利用“门面模式”,将页面类和数据库类进行隔离。这样就作到了页面类不依赖于数据库的效果。以一段比较简单的代码来描述这三个程序的关系:

public class ListLWord

{

private void LWord_DataBind()

{

<oval id="_x0000_s1028" style="MARGIN-TOP: 0px; Z-INDEX: 3; LEFT: 0px; MARGIN-LEFT: 26.25pt; WIDTH: 220.5pt; POSITION: absolute; HEIGHT: 15.6pt; TEXT-ALIGN: left" filled="f" strokeweight="1.5pt" strokecolor="red"><font face="Courier New"></font></oval> (new LWordTask()).ListLWord( ... );

<stroke endarrowlength="long" endarrowwidth="wide" endarrow="open" dashstyle="dash"><font face="Courier New"></font></stroke> }

}

public class PostLWord

{

private void Post_ServerClick(object sender, EventArgs e)

{

<oval id="_x0000_s1029" style="MARGIN-TOP: 0px; Z-INDEX: 4; LEFT: 0px; MARGIN-LEFT: 26.25pt; WIDTH: 220.5pt; POSITION: absolute; HEIGHT: 15.6pt; TEXT-ALIGN: left" filled="f" strokeweight="1.5pt" strokecolor="red"><font face="Courier New"></font></oval> (new LWordTask()).PostLWord( ... );

<stroke endarrowlength="long" endarrowwidth="wide" endarrow="open" dashstyle="dash"><font face="Courier New"></font></stroke> }

}

public class LWordTask

{

public DataSet ListLWord(DataSet ds)...

public void PostLWord(string textContent)...

}


应用中间业务层,实现“三层结构”

前面这种分离数据访问代码的形式,可以说是一种“三层结构”的简化形式。因为它没有“中间业务层”也可以称呼它为“二层结构”。一个真正的“三层”程序,是要有“中间业务层”的,而它的作用是连接“外观层”和“数据访问层”。换句话说:“外观层”的任务先委托给“中间业务层”来办理,然后“中间业务层”再去委托“数据访问层”来办理……

那么为什么要应用“中间业务层”呢?“中间业务层”的用途有很多,例如:验证用户输入数据、缓存从数据库中读取的数据等等……但是,“中间业务层”的实际目的是将“数据访问层”的最基础的存储逻辑组合起来,形成一种业务规则。例如:“在一个购物网站中有这样的一个规则:在该网站第一次购物的用户,系统为其自动注册”。这样的业务逻辑放在中间层最合适:

<shape id="_x0000_i1037" style="WIDTH: 408.75pt; HEIGHT: 429.75pt" o:ole="" type="#_x0000_t75"><imagedata o:title="" src="file:///C:%5CDOCUME~1%5CDREAM6~1%5CLOCALS~1%5CTemp%5Cmsohtml1%5C01%5Cclip_image008.emz"></imagedata></shape>

在“数据访问层”中,最好不要出现任何“业务逻辑”!也就是说,要保证“数据访问层”的中的函数功能的原子性!即最小性和不可再分。“数据访问层”只管负责存储或读取数据就可以了。

  在新TraceLWord3中,应用了“企业级模板项目”。把原来的LWordTask.cs,并放置到一个单一的项目里,项目名称为:AccessTask。解决方案中又新建了一个名称为:InterService的项目,该项目中包含一个LWordService.cs程序文件,它便是“中间业务层”程序。

ASP.NET Web应用程序解决方案中,并不是说有aspx文件、有dll文件、还有数据库,就是“三层结构”的Web应用程序,这样的说法是不对的。也并不是说没有对数据库进行操作,就不是“三层结构”的。其实“三层结构”是功能实现上的三层。例如,在微软的ASP.NET示范实例“Duwamish7中,“表现层”被放置在“Web”项目中,“中间业务层”是放置在“BusinessFacade”项目中,“数据访问层”则是放置在“DataAccess”项目中……而在微软的另一个ASP.NET示范实例“PetShop3.0中,“表现层”被放置在“Web”项目中,“中间业务层”是放置在“BLL”项目中,而“数据访问层”则是放置在“SQLServerDAL”和“OracleDAL”两个项目中。Bincess.CN彬月论坛中,“表现层”是被放置在“WebForum”项目中,“中间业务(服
分享到:
评论

相关推荐

    ASP.NET源码——CodematicS3三层结构示例项目.zip

    总之,"ASP.NET源码——CodematicS3三层结构示例项目.zip"提供了一个宝贵的实践平台,通过研究这个项目,开发者能够深入理解ASP.NET的Web应用程序开发,尤其是三层架构的设计和实现,提升自己的专业技能。

    web应用程序——bbs论坛

    在本文中,我们将深入探讨这个BBS论坛所采用的技术栈,包括Struts、JSP、JavaScript,以及它们如何协同工作来构建一个典型的Model-View-Controller(MVC)三层架构的应用。 首先,Struts是一个开源的Java框架,主要...

    第21章学生信息管理——三层结构数据库编程.ppt

    【第21章 学生信息管理——三层结构数据库编程】 在信息技术领域,尤其是在软件开发中,学生信息管理系统是一个常见的示例,用于演示如何利用数据库处理数据。本章重点介绍了如何构建一个基于三层结构的数据库编程...

    Web程序设计——JSP

    【Web程序设计——JSP】是Web开发领域中一种重要的技术,它允许开发者在服务器端创建动态网页。...通过17819 web程序设计——JSP-电子教案,你可以系统地学习这些知识,深入理解JSP在Web开发中的应用。

    asp.net登录注册——三层架构学习

    ASP.NET是一种由微软开发的用于构建Web应用程序的框架,它基于.NET Framework,提供了一种高效、安全和可扩展的...对于初学者来说,这是一个很好的实践项目,可以帮助他们深入理解Web开发的各个方面,并提高编程技能。

    怎样搭建三层架构——三层架构的小例子

    通过学习这个三层架构的小例子,你可以深入理解各层的职责和它们之间的交互方式,从而更好地设计和实现复杂的应用程序。实践中,可以根据项目需求和团队协作情况调整和优化三层架构的具体实现。

    c# 三层结构编程.rar 附源码

    ……而在这篇文章的新作中,配合这篇文章我写了7个程序实例(TraceLWord1~TraceLWord7留言板)以帮助读者理解“三层结构”应用程序。这些程序示例可以在随带的CodePackage目录中找到——  对于那些有丰富经验的Web...

    设计模式在典型net三层架构Web程序中的应用

    ### 设计模式在典型.NET三层架构Web程序中的应用 #### 一、设计模式与.NET多层架构程序 ##### 1.1 设计模式 设计模式是软件开发中一系列被广泛认可的最佳实践,它帮助开发者解决特定类型的问题。设计模式根据其...

    MVC三层架构——超市订单管理系统

    **MVC三层架构详解** MVC(Model-View-Controller)是一种常见的软件设计模式,尤其在Web开发领域广泛应用。在超市订单管理系统中,MVC架构能够有效地分离业务逻辑、数据处理和用户界面,提高代码的可维护性和复用...

    ASP.NET源码——[CMS程序]myhome2009三层项目源码.zip

    通过对"myhome2009三层项目源码"的分析,开发者可以学习到如何在ASP.NET环境中构建一个完整的CMS系统,理解每一层的职责以及它们之间的通信机制,同时也能掌握具体的编程技术和最佳实践。这个源码对于提升ASP.NET...

    ASP.NET源码——无限级树形(三层开发)源码.zip

    在这个“ASP.NET源码——无限级树形(三层开发)源码.zip”压缩包中,包含了一个使用ASP.NET实现的无限级树形结构的示例项目。下面我们将深入探讨这个项目的相关知识点。 首先,无限级树形结构在很多应用场景中非常...

    浅谈"三层结构"

    文章中提到了一个具体的案例——留言板程序,这是一个非常典型的例子,用来说明三层结构的实际应用: 1. **表现层**:负责展示留言列表和提交留言的界面。例如,在`ListLWord.aspx`中展示了数据库中的留言记录;`...

    三层个人网站小程序(Ajax源码)

    三层个人网站小程序(Ajax) Ajax三层个人网站小程序 &lt;br&gt;DAL——数据层 IDAL——数据接口层(控制是选择什么类型的数据库) Bll——逻辑层 Model——构造模型(对应数据库字段) &lt;br&gt;功能很...

    Grails——web开发应用

    Grails 是一个基于 Java 平台的开源Web开发框架,它旨在简化Web应用程序的构建过程。Grails 采用了敏捷开发的思想,遵循“约定优于配置”(Convention Over Configuration)和“不要重复自己”(Don’t Repeat ...

    桌面应用Web化——应用接入架构

    ### 桌面应用Web化——应用接入架构 #### 一、引言 随着信息技术的飞速发展,网络已经成为现代社会不可或缺的一部分。在此背景下,软件架构的设计对于提高用户体验、降低成本及提高系统的灵活性至关重要。传统的C/...

    J2EE 三层结构讲解

    本书旨在帮助读者深入理解J2EE的三层架构模型,并通过具体的案例来阐述其核心组成部分——数据访问对象(DAO)模式的应用场景与实现细节。 #### 二、J2EE 三层架构概述 J2EE采用了一种分层架构设计思想,主要分为...

    ASP.NET源码——三层无存储过程分页Demo.zip

    在这个“ASP.NET源码——三层无存储过程分页Demo.zip”压缩包中,我们可以预见到一个使用ASP.NET技术实现的三层架构(Presentation Layer、Business Logic Layer、Data Access Layer)的无存储过程分页示例。...

Global site tag (gtag.js) - Google Analytics