在Web页面中执行Windows程序

现在许多公司都面临一个难题：如何在Web环境中执行存在的Windows应用程序。这里就介绍实现这个功能的技术，它争取对代 码做最小的改变，完成在Windows环境中应做的一切。

现存的Windows应用程序

这里想要在Web中执行的Windows例子程序是非常简单的，它是用VB编写的，其中有一个表单。运行时，在表单上显示雇员的信 息，这些信息来源于Access数据库的一个表。表单上设有First、Next、Previous 和 Last按钮，从而允许用户浏览记录。同时， 还可以通过按钮Add、Delete 和 Update来改变数据。

这个程序通过一个COM类来与数据库通信，它有下面的方法：

    AddEmployee() 在表中添加一个记录，保存新雇员的信息
    UpdateEmployee() 更新一个记录
    DeleteEmployee() 删除一个记录
    GetEmployees() 获取一个雇员的信息

程序正常运行时，浏览器显示如下：

开发Web应用程序

在传统的web应用程序中，大多数的处理都是在服务器端完成的。这里，我们将尝试在客户端做一些处理，以减少服务器上的工 作量。也就是，让客户端完成显示信息的处理工作，并将商业规则和数据库存取留给服务器端。这就象一个n层处理模型。

当用户需要访问另一个不同的数据时，我们也不想从服务器上再调入整个web页面，因此，需要找到一个web客户端在后台与 web服务器交流信息的方法。这个例子中，我们使用了微软公司的XMLHTTP COM对象组件，它是随Internet Explorer 5.0而来 的。当然，也可以编写一个功能类似的Java applet来克服这个局限。

服务器端的代码

让我们从研究VB应用程序的COM类到Web的每一个方法开始，这可以通过编写ASP页面来调用COM类中的每个方法实现 (AddEmployee.asp, UpdateEmployee.asp, DeleteEmployee.asp, GetEmployee.asp)。 明白了这些，就能够在Web中存取COM 类方法了。

ASP页面应该能够接受与COM类一样的参数，这些页面向原始的COM类发送调用。这里主要的区别就是所有的输出是以XML格式 的。我们使用另外一个叫XMLConverter的COM类，转换方法的输出为XML格式。XMLConverter的代码包含在下载文件中，它有一个 函数，能够接受一个ADO记录集做为参数，并且转换为一个XML文档。实现这个目的的函数例子可以从Internet上很容易地找到，比 如： http://www.vbxml.com/xml/guides/developers/ado_persist_xml.asp

我们也许曾经使用过ADO记录集的Save函数，加上adPersistXML，来实现按照xml格式保存，但是在这里，为了简单起见，我 们仍使用编制的函数。

下面的代码来自GetEmployees.asp，它执行GetEmployees方法，从而可以让你清晰地看到这种技术：

    <SCRIPT LANGUAGE=vbscript RUNAT=Server>
     'Declare the above described XMLConverter
     Dim objXMLConverter

     'Create the XMLConverter object on the web server machine
     Set objXMLConverter = Server.CreateObject("XMLConverter.clsXMLConverter")

     'Declare the above described EmployeeMgr object
     Dim objEmployeeMgr

     'Create the EmployeeMgr object on the web server machine
     Set objEmployeeMgr = Server.CreateObject("EmployeeMgr.clsEmployeeMgr")

     'Declare a String varaible
     Dim strXML

现在调用Employees对象的Employees()方法，它将返回一个ADO记录集对象，我们将这个对象传递给XMLConverter对象的 xmlRecordset（）方法，xmlRecordset（）负责将ADO记录集转换为XML文档。最后，我们取回XML文档，并将它存入strXML字符 串变量中：

     strXML = objXMLConverter.xmlRecordset(objEmployeeMgr.GetEmployees)

     'Destroy the EmployeeMgr object
     Set objEmployeeMgr = Nothing

     'Destroy the XMLConverter object
     Set objXMLConverter = Nothing

     'Write the XML Document as the response
     Response.Write strXML
    </SCRIPT>

然后，用同样的方式来创建页面AddEmplyee.asp、DeleteEmployee.asp和UpdateEmployee.asp。

客户端的代码

现在准备编写客户端代码，首先，让我们仔细看看VB应用程序在调用后如何显示信息。在VB表单的On_Load方法（参见下面的 代码）中，我们调用了COM对象组件GetEmployees方法，这个方法返回一个附带雇员信息的ADO记录集。ADO记录集的MoveFirst （）、MoveNext()以及 MoveLast() 方法建立了记录浏览的方法。

    Private Sub Form_Load()
     'Create the EmployeeMgr Object
     Set objEmplyeeMgr = New clsEmployeeMgr

     'Obtain the Employee Records in a ADODB.Recordset
     Set rst = objEmplyeeMgr.GetEmployees
     rst.MoveFirst
     DisplayCurrentRecord
    End Sub

在这种情况下，我们有一个ASP页面GetEmployees.asp，它给出了做为XML文档的信息。所以我们将在web客户端建立一个 XMLDOM对象，并且调入由GetEmployees.asp提供的信息。在这个例子中，我们使用Microsoft DOM XML来解析。关于DOM XML解 析的完整文档，请参考MSDN有关文章，比如 XML DOM Objects。

另一个较好的解决方法是使用纯Java/JavaScript，它同时可以在非Internet Explorer的浏览器上应用。这里，我们仍使用 XMLHTTP对象，它可以让web客户端建立一个到web服务器的HTTP请求。关于对XML HTTP的详细描述，请参考MSDN上的文档。

     //Create an XMLDOM on the Web Client machine
     var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");

     // node pointing at Root node of the XML Document
     var nodeRoot;

     // node to point at Current Record
     var nodeCurrentRecord;

     // Integer pointing at the current Record number
     var nCurrentIndex = 0;

     //Create the Microsoft XMLHTTP object on the web client machine
     //This would have to be present and registered on the client machine
     //Installing Internet Explorer 5.0 satisfies this requirement
     var objHTTPRequest = new ActiveXObject("Microsoft.XMLHTTP");

     //Open a http connection to the URL in strURL
     objHTTPRequest.Open ("GET", strURL, false, null, null);

     //Send the request
     objHTTPRequest.send();

     //Obtain the response received to the xmlResponse variable
     //This response would be the XML document returned by the web server
     var xmlResponse = objHTTPRequest.responseText

     //Since the response is an XML document we can load it to an xmlDoc object
     xmlDoc.loadXML (xmlResponse);

     //Set nodeRoot to point at the root of the xml document
     nodeRoot = xmlDoc.documentElement;

从上面我们了解了XML文档的结构，现在可以仔细研究XML文档对象了。我们将编写一个客户端的JavaScript函数 rstMoveFirst（），它可以移动当前记录指针到第1条，这与ADO记录集的MoveFirst方法类似：

    function rstMoveFirst() {
     //Error trap for empty record set
     if (nodeRoot.childNodes.length; < 1) {

     //If the root node does not have any child nodes then there are
     //no "records"
     return false;
     }
     nCurrentIndex = 0;

     //Set the nodeCurrentRecord to point at the 0th child of the
     //XML Document. The 0th child would be the first record.
     // nodeRoot is the XML document？ documentElement
     nodeCurrentRecord = nodeRoot.childNodes(nCurrentIndex);

     //Return Success
     return true;
    }

同样，我们可以编写rstMoveNext()和 rstMoveLast()函数，通过编写这些代码，我们将能仔细地了解XML文档元素。而且， 再编写一个类似于ADO记录集upadte方法的函数。

现在我们在客户机上创建了一个假冒的ADO记录集对象，因此就可以象在VB应用程序中一样来处理这些“记录集”。

有了这些函数，剩下的就是编写用户界面，这就象在VB应用程序中一样。比如，在VB应用程序中，“移动到第1条记录”后面 的代码是：

    Private Sub btnFirst_Click()
     If Not (rst.EOF And rst.BOF) Then

     'Move to the first record
     rst.MoveFirst

     'DisplayCurrentRecord is a function that display the current 'records information
     DisplayCurrentRecord

     End If
    End Sub

    在web应用程序中，相应的代码是：

    function btnFirstClick() {
     'Move to the first record in the recordset
     'Note that our rstMoveFirst returns True if
     'it was successful and false if EOF and BOF
     if (rstMoveFirst()) {
     'Here DisplayCurrentRecord is client side JavaScript
     'function that display the current records information on
     'the the screen
     DisplayCurrentRecord();
     }
    }

当需要更新实际的数据库时，就发送更新信息给UpdateEmployee.asp，这个页面将通过COM对象的UpdateEmployee方法来更 新数据库。上面描述的应用程序，输出到web上，将显示如下图：

结论

在web应用中，要建立适当的计划来转换ADO记录集为XML文档。一旦定义明确了，象那样标准的应用将很好实现。另外一个我 们想研究的领域是客户端记录集的操纵函数（就是rst*函数）。我们可以编写Java applet来处理这些记录集操纵函数，从而在客 户端建立了Java记录集对象。这种方法将是很面向对象的一种处理方法。