《面向服务的计算和web数据管理》课件第5章_第1页
《面向服务的计算和web数据管理》课件第5章_第2页
《面向服务的计算和web数据管理》课件第5章_第3页
《面向服务的计算和web数据管理》课件第5章_第4页
《面向服务的计算和web数据管理》课件第5章_第5页
已阅读5页,还剩235页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第5章Web应用和数据管理5.1Web应用的结构

5.2Web应用模型

5.3状态管理

5.4将用户数据存到服务器文件系统

5.5高速缓存

5.6图形数据的生成和表示

5.7讨论传统桌面应用具有唯一的入口,整个应用被编译成独立的可执行文件。一个应用可包含多个类和文件,并由一个工程文件组织在一起成为一个定义良好的工程域。另一方面,Web应用包含很多页面和其他文件,可以通过任意页面进入这个Web应用,即使最常用的入口是主页面或默认页面。为了更好的满足交互性,Web应用经常是事件驱动的。由于Web服务和HTTP协议是无状态的,所以Web应用中的状态管理问题很关键,并且需要采取的技术和面向对象软件开发中的技术完全不同。

本章主要关注利用Internet上提供的已有Web服务以及应用域创建的一些本地构件来构建Web应用。

一个ASP.NetWeb站点应用包含该应用的目录以及子目录中所有文件,其中有的目录和文件是系统生成的,其他是开发者创建的。但是开发者可以编辑所有的文件,包括那些系统生成的文件。5.1Web应用的结构5.1.1Web应用的构件

ASP.NetWeb站点应用通常包含下面几种类型的文件和构件,其中有些是必需的,有些则是可选的。

(1)ASPX文件:ASPX文件采用Web格式,用于创建用户与程序交互的GUI页面。当ASPXWeb站点应用被创建时,文件Default.aspx也被生成。一个ASP.NetWeb站点至少有一个ASPX文件,开发者也可以添加更多的ASPX文件。

(2)ASCX文件:ASCX文件都通过服务器端脚本或页面后台代码创建HTML页面中的用户控件。用户控件不能创建完整的页面,但是它可以在一个或多个ASPX页面中添加(用户控件)可重用项。

(3)Web.config文件:它包含模式定义、访问控制、参数化应用的行为等配置设置。

(4)Global.asax全局应用类:包含对全局事件的事件处理,例如应用或新的会话的启动。在创建应用时,此文件放在其根目录下。

(5)DLL(动态链接库):它包含Windows环境下的通用库函数,并与.exe文件有相同的格式。在任何时候,它们都可以被计算机上运行的其他程序调用,例如,允许另外一个程序与特定设备,如打印机和键盘调用,通信程序通常被打包成DLL程序。支持特定设备操作的DLL文件被称为设备驱动程序。

(6)C#文件或者.cs文件用于页面后台的事件处理程序,用来处理诸如用户输入(鼠标点击)、程序回滚以及异常等事件。

(7)XHTML页面:是ASPX页面的标记页面。XHTML页面可由ASPX设计页面生成,也可由开发者创建。另一方面,ASPX页面可由XHTML页面生成。XHTML页面必可包含C#脚本。

应用的根目录通常包含Default.aspx、Global.asax文件、Web.config文件,以及任何其他顶层ASPX和ASCX文件。ASP.NetWeb站点应用可创建多个子目录分类存储应用生成的文件。通常来说,这些子目录包括:

(1)Bin:包含可执行码和DLL文件;

(2)App_Code:包含程序源代码,例如C#程序;

(3)App_Data:存储XML文件和数据库文件;

(4)App_WebReferences:存储添加在应用中的Web服务的引用。

最简单的Web应用只包含一个文件,它是提供用户GUI的ASPX文件。ASPX文件的计算能力是有限的。对于更复杂的应用需要多个文件,这些文件组织成为一个树形图,如图5.1。

图5.1ASP.NetWeb站点应用的组织全局文件定义之后必须放在根目录下,并且任何应用只能定义一个全局文件。任何目录下都可以定义任意数目的ASPX文件、ASCX文件和DLL文件。每个目录只定义一个Web.config文件。因为Web.config文件和应用的安全性有关,因此我们重点关注它。

ASP.Net可以创建允许进行xcopy安装的软件,也就是,可通过拖拽软件文件夹到用户选定的安装位置进行安装,删除时也只需要删除该文件夹。只要把Web.config文件放在应用软件所在的目录中,而不是放在Windows系统注册表中,就会支持XCOPY机制。Web.config文件的另一个意图是参数化应用的行为,即不用修改或者重新编译源代码就可修改行为。它本质上是一种基于策略的计算。基于策略的计算是SOA的常见特点,但是,它目前是比较活跃的研究领域,因此本书不详细讨论。

Web应用中的每个子目录都可包含Web配置文件,都起名为Web.config。Web.config文件中的设置应用于它所在的目录和所有子目录。一个目录中Web.config文件中的设置优先于(覆盖)父目录中的设置。用户可以创建子目录的Web.config文件,并用它们控制子页的设置。图5.1是一个应用域中的文件和这些文件的组织的例子。

Web.config文件受IIS保护,所以客户端不能通过浏览器浏览。任何访问文件的尝试都会收到拒绝访问的出错信息。

Web.config采用XML格式并作为简单的文本文件存储。任何文本编辑器或者XML解析器都可创建编辑Web.config文件。Web.config包含两部分数据,下面是它的基本框架:

<configuration>

<appSettings>

<!applicationsettingvaluesgohere>

</appSettings>

<system.web>

<!ASP.Netconfigurationsettingsgohere>

<system.web>

<configuration>

Web.config文件中的<appSetting>元素包含应用中的一些特定值,例如,应用访问数据库时需要的链接字符串,它允许开发者参数化应用。下面的代码将链接SQL数据库的字符串硬编码到C#程序中:

SqlDataAdapteradapter=newSqlDataAdapter("select*fromnamewhereyear=2008,"server=myServer;database=myDatabase;IntegratedSecurity=SSPI;UserID=myID;Password=MyPassWord");

DataSetrefDataSet=newDataSet();

adapter.Fill(refDataSet);这样,如果要修改,例如密码改变,会导致C#代码被修改并重新编译。最好的方式是在<appSetting>中定义链接字符串,这样使用不同的数据库时,不需要修改代码。下面的Web.config文件将和服务器相关的值放入<appSetting>元素:

<configuration>

<appSettings>

<addkey="MyConnectionString"value="server=myServer;database=myDatabase;

IntegratedSecurity=SSPI;UserID=myID;Password=MyPassWord"/>

</appSettings>

</configuration>

这样,C#代码使用路径ConfigurationSettings.appSettings和参数(关键码)MyConnectionString访问Web.config文件中的链接字符串,就像已在MSDN库中定义的字符串。

StringrefString=ConfigurationSettings.appSettings[MyConnectionString];SqlDataAdapteradapter=newSqlDataAdapter("select*fromnamewhereyear=2008",

refString);DataSetrefDataSet=newDataSet();

adapter.Fill(refDataSet);5.1.2服务控件

ASPX页面中的图形用户界面(GUI)可以通过工具箱中的服务控件来实现。服务控件是.Net类库中控制类的对象。这些控件是ASPX页面的组成部分。控件可以接收输入并由此激发事件,这样,我们可以给控件编写事件处理程序并以事件驱动方式处理输入。图形化设计视图中的控件也可以显示成XHTML格式,可以发送到客户端浏览器以显示为Web页面。ASP.Net提供了三种服务控件:Web控件、HTML控件、由用户自己定义的类创建的用户控件。

(1)HTML控件是在服务器端生成相当于HTML构件的对象,因此所有的HTML函数都可以在ASPX应用中处理。通过事件,处理程序和控件连接起来,所以,输入控制或数据都能迅速被处理。

(2)Web控件提供了传统的HTML页面中不存在的构件。这些构件比HTML控件功能更强大。

(3)用户控件:HTML控件和Web控件通过.Net类库中的类提供。如想使用库中没有提供的控件,可以创建用户控件(对象)。用户控件通过单独的ASCX页面定义,页面包含服务器端脚本或页面支持的后台代码。由于用户控件被保存为单独的XHTML文件,所以修改控件时不需要修改相关的ASPX页面。一个用户控件可以被多个ASPX页面共享。

ASPX页面和ASCX页面有两种不同的视图:(图形化)设计视图和(XHTML)源码视图。可以用两种视图开发页面。图5.2显示的是ASPX页面的设计视图。Web应用包含两个ASPX页面:Sender.aspx和Receiver.aspx。此应用中使用Web服务Encryptor进行加密和解密。

图5.2一个ASPX应用的设计视图如果在文本框中输入普通文本消息,点击“EncryptNow”按钮,加密信息就就会显示出来。例如键入“MypasswordisSuperMan1”,“EneryptedMessage”就显示“箣軈澨?蹧???竭???Ⅴ?脫(因为加密,所以显示乱码)”。如果点击按钮“SendtoReceiver”,加密信息会发送到接收页面。接收页面会自动打开。如果没有自动打开,则可以返回到应用,选择“Receiver.aspx”页面,就会执行应用(不需要调试即开始)。点击按钮“DecryptNow”,就会看见原始信息“MypasswordisSuperMan1”。下面给出ASPX页面的源码视图。

<%@PageLanguage="C#"Debug="True"AutoEventWireup="true"CodeFile="Sender.aspx.cs"Inherits="Default"%>

<!DOCTYPEhtmlPUBLIC"-//W3C//DTDXHTML1.0Transitional//EN"

"/TR/xhtml1/DTD/xhtml1transitional.dtd">

<htmlxmlns="/1999/xhtml">

<headrunat="server"><title>EncryptionSender</title>

</head>

<body>

<formid="form1"runat="server">

<p>Pleasetypeyourmessageinthetextbox</p>

<div>

<asp:TextBoxID="txtInput"runat="server"Width="616px">Pleaseentertexthere

</asp:TextBox></div>

<asp:ButtonID="btnEncrypt"runat="server"onclick="btnEncryptClick"

Text="EncryptNow"/>

<br/>

<asp:LabelID="lblEncryptedMessage"runat="server"Text="EncryptedMessage"></asp:Label>

<br/>

<asp:ButtonID="btnSend"runat="server"onclick="btnSendClick"Text="SendtoReceiver"/>

<br/></form>

</body>

</html>

XHTML的源码视图包含两个HTML控件:<headrunat=“server”>和<formrunat=“server”>,任何包含属性runat=“server”的HTML元素都是HTML控件。

XHTML的源码视图包含两个Web控件:

<asp:Buttonrunat=“server”>和<asp:Lablerunat=“server”>,任何包含限定符asp和属性runat=“server”的元素都是Web控件。关于XML和XHTML的定义,请参考第4章。

为了使这个例子可运行,我们需要以Web引用的方式把Encryptor服务添加到应用中。服务的网址为:

/WSRepository/Service/Encryption/Service.asmx

Sender.aspx页面的后台C#代码如下:

publicpartialclassDefault:System.Web.UI.Page{

protectedvoidPageLoad(objectsender,EventArgse){}

protectedvoidbtnEncryptClick(objectsender,EventArgse){

//importremoteWebservicetodothedifficultpartofthework

Encryptor.ServiceprxyEncrypt=newEncryptor.Service();

//Takethemessagefromthetextbox

stringmsg1=txtInput.Text;

//CalltheEncryptionmethodintheWebservice

stringmsgEncrypted=prxyEncrypt.Encrypt(msg1);

//Displayencryptedmessageatthepositionofthelabel

lblEncryptedMessage.Text=msgEncrypted;

//SavetheencodedmessageintoaSessionVariable‖,sothat

//theReceiver.aspxpagecanretrievethemessage

Session["msgEncoded"]=(object)msgEncrypted;

}

protectedvoidbtnSendClick(objectsender,EventArgse){

Response.Redirect("Receiver.aspx");

}

}

应用中的第二个ASPX页面是Recerver.aspx,页面的XHTML源码如下:

<%@PageLanguage="C#"AutoEventWireup="true"CodeFile="Receiver.aspx.cs"Inherits="Receiver"%>

<!DOCTYPEhtmlPUBLIC"-//W3C//DTDXHTML1.0Transitional//EN""/TR/xhtml1/DTD/xhtml1transitional.dtd">

<htmlxmlns="/1999/xhtml">

<headrunat="server">

<title>EncryptionReceiver</title>

</head>

<body>

<formid="form1"runat="server">

<div>Themessagereceived</div>

<asp:LabelID="lblMessageReceived"runat="server"></asp:Label>

<br/>

<br/><asp:ButtonID="btnDecrypt"runat="server"onclick="btnDecrypt_Click"

Text="DecrptNow"/><br/>

<asp:LabelID="lblMessageDecrypted"runat="server"Text="DecryptedMessage"></asp:Label>

</form>

</body></html>

Receiver.aspx页面的后台C#代码如下:

publicpartialclassReceiver:System.Web.UI.Page{

protectedvoidPageLoad(objectsender,EventArgse){

lblMessageReceived.Text=(string)Session["msgEncoded"];

}

protectedvoidbtnDecryptClick(objectsender,EventArgse){

//importremoteWebservicetodothedifficultpartofthework

Encryptor.ServiceprxyDecrypt=newEncryptor.Service();

//Takethemessagefromthesessionvariableusingthesameindexstring

stringmsg1=(string)Session["msgEncoded"];

//Checkifthesessionvariablecontainsanydata.

if(Session.Count==0){

//(Session.Count==0)meansnodataisstoredbythesender

lblMessageDecrypted.Text="NoMessagetoDisplay";

}

else{

//CalltheDecryptionmethodintheWebservice

stringdecrypted=prxyDecrypt.Decrypt(msg1);

//Displaythedecryptedmessageatthelabel

lblMessageDecrypted.Text=decrypted;

}

}

}通过组装GUI设计页面和C#页面,我们就得到一个可运行的应用。

这是HTML控件和Web控件的另一个例子。下面给出了常用的HTML控件列表:

<buttonrunat="server">HtmlButton<inputtype="button"runat="server">HtmlInputButton<inputtype="reset"runat="server">HtmlInputButton<inputtype="submit"runat="server">HtmlInputButton<inputtype="checkbox"runat="server">HtmllnputcheckBox<inputtype="file"runat="server">HtmlInputFile<inputtype="hidden"runat="server">HtmlInputHidden<inputtype="image"runat="server">HtmlInputImage<inputtype="radio"runat="server">HtmlInputRadioButton<inputtype="password"runat="server">HtmlInputText<inputtype="text"runat="server">HtmlInputText<arunat="server">tmlAnchor<formrunat="server">HtmlForm<selectrunat="server">HtmlSelect<tablerunat="server">HtmlTable<tdrunat="server">HtmlTableCell<thrunat="server">HtmlTableCell<trrunat="server">HtmlTableRow<textarearunat="server">HtmlTextArea<imgrunat="server">HtmlImage

.Net框架类库(FCL,FrameworkClassLibrary)实现了许多Web控件,包括下面几组控件:

●按钮控件,用于创建ASPX页面中各种类型的按钮,如前面的例子所示。

●日历控件,在ASPX页面中添加交互式日历。

●数据绑定控件,使用数据绑定显示来自数据库或其他数据源的信息。

●列表控件,显示列表项。

●简单控件,将简单HTML控件包装成Web控件。5.1.3用户控件

为了说明用户控件的应用,我们给发送页添加一个新的特征,在“SendtoReceiver”按钮下显示日期和时间。用户控件可通过下列步骤实现:

(1)选择VisualStudio菜单命令Web站点→添加新项…

(2)在弹出的窗口中选择Web用户控件。

(3)把新项命名为SenderDateTime.ascx,点击添加。用户控件将会出现在应用程序的SolutionExplorer中,如图5.3所示。图5.3用户控件被添加到Solution中(4)双击文件名SenderDateTime.ascx打开文件,出现“source”视图,在页面中添加两个名为1b1DateMsg和1blDate的标签,如下所示。

<%@ControlLanguage="C#"AutoEventWireup="true"CodeFile="SenderDateTime.

ascx.cs"Inherits="SenderDateTime"%>

<asp:LabelID="lblDateMsg"runat="server"Text="Thedateandtimeare"></asp:Label>

<asp:LabelID="lblDate"runat="server"Text=""></asp:Label>

(5)点击“design”标签,转换到设计视图,在图形视图中查看标签。

(6)双击页面的空白区域打开C#编码页,添加下列C#代码。

publicpartialclassSenderDateTime:System.Web.UI.UserControl{

protectedvoidPageLoad(objectsender,EventArgse)

{

Stringdate=DateTime.Now.ToLongDateString();

Stringtime=DateTime.Now.ToLongTimeString();this.lblDate.Text=date+","+time;

}

}现在,我们创建了用户控件。下来,我们需要将用户控件与需要控制的ASPX页面连接。要连接Sender.aspx页,需要打开XHTML源代码视图,通过添加下面代码中的第一行来注册用户控件:

<%@RegisterTagPrefix="myControl"TagName="SenderDateTime"

src="SenderDateTime.ascx"%>

然后,将下面一行代码放到Sender.aspx页面中需要显示日期和时间的位置:<myControl:SenderDateTimeID="SenderDateTime"runat="server"/>

下面给出添加了用户控件的Sender.aspx页面的完整的XHTML代码,黑体部分是添加的代码。

<%@PageLanguage="C#"Debug="True"AutoEventWireup="true"CodeFile="

Sender.

aspx.cs"Inherits="_Default"%>

<%@RegisterTagPrefix="myControl"TagName="SenderDateTime"src="SenderDateTime.ascx"%>

<!DOCTYPEhtmlPUBLIC"-//W3C//DTDXHTML1.0Transitional//EN

"/TR/xhtml1/DTD/xhtml1transitional.dtd">

<htmlxmlns="/1999/xhtml">

<headrunat="server">

<title>EncryptionSender</title>

</head><body>

<formid="form1"runat="server">

<p>Pleasetypeyourmessageinthetextbox</p>

<div>

<asp:TextBoxID="txtInput"runat="server"Width="616px">

Pleaseentertexthere</asp:TextBox>

</div>

<asp:ButtonID="btnEncrypt"runat="server"onclick="btnEncryptClick":

Text="EncryptNow"/>

<p/>

<asp:LabelID="lblEncryptedMessage"runat="server"Text="EncryptedMessage"></asp:Label>

<p/>

<asp:ButtonID="btnSend"runat="server"onclick="btnSendClick"

Text="SendtoReceiver"/>

<p/>

<myControl:SenderDateTimeID="SenderDateTime"runat="server"/>

</form>

</body>

</html>上述例子说明在ASPX页面中如何创建和包含用户控件。显然,这项功能通过Web控件“Label”,并在Sender.aspx页面后台直接添加C#代码就很容易实现。用户控件的主要优点是它的重用性。同一个用户控件可被多个ASPX页共享,而服务控件和它的后台代码绑定到一个ASPX页面,不能被共享。在上面的例子中,可为Receiver.aspx页添加相同的用户控件。5.1.4Web应用配置

VisualStudio开发环境将所有文件,包括配置文件,放在一个(根)目录下的应用域中。如果配置文件放在应用域外的系统注册表中,则安装程序必需把配置放在正确的地方。这样,创建的.Net应用就很容易安装和卸载。可以通过拖曳应用文件夹的方式将应用安装到文件系统的任何位置,卸载时只需删除这个文件夹即可。

ASP.Net应用的配置文件Web.config是XML文本文件,创建应用时其配置文件自动生成。可以使用任何标准的文本编辑器或XML解析器读写配置文件。配置文件不会被锁定,应用执行时也可以对它进行编辑。ASP.Net可以发现配置文件的改变,并对被变更影响的Web资源自动实施新的配置项,服务器端不需要重新启动。任何时候,层次结构中的配置文件一旦修改,层次配置的设置都会自动重新计算并重新载入。ASP.NetWeb应用服务器的多个目录下都会有配置文件,多个配置文件都命名为Web.config。

配置文件的作用范围是它所在的目录以及它的子目录。子目录中的配置文件除了可以应用从父目录继承的配置信息外,还可以覆盖或修改父目录中定义的设置。通过配置IIS阻止直接浏览访问配置文件,ASP.Net保护配置文件不受外来访问。任何浏览器试图直接访问配置文件,都将返回HTTP访问错误403(禁止)。下面的文件是之前讨论的加密例子中的Web.config。

<?xmlversion="1.0"?>

<!

Note:Asanalternativetohandeditingthisfileyoucanusethe

Webadmintooltoconfiguresettingsforyourapplication.Use

theWebsite>Asp.Net?ConfigurationoptioninVisualStudio.

Afulllistofsettingsandcommentscanbefoundin

machine.config.commentsusuallylocatedin

/Windows/Microsoft.Net?/Framework/v2.x/Config

><configuration>

<configSections>

<sectionGroup>

</sectionGroup>

</configSections>

<appSettings>

<addkey="Encryptor.Service"value="/WSRepository/

Services/Encryption/Service.asmx"/>

</appSettings>

<system.Web>

<!

Setcompilationdebug="true"toinsertdebugging

symbolsintothecompiledpage.Becausethis

affectsperformance,setthisvaluetotrueonly

duringdevelopment.

>

<compilationdebug="true">

<assemblies>

</assemblies>

</compilation>

<!

The<authentication>sectionenablesconfiguration

ofthesecurityauthenticationmodeusedby

ASP.Net?toidentifyanincominguser.

>

<authenticationmode="Windows"/>

<!

The<customErrors>sectionenablesconfiguration

ofwhattodoif/whenanunhandlederroroccurs

duringtheexecutionofarequest.Specifically,

itenablesdeveloperstoconfigurehtmlerrorpages

tobedisplayedinplaceofanerrorstacktrace.

<customErrorsmode="RemoteOnly"defaultRedirect="GenericErrorPage.htm">

<errorstatusCode="403"redirect="NoAccess.htm"/>

<errorstatusCode="404"redirect="FileNotFound.htm"/>

</customErrors>

>

<pages>

<controls>

</controls>

</pages>

<httpHandlers>

</httpHandlers>

<httpModules>

</httpModules>

</system.Web>

<system.codedom>

<compilers>

</compilers>

</system.codedom>

<!

Thesystem.WebServersectionisrequiredforrunningASP.Net?AJAX

underInternetInformationServices7.0.Itisnotnecessary

forpreviousversionofIIS.

>

<system.WebServer>

<validationvalidateIntegratedModeConfiguration="false"/>

<handlers>

<removename="WebServiceHandlerFactoryIntegrated"/>

<removename="ScriptHandlerFactory"/>

<removename="ScriptHandlerFactoryAppServices"/>

<removename="ScriptResource"/>

<addname="ScriptHandlerFactory"verb="*"path="*.asmx"/>

<addname="ScriptHandlerFactoryAppServices"verb="*"/>

<addname="ScriptResource"preCondition="integratedMode"/>

</handlers>

</system.WebServer>

<runtime>

<assemblyBindingxmlns="urn:schemasmicrosoftcom:asm.v1">

<dependentAssembly>

</dependentAssembly>

</assemblyBinding>

</runtime>

</configuration>

下面详细介绍一下Web.config文件。它是一个XML文件,包含许多元素。根元素是<configuration>,第一层子元素是配置文件的主要部分。

(1)<configSections>部分:包含配置文件中出现的各部分的声明,类似于程序中的变量声明,我们需要在程序的开始部分声明程序中使用的所有变量。

(2)<appSettings>部分:保存应用中特定的值(字符串),它们在运行过程可以被读取。

(3)<system.Web>部分:保存系统使用的配置(ASP.Net)。

(4)<system.codedom>部分:保存应用中使用的每一种语言编译时使用的配置。

(5)<system.WebServer>部分:保存Web服务或Web应用所在的Web服务器使用的配置。

(6)<runtime>部分:保存运行时系统相关的绑定、部署和身份验证的配置。

ASP.Net配置系统是可扩展的,可以定义新的配置部分,编写程序读取特定部分,运用数据作决策。因此,Web.config文件可以用来支持基于策略的计算。如果你喜欢,也可以使用ASP.NetWebSite管理工具编辑Web.config文件,而不是直接使用文本工具编辑XML元素。在ASP.Net菜单中,选择Website→ASP.NetConfigeration,就可以定义和编辑你关心的所有部分。

Web.config文件的部分和子部分在后面需要使用它们的章节中会继续介绍。例如,在研究安全机制的开发时,会介绍<authentication>和<authorization>元素。5.1.5全局应用类

ASP.Net提供全局应用类Glabal.asax,它包含负责处理全局事件的处理程序。全局变量可以通过形如Application[“index”]的应用状态来使用,它提供了对象数组存储全局信息。想要在应用中添加全局应用类,可右击应用文件夹,选择“AddNewItem…”,然后选择“GlobalApplicationClass”,Global.asax将会被添加到应用的根目录下。打开文件,里面包含了带有事件处理接口的模板。

下面的代码是添加几个简单事件处理的全局应用类的例子。

<%@ApplicationLanguage="C#"%><scriptrunat="server">

voidApplicationStart(objectsender,EventArgse){

//Codethatrunsonapplicationstartup

Application["SessionCounter"]=0;

}

voidApplicationEnd(objectsender,EventArgse){

//Codethatrunsonapplicationshutdown

Response.Write("<hr/>TheWebsitewaslastvisitedon"

+DateTime.Now.ToString());

}

voidApplicationError(objectsender,EventArgse){

//Codethatrunswhenanunhandlederroroccurs

}

voidSessionStart(objectsender,EventArgse){

//Codethatrunswhenanewsessionisstarted

Int32count=(Int32)Application["SessionCounter"];

count++;

Application["SessionCounter"]=count;

}

voidSessionEnd(objectsender,EventArgse){

//Codethatrunswhenasessionends.

//Note:TheSessionEndeventisraisedonlywhenthesessionstate

//modeissettoInProcintheWeb.configfile.Ifsessionmodeis

//settoStateServerorSQLServer,theeventisnotraised.

Int32count=(Int32)Application["SessionCounter"];

count;

Application["SessionCounter"]=count;

}

</script>

Web应用可以被多个用户同时访问。每次访问都打开新的会话。这些事件处理的作用是跟踪有多少个会话被同时打开。

在事件处理Application_Start()中,将应用状态变量Application[“SessionCounter”]初始化为0。当启动应用时,这个事件处理被自动调用。

在事件处理Session_Start()中,增加状态变量Application[“SessionCounter”]的值,当新的会话开始时,这个事件处理被自动调用。在事件处理Session_End()中,减少状态变量Application[“SessionCounter”]的值,当会话结束时,这个事件处理被自动调用。

这个实现中,应用重新启动时,计数器初始化为0。如果想保留打开会话的总数,可以使用另外一个应用状态变量Application[“TotalSessions”]。将此变量的值保存在包含Application_End()事件处理的硬盘文件中,在Application_Start()事件处理中恢复该变量的值。关于应用状态以及在服务器文件系统中存储应用数据等内容在本章后面的章节讨论。5.1.6动态链接库

ASP.Net提供了多种代码复用方式。前面讨论了通过创建服务或用户控件类来共享多个应用或一个应用的多个页面中的代码。创建DLL(动态链接库)类是通过类库进行代码共享的传统方法。

创建DLL类时,选择VisualStudio菜单“文件→新建→项目…”创建新的工程。然后,在VisualStudio的安装模板中,选择“类库”,将打开一个C#名字空间页面,在此可以写多个类。类创建和编译完成后,就可以在需要库功能的Web应用中通过使用“添加引用…”选项来访问这些类。一旦找到到类库的位置,并在应用中添加了库时,类的执行代码就会被载入到应用的bin文件夹中。下面的例子中,在名字空间模板中创建了两个简单类。

namespacemyLibrary{

publicclassTemperatureConversion{

publicstaticInt32getFahrenheit(Int32c){

Doublef=c*9/5+32;

returnConvert.ToInt32(f);

}

publicstaticInt32getCelsius(Int32f){

Doublec=(f-32)*5/9;

returnConvert.ToInt32(c);

}

}

publicclassmyMath{

publicstaticlongabs(longx){

if(x>=0)return(x);elsereturn(-x);

}

}

}

在应用中使用“添加引用…”添加名字空间“myLibrary”后,就可以在程序中使用类库。例如,名字空间“myLibrary”定义了类“TemperatureConcersion”,就可以使用TemperatureConcersion.getFahrenheit(Ctemp)访问类中的函数。下面的例子是用名字空间访问类库。usingmyLibrary;//YoumustusethenamespacenamedefinedinDLL

classmyApplication{

staticvoidMain(string[]args)

{

Int32Ctemp=23;

Int32Ftemp=121;

doublex=TemperatureConversion.getFahrenheit(Ctemp);//UsingDLLheredoubley=TemperatureConversion.getCelsius(Ftemp);//UsingDLLhere

System.Console.WriteLine(―Ctemp{0}isFtemp{1}",Ctemp,x);

System.Console.WriteLine(―Ftemp{0}isCtemp{1}",Ftemp,y);

}

}

Web应用是指具有计算能力的Web页。在第一代Web中,HTML语言是浏览器唯一支持的语言,而后来的浏览器支持更多的语言,包括许多脚本语言和其他计算方法。5.2Web应用模型5.2.1纯基于HTML的Web应用

纯粹的HTMLWeb页不支持计算,但是,它提供了大量的方法和格式,例如GET、POST、PUT、HEAD以及DELETE,用来发送和接收来自服务器的数据。例如,下面的代码允许用户输入数据、进行操作,并且发送数据到服务器进行计算。<html>

<body>

<form>

<inputtype="text"name="operand1"VALUE="number"/>

<inputtype="text"name="operation"VALUE="operation"/>

<inputtype="text"name="operand2"VALUE="number"/>

<inputtype="submit"value="="/>

</form>

</body>

</html>在服务器端,当有来自Web站点的请求时,一个进程被实例化以处理数据并发送结果到页面。通常情况下,在执行计算之前,程序员必须提供自己的方式来收集足够的信息、对额外的数据执行大量的字符串处理、解释数据。随着Web计算技术的进步,使用这种方式开发Web应用的人越来越少。5.2.2客户端脚本编写

在Web浏览器中增加执行脚本语言的能力,是从桌面计算转移到Web计算的重要里程碑。JavaScript是最早最广泛使用的脚本语言之一。

Netscape公司BrendanEich开发的Mocha,后来改名为LiveScript,是第一代JavaScript,被用在1995年12月发布的Netscape浏览器2.0B3中。在LiveScript发布不久后,这个流行的脚本语言以新的名字“JavaScript”出现在Netscape公司和SunMicrosystems公司的合作中;现在“JavaScript”是SunMicrosystems公司的注册商标。下列代码说明了一个带有<script>元素的HTML页面,这个<script>元素包含JavaScript函数。

<html>

<body>

<scripttype="text/JavaScript">

functionadd2Nos(){

document.sum.z.value=parseInt(document.sum.x.value)

+parseInt(document.sum.y.value)

}

</script>

<formname="sum">

<inputtype="text"name="x"size=5maxlength="5">

<inputtype="text"name="y"size=-5"maxlength="5">

<inputtype="button"value="="name="Submit"

onClick="add2Nos()"><inputtype="text"name="z"size="5"maxlength="5">

</form>

</body>

</html>可以看出,脚本程序被嵌入到HTML代码中,并被载入到客户端浏览器,脚本在浏览器中执行。这一技术被称为客户端脚本。在这个例子中,Web页面从输入表格里获取2个数字,通过调用JavaScript函数在页面执行加法,不需要和服务器进行数据通信。

随着脚本语言的流行,越来越多的脚本语言出现了,其解释器也被嵌入到Web浏览器中。许多传统的编程语言也被升级以提供脚本能力。由于规模的限制,许多脚本语言不被浏览器支持,这些脚本语言只能用于服务器端,而服务器几乎支持任何脚本语言以及传统的编程语言。按照功能和用途,脚本语言可以分为以下几种:

(1)作业控制语言和Shells,包括:IBMJCL,UnixScript以及AppleScript;

(2)GUI/可视化编程语言,包括:OracleSOASuite支持的GraphicBPEL,ActiveBPEL,MicrosoftVPL以及NationalInstrumentLabView;

(3)具体应用语言,包括:QuickC,EmacsList,用于机器人编程的ParallaxC;

(4)扩展/嵌入式语言,包括:嵌入到YahooWidgetEngine中的SpiderMonkey,AdobeFlash(ActionScript),Silverligh,TCL,Perl以及Python;

(5)Web客户端脚本,包括:AJAX,CSS,XSLT,JavaScript,ECMAScript以及VBScript;

(6)动态语言和服务器端脚本语言,包括:Java,PHP,C#和Ruby。

图5.4说明了部分编程语言以及这些语言在传统编程语言和脚本语言中所处的位置。

图5.4传统编程语言和脚本语言

客户端脚本主要的好处是在客户端浏览器完成计算,这样降低了客户端和服务器之间来回传输数据的压力,然而也存在一些弊端,包括:

(1)脚本编码需要解释。解释执行通常比编译执行慢。

(2)脚本编码无法重用。脚本不能调用另外一个网页中的脚本函数。

(3)脚本编码支持模块化但不可扩展。可以定义单个函数,但不能动态绑定和继承。

(4)安全性。一方面,允许编码在浏览器运行会给客户机带来安全隐患;

另一方面,通过浏览器的“查看源代码”功能,可以查看脚本编码,这给黑客提供了攻击的漏洞。例如,http:///watch?v=MJNJjh4jORY提供的视频显示了黑客如何通过修改脚本进入到安全系统。5.2.3服务器端脚本编写和后台代码计算

Web浏览器的计算能力受计算速度、内存大小以及存取其他资源的限制,因此客户端脚本只用于简单的计算,要想具备强大的计算能力,只能选择服务器端计算。

服务器端脚本看上去和客户端脚本类似,但是它能够解决客户端脚本存在的许多问题。下面的代码是服务器端脚本的例子,其中C#函数包含在HTML文件中。

<%@PageLanguage="C#"AutoEventWireup="true"CodeFile="Default.aspx.cs"Inherits="_Default"%><!DOCTYPEhtmlPUBLIC"-//W3C//DTDXHTML1.0Transitional//EN"

"/TR/xhtml1/DTD/xhtml1transitional.dtd">

<htmlxmlns="/1999/xhtml">

<headrunat="server">

<title>ServerScripting</title>

</head><body>

<formid="Form1"runat="Server">

<asp:TextBoxID="op1"Runat="server"/>

<asp:TextBoxID="op2"Runat="server"/>

<asp:ButtonID="Button1"Text="="OnClick="add"Runat="server"/>

<asp:LabelID="result"Runat="server"/>

</form>

</body>

</html>

<scriptlanguage="C#"runat="server">

voidadd(Objectsender,EventArgse){

Int32a=Convert.ToInt32(op1.Text);

Int32b=Convert.ToInt32(op2.Text);

result.Text=Convert.ToString(a+b);

}

</script>

然而,服务器脚本依旧有着和客户端脚本相同的问题,包括重用性、模块化和扩展性。最终解决这些问题的方法是利用服务器端计算和后台代码。将代码与用户界面分离也支持层次化体系结构的概念,即将表示与应用逻辑分离。5.1节讨论的例子使用了服务器端计算和后台代码的概念。表5.1总结了四种不同的基于Web的计算模型。本章后面的内容主要关注服务器端后台代码的计算模型,因为它是常见的较高级的Web计算模型。表5.1基于Web的计算模型

传统的过程(方法)调用会通过内容转换给进程产生一个私有的工作区,也就是调用者会置换出来,并且它的执行环境会保存在栈里。进程代码会控制工作区。当进程执行完之后,调用者的执行环境被恢复,然后从下一条指令开始执行。5.3状态管理

Web服务和Web应用与它们的调用者松散耦合。它们通过数据交换进行通信。调用者的控制流不会跳转到服务,但会发生环境切换。此外,Web服务和Web应用能同时被多个用户访问。Web服务和Web应用都是基于HTTP的,而HTTP是无状态的,即每一个包都独立于其他包。

因此,Web服务和Web应用的存储和状态管理完全不同于进程调用的模式。

默认情况下,Web服务和Web应用都是无状态的:每次我们调用一个服务或访问一个应用,它都会认为我们是一个新用户。

但是,当我们把Web作为一个新的计算平台时,很多情况下,我们都需要有状态的计算,例如购物车服务、计数器、计时器等。5.3.1状态管理技术综述

为了提供有状态的Web服务和应用,有些特殊问题需要考虑。表5.2列举了ASP.Net中不同的Web服务和Web应用状态管理方法。后面的讨论中,我们会用Web应用状态管理这一术语。讨论的技术也适用于Web服务。表5.2ASP.Net状态管理技术5.3.2视图状态

当用户访问ASPX页面时,就生成一个XHTML页面,并被发送给客户端正在运行的浏览器。当在同一个浏览器会话中多次访问一个页面时,开发者会在XHTML中一个隐藏字段里保存这个页面的信息。ASPX页面可利用语法ViewState[“name”]对这个字段进行读写,其中“name”是一个字符串索引。隐藏字段可以保存被不同名字索引的字符串集合。

为了说明视图状态变量的使用,我们设计了一个Web计算器,如图5.5所示。该应用提供了一个文本框,当输入一个数字,并且当按下“AddtoSum”按钮时,这个数字被添加到总和中。

图5.5数字25连加3次后总和是75

首先,用传统桌面编程技术把下面代码放到Default.aspx网页后台,看看会有什么结果,其中类变量sum是用来保存总和的。

usingSystem;

publicpartialclass_Default:System.Web.UI.Page{

protectedvoidPage_Load(objectsender,EventArgse){}

Int32sum=0;

protectedvoidButton1_Click(objectsender,EventArgse){

Int32newValue=Convert.ToInt32(this.TextBox1.Text);

sum=sum+newValue;

this.Label1.Text=Convert.ToString(sum);

}

}当我们执行程序并点击按钮“AddtoSum”,当前输入值将代替目前正在运行的总和值显示出来。原因是,每次访问Web页面或者每次点击这个按钮都会被视为一个新的会话,并且sum变量会被初始化为0。如果我们给类变量sum加上关键字static会出现什么情况呢?

staticint32sum=0;

在这种情况下,变量sum供所有会话使用,这些会话可能来自不同的浏览器和不同的电脑。换句话说,来自某一用户的数据将被另一个用户访问。这显然不是这个计算器应用希望的。视图状态是这个应用最恰当的技术,变量ViewState[“Sum”]将被存储在浏览器中的XHTML页面的隐藏字段里,并且仅能被这个浏览器使用。下面我们将给出按钮后台的视图状态版本的代码。

publicpartialclass_Default:System.Web.UI.Page{

protectedvoidPage_Load(objectsender,EventArgse){}

Int32FinalAmt=0;

protectedvoidButton1_Click(objectsender,EventArgse){

Int32sum=0;

if(ViewState["Sum"]==null)ViewState["Sum"]=0;

else{

Int32newValue=Convert.ToInt32(this.TextBox1.Text);

sum=(Int32)ViewState["Sum"]+newValue;

ViewState["Sum"]=sum;

this.Label1.Text=sum.ToString();

FinalAmt=sum;

}

}

}

由于数据存储在客户端,视图状态的好处是能最大限度的减少服务器的负担,数据存储在客户端,视图状态可以使服务器处理更多数量的访问。但视图状态也存在一些问题:视图状态仅能存储字符型数据,而且一个页面的数据在另一个页面不可见,即使这些页面属于同一会话。例如,如果我们的应用有两个ASPX页面:一个是添加到购物车页面,用于计算所有购物的总花费;另一个是结账页面,用于访问银行服务以通过信用卡支付花费。因而,我们需要将来自购物车页面的总花费传递到结账页面。不幸的是,结账页面无法读取购物车页面的数据。有几种不同的方法来解决这个问题,例如,通过跨页面调用,允许一个页面调用另外一个页面的方法。在下节,我们将创建一个会话范围可见的变量,叫做会话状态。5.3.3会话状态

会话状态(SessionState)可以创建存储服务端结构化对象的变量,并且变量的作用域是会话范围。存储在会话状

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论