ASP.NET环境下WEB站点的构建--浪费时间

ASP.NET环境下WEB站点的构建

       1999年,华盛顿的Wrox会议厅,ASP.NET这一革命性的产品正在做现场演示,场内的观众表现出浓厚的兴趣。20007月,ASP.NETPDC迎来了它的首次公开发布,在那里约6000名开发人员感受到了.NET所带来的强烈震撼。

       ASP.NET相对于ASP不仅仅是技术上的前进,更是一次思想上的革命。ASP.NET将许多原本只在那些如C++Java的高级语言上才出现的编程思想引入了WEB站点的开发,使得WEB的开发越来越“像”一个“真正的”软件的开发,也因此WEB程序员又要面对新的挑战。

       旧版的ASP 在交付用户时是没有被编译的,一直到WEB页面被访问的时候,那些程序才会以直译的方式一行一行的编译执行,并且这种编译不是永久性的,也就是说下次访问同一页面时,那些程序将会重新编译。所以如果网页程序太复杂或是浏览人数变多,或是服务器负载变重,其执行的效率可想而知。ASP.NET 为了改善执行的效率,以及让程序将来可跨平台执行,所以便设计了ILIntermediate Language 以及JITJust In Time 编译器。IL 这种架构非常接近机器码,可以非常有效率的透过JIT 编译器转换为机器码;而透过JIT 编译器所编译出来的机器码再经由CLRCommon Language Runtime)管理后便可让CPU执行。CLR是各种RRuntime)的整合,CLR架构在操作系统的服务上,它负责应用程序实际的执行,满足所有的应用程序的需求;例如内存管理、处理安全问题、整合不同的程序语言等等。读者也许有点糊涂:Runtime 是干什么的?为什么要把它们整合成CLR呢?事实上如果我们想要执行由某种特定程序语言所开发出来的程序,计算机内部必需装置这种特定程序语言的Runtime组件才可以。例如想要执行以VB 所撰写的程序,计算机内就必须有安装VBRuntime 组件(msvbvm.dll)才可执行;而其它诸如由Java 或是VC++ 等的程序语言所写成的软件,也是需要由特定的Runtime 组件才能执行,这些Runtime是不一样的。在ASP.NET里程序员将会使用多种语言编写程序,也就是说程序的执行需要多种Runtime,于是Microsoft将这些Rutime整合在一起形成了CLR。在IL中有许多广泛的指令,不但包括对象的加载、排序、初始、以及方法呼叫的指令,而且还有算数暨逻辑运算、流程控制、直接内存存取,以及例外处理的指令。不过因为每个CPU 的架构都不一样,所以IL 不能够直接执行;必需透过JIT 编译器先转换成可以被CLR 所管理的机器码,然后CPU便可执行。只要有支持该种CPU 架构的JIT 编译器,就可以把IL 编译成可以在该CPU 架构上执行的机器码,这意味着IL 透过各种JIT编译器将可以跨平台。而IL 这种格式又非常接近机器码,直接由这种格式透过JIT 编译器编译成机器码的速度又非常的快,所以第一次执行aspx 网页时需要编译成IL 效率较差外,尔后只要aspx 网页没有异动过,就只要从IL 透过JIT 编译器编译成机器码就可以执行,效率当然比以前的ASP 网页以直译器来执行的效率提升许多。编译成IL 也有另外一个好处,那就是只要该种程序语言可以被编译成IL,就可以由JIT 编译器编译执行。所以不管该组件用VBC#Java 或其它语言所写成的,都可以被结合在一起使用。

       可以说正是这种新的编译方式的引入,使得WEB程序的编写产生了革命性的变化。而随着编译方式的改变,程序员在编写程序时也不得不与时俱进。任何一个成型的软件至少要包括三部分:数据存取,业务逻辑,用户界面,WEB站点当然也不例外。Microsoft(和其他公司)正大力提倡一种叫做“三层应用程序设计”的编程方式,更正式的讲应该是“n层应用程序设计。这意味着每个应用程序都有代码“层”,每层都只与其周围的层进行通信。三层应用程序设计的各层如下所示:

l         数据层――包含数据源和存储过程,以及数据访问代码。数据源可以是任何一种类型,例如数据库、XML文件、Excel工作表格,甚至是包含数据的文本文件。

l         业务层――包含业务逻辑――定义这个系统的唯一功能的方法,将这些工作从其他层中抽象出来。这有时被叫作“中间层”。它包含用于查询数据库、管理检索到的数据、把数据传送给用户界面、处理UI上的任何输入的所有代码。

l         表示层――提供用户界面,由所有的用户界面代码组成,包括静态HTML、用户控件和服务器控件。


采用三层应用程序设计的方式来编写
WEB站点的优点是显而易见的。层次的分离使得分工合作得以实现,使得代码维护变得简便,使得程序复用率得以提高,所以一个WEB程序员所应该关心的正是如何去编写这三个层面。

       首先让我们来看看数据层。数据层的首要任务当然是建立数据库,数据库中将会存储大量的信息,正是由于这些信息我们才能做出动态网页(Active Server Page)。那么数据库中一般存储哪些东西呢?假设我们要做一个网上拍卖站点(以下简称Bid),那么我们至少要获取两种信息,商品(Item)信息和商人(Person)信息,这些信息当然要存储,并且经常需要修改,显然最好的管理方式是把它们放入数据库之中。一般情况下,我们会采用SQL ServerAccess作为数据库管理系统(DBMS)。而那些数据将会以实体的模式存入数据库中,实体是指我们所处理的实际事物或者概念的模型。我们会为那个拍卖站点Bid建立一个数据库,在这个数据库中建立两个表ItemPerson,它们分别为商品和商人的模型,也即是数据库中的实体。每个实体都是若干属性的集合。对于Person我们感兴趣的属性有person的姓名,性别,地址,证件号码等等。我们将会在每一个表中建立若干字段,这些字段将会与属性相对应,正是这些字段描述了我们所需要的信息,而我们所要做的就是利用程序不断的将这些信息提取出来,或者存储进去。

       在数据层中我们除了建立数据库,还可以编写一些数据访问代码,它们以用SQL语句编写的存储过程的形式放在数据库中。但是问题产生了,因为这些SQL语句既可以放在数据库中,也可以放在业务层逻辑中。那么它们到底应该放在哪里呢?这将导致一个问题,数据层究竟在哪里结束,而业务层又在哪里开始?我们看一下这些SQL语句放在不同的层次里会导致怎样的后果。如果SQL语句以存储过程的形式放在数据库中,那么整个站点的性能将得以提高,因为我们将不需要通过网络传递大量的SQL代码,并且由于它们放在数据库管理系统之中,数据库管理系统将会对它们进行编译和优化,从而在程序执行时节约大量时间。另外由于存储过程在数据库中是相对独立的,所以我们可以对这个独立部分进行有效控制,加强它的安全性。如果将SQL语句放在业务层中,它们将和逻辑代码混在一起,我们无法进行特殊的控制。但是这样做的话,那些程序就变得易于移植。因为根据实际的需要,我们可能要更换数据库管理系统,在更换时,存储过程的兼容性比较低,而SQL语句确是处处可用的。所以如果我们把SQL语句放入业务层,我们将不必在更换数据库管理系统时做大量的修改工作。至于究竟怎样划分那就看我们的需要了。是否能快速的移植到其他数据库服务器产品更重要,还是是否有更好的性能更重要?如果是前者,那么把大部分功能放在业务层是更好的选择,反之则放在数据层。

       做完了数据层,我们跳过业务层,先来看看显示层。显示层在最终用户面前呈现的是一个个丰富多彩WEB页面,用户通过它来进行人机交互,用户在这个页面上获取需要的信息,并根据要求输入自己的信息。显示层页面一般以aspx文件的形式存储于服务器的硬盘之中,用户可以通过在浏览器的地址栏里输入特定的地址或点击已有的页面上的超级链接来向服务器索要特定的WEB页面。我们需要编写HTML代码并加入各种各样的控件,对于HTML代码我想大家都不陌生。HTML是一种描述性语言,它的作用是格式化程序员想要在页面上显示的信息。比如我想让一段文字显示为红色,另一段显示为蓝色,那么我就要使用HTML把那段文字格式化。

       ASP.NET中,控件肩负了各种各样的功能,控件主要分为三类:HTML服务器控件,WEB服务器控件,和用户控件。其中HTML服务器控件是HTML 标注的对象化,使得程序编写方式更有利于三层应用程序设计。而功能更多的是WEB服务器控件,WEB服务器控件包括了HTML服务器控件的所有功能,只是使用时较为复杂。Microsoft是一个很贴心的企业,它不想让程序员一下子变化太大,所以在提供功能强大的WEB服务器控件的同时也提供了与ASP时代联系较为紧密的HTML服务器控件。WEB服务器控件除了具有传统的ASP控件(HTML表单组件)所具有的数据输入功能之外,更重要的是具有数据绑定和数据验证功能。

       假设在我们的Bid网站中我们需要每位person的姓名与性别。我们编写如下页面:

<html>

<form id="Form1" method="post" runat="server">

姓名:

<asp:TextBox ID="txtEmail" Runat="server" /><br>

性别:

<asp:dropdownlist id="sex" Runat="server"/>

</form>

</html>

<Script Language="C#" Runat="Server">

private void Page_Load(object sender, System.EventArgs e)

{

string[] SexArray = new string[] {"Male","Female"};

sex.DataSource = SexArray;

sex.DataBind();

}

</Script>

我们可以看到,在程序中我们创建了两个WEB服务器控件,分别为textbox(文本框)与dropdownlist(下拉框),前者用于获取用户姓名,后者获取性别。函数Page_Load会在页面加载时自动执行。在这个函数中我们首先定义了一个字符串数组SexArray用于存储性别类型。然后我们使用WEB服务器控件的数据绑定功能,将IDsexdropdownlist的数据源设置为数组SexArray。这样在页面加载后那个dropdownlist的下拉选项就被设置为MaleFemal。在这里我们为了简单化,没有使用那些复杂但相对于ASP方式却非常简单的并且高效的控件。比如我们可以使用Datagrid控件将数据库中的整个表的数据显示出来,并且将修改,删除,分页结合在一起。这些操作如果放在ASP当中将是一个庞大的工程,但是到了ASP.NET,这一切都变得唾手可得。在上面的程序之中,我们还可以添加一个验证控件RequiredFieldValidator来验证用户输入数据的有效性,限于文章篇幅此处不再多提。

       我们除了可以使用Microsoft给我们提供的控件,还可以自己创建一些控件。也许读者会以为自己创建控件是一件复杂的事情,其实在这里,Microsoft偷换了一个概念。ASP.NET小组刚提出用户控件的概念时,它的英文名为pagelet(小页面),可惜很多人不喜欢这个名字,于是Microsoft把它的名字改成了User Control(用户控件)。其实pagelet对用户控件进行了很好的描述。假设我们想在我们的Bid网站的每个页面上放置一些我们公司的联系方式,不同页面上的联系方式当然是一样的,那么我们需要在每一个页面上重复的编写这些联系方式的代码吗?当然不需要。我们只要为这些联系方式编写一个单独的页面,即aspx页面,然后将文件类型改为ascx,这样它就成了用户控件。最后我们在那些需要显示联系方式的页面里引用这个用户控件,我们就可以轻松的完成了任务。所以请记住,用户控件就是包含在大页面中的小页面。

       好,现在激动人心的时刻到了,我们将要投入到业务层的工作之中。可以说业务层是整个WEB站点的枢纽,业务层要完成几乎所有的逻辑功能,它需要对用户的输入进行处理,它需要把用户需要的信息提供出来,它需要完成客户端与服务端的交互,一句话它需要完成各种各样的事情。业务层作为程序枢纽,我们可以想像它必定包含着两面,分别与表示层数据层进行连接。

ASP.NET中有一个重要的概念:后台编码。每一个用于页面显示的aspx文件都有且仅有一个后台编码文件。如果我们使用C#作为脚本语言,那后台编码文件即为cs文件,如果使用VB.NET则是vb文件。所有在aspx文件中用于显示的控件,HTML标记,我们都可以在后台编码文件之中对它们的外观,内容,触发事件进行控制。在上面的示例程序中我们看到有一段Script代码,其实在正规的编程方式下,那些代码将被放入后台编码文件中。后台编码便是业务层与显示层的接口。下面我们将会看到后台编码事实上还担负着动态的逻辑处理。

由于ASP.NET引入了面向对像的思想,所以我们可以建立一个个的类库用于操作数据库,它们便是应用层与数据层的接口。类库,顾名思义,它是各个类的集合。在数据层我们曾讲到,我们为每个实体建立一个表,相对应的,我们在类库中为每个实体建立一个类,对应于那些在数据表中的字段我们为每个类设置相应的成员变量,也就是属性。而这些类的成员函数,也就是方法,就是操作数据库的具体动作。正如前面所言我们可以把具体的SQL语句放入这些成员函数之中,也可以把它们以存储过程的形式放在数据库中,但是有一点是不变的,那就是那些函数将会对数据库进行操作。

好,现在就让我们按照上面的论述来为Bid站点的person表建立相应的类。使用C#的伪代码如下:

public class Person

              {

                     public Int32 ID;

                     public string Name;

                     public string sex;

                     public Person()

                     {

                     //构造函数,一般为空

                     }

                     public void ADDPerson()

                     {

                     //向数据库中添加记录

                     }

                     public void SELPerson()

                     {

                     //以某种方式查询数据库

                     }

              ……

              }

这些类是以静态的方式存在于类库之中的。当用户的信息需要和数据库进行交互的时候,我们就可以在后台编码文件中将这些类实例化,然后调用类的函数与成员变量完成我们需要的操作和返回需要的结果。假设一个新的Person已经在显示层界面上填写好了他的信息,我们需要把这些信息加入到数据库中去,那么我们可以在后台编码文件中加入下面两行程序:

Person newperson = new Person();

newperson. ADDPerson();

在第一行程序之中我们实例化了Person,然后在第二行中调用ADDPerson方法操作数据库将信息存进去。于是这三个层次完美无缺地结合在了一起!我们不得不感叹技术的先进与科学的伟大。

 

 

posted on 2004-04-14 20:36  flybeyond  阅读(1722)  评论(1)    收藏  举报

导航