智能客户端(SmartClient)
智能客戶端(SmartClient)
??? 本文主要討論基于企業環境的客戶端應用程序模型,由于本人曾經從事過傳統的客戶端/服務器兩層結構應用程序和基于.net平臺的多層結構應用程序的開發,因此本文將著重描述.net平臺上的智能客戶端應用程序模型,并根據一般的企業應用系統的需求來一步一步構造出一個較為完整的客戶端軟件框架。
簡介
??? 智能客戶端的概念作為Microsoft.net平臺的一個特性而被提出,其實它的很多功能在傳統的應用程序中早已存在,只是.net平臺從系統和語言級別對它提供了支持,使開發智能客戶端應用程序更為便捷。本文將從企業應用系統的角度來討論智能客戶端應具有的功能和特性以及如何在.net平臺上實現。
概述
??? 1、當前的客戶端應用程序模型比較
??? 當前的客戶端應用程序模型大致分為兩種:C/S(客戶端/服務器模型)和B/S(瀏覽器/服務器模型)。以企業環境為對象的軟件開發人員,對于以瀏覽器為基礎的精簡型客戶端 (Thin Client) 應用程序模型,以及對應的豐富型客戶端 (Rich Client) 之間,究竟該如何取舍,面臨了困難的世代替換。
??? 以瀏覽器為基礎的應用程序的優缺點:
- 易于安裝:可以用于許多桌上型計算機,并且和客戶機算計的操作平臺無關。大多數計算機已經默認安裝有瀏覽器軟件(有些應用系統需要基于IE瀏覽器,或者需要安裝java虛擬機,在此暫且忽略不及)。
- 易于部署與維護:只需要在服務器端進行部署和維護工作。
- 必須在線工作:工作效率和網絡是否延遲有關。
- 不能充分利用客戶端計算機的資源:只能通過有限的HTML語言來呈現用戶界面,沒有利用客戶端計算機的計算處理能力。只能利用瀏覽器的打印功能來打印資料,不適用于企業的報表打印。
- 網絡傳輸量大:由于客戶端不能保存狀態數據,因此必須在客戶端和服務器之間傳輸用戶界面內容以及所需的數據。
- 安全性較低。對于服務器來說可以通過防火墻軟件來過濾數據,因為所有傳輸內容都是基于HTTP端口。但很難對數據進行加密和簽名以保證在傳輸過程中的完整性。(HTTPS似乎并不能解決問題)
- 適合電子商務或不要求嚴格控制客戶端的應用程序。
??? 豐富型客戶端應用程序的優缺點:
- 可以離線工作:前提是本地必須有緩存數據的能力,這涉及到與服務器數據同步的問題。
- 充分利用客戶端計算機的資源:可以為用戶提供豐富的界面元素,可以存取本機磁盤與本機應用程序接口 (API),執行速度較快。
- 網絡傳輸量較小:只需在客戶端和服務器之間傳輸數據。
- 安全性較高。可以方便的在客戶端和服務器執行加密和解密操作,同時也可以通過Web Service來消除傳統的應用程序諸如防火墻和HTTP的障礙。
- 安裝、部署和維護工作較為繁瑣:對客戶端計算機在操作平臺和附加軟件上有一定的限制和要求。
- 適合企業內部應用程序。
??? 目前,還有一種不是基于瀏覽器的瘦客戶端應用程序。通過諸如Microsoft Terminal Server、Citrix System的Independent Computing Architecture和MetaFrame產品這樣的技術和工具把它們提供給用戶。這些類型的解決方案可以讓用戶運用胖客戶端的經驗,并通過集中的軟件安裝和維護來進行管理,這對公司來說是很劃算的。這種模式的問題是,當應用程序沒有連接到應用服務器時,用戶就不能用了。客戶端不進行真正的處理,處理完全依賴應用程序服務器,這種情況會導致服務器性能問題,并消耗桌面計算機的CPU周期。
??? 總之,相對于豐富型客戶端,以瀏覽器為基礎的模型對于信息科技 (IT) 系統管理員而言是非常棒的模型,但對于開發人員與使用者而言卻有很多不足的地方。
Microsoft .NET Framework 將滿足這三方的需求。它的智能型客戶端應用程序模型結合了豐富型客戶端模型的強大功能與彈性,還有以瀏覽器為基礎之模型的容易部署與穩定性。
??? 2、客戶端應用程序還應具備的其他功能
??? 對于企業應用系統來說,客戶端應用程序作為整個系統與用戶的交互界面,還需要考慮以下功能:
- 安全性:這里的安全性主要是指應用層次的安全性,主要通過用戶權限、角色分配來實現。對于客戶端應用程序來說,通常需要提供一個登錄窗體或登錄頁面來完成用戶身份的認證。對安全性要求較高的應用系統可能還需要通過公共密鑰基礎設施(PKI)為應用提供可靠的安全服務,客戶端則附加了加密簽名模塊。
- 可擴展性:客戶端應用程序應該具有包含各種不同類型的應用模塊的能力,同時又能在使用過程中的不斷的增加應用來完善整個系統。因此可以將客戶端應用程序設計為一個容器,而各個應用模塊作為組件由容器進行動態加載。
- 可配置性:由于用戶權限和用戶喜好的不同,客戶端加載的應用組件以及呈現的表現形式都因人而異。需要由應用系統將用戶權限的范圍以及用戶的個性化配置信息傳遞給客戶端,由客戶端應用程序來解釋并呈現相應的用戶界面。
定義
??? 綜上所述,我們對智能客戶端應用模型下一個概括性的定義:一個可擴展的能集成不同應用的桌面應用程序,并具有以下特征:
- 無接觸部署:安裝時只要將一個主程序文件下載到本地,直接運行即可,無須改變注冊表或共享的系統組件,其他應用組件將在第一次運行時自動下載。
- 自動更新:只需將新版本的程序發布在服務器上,由客戶端自動發現最新版本的程序和應用組件,并自動下載和更新。
- 離線運用:允許脫離服務器時,利用本地的客戶端程序和應用組件進行工作。
- 動態加載應用組件:應用軟件開發商可根據企業應用系統的公共接口進行開發,然后將應用組件發布在企業的服務器上,客戶端應用程序將自動發現并加載該應用組件。
- 個性化用戶界面:用戶可根據喜好自行設置客戶端應用程序,配置信息將被保存到服務器上。
??? 以下我們將以.net平臺WinForms應用程序為例,對上述特征進行詳細描述。
.net平臺WinForms應用程序舉例
??? 一、系統需求
??????? 1、客戶端軟件要求
- 任何支持 .NET Framework 的操作系統
- 已安裝 SP1 的 .NET Framework
- Internet Explorer 5.0.1 或更高版本
??????? 2、服務器軟件要求
??????????? 自動發布、更新服務器:Microsoft .NET Framework、MDAC2.7、IIS
??? 二、運行方式
??? 客戶端應用程序有兩種運行方式,不同的運行方式將直接影響以后的程序集發布和更新,以下將詳細解釋:
??????? 1、網絡運行
??? .NET Framework 安裝提供了一個掛接 Internet Explorer 5.01 和更高版本以偵聽所請求的 .NET 程序集的機制。在請求期間,可執行程序被下載到磁盤上稱為程序集下載緩存的位置(Windows2000下為:C:\Documents and Settings\Administrator \Local Settings\Application Data\assembly下的某個子目錄中),同時該程序集本身以及它引用的其他相關程序集也被下載到本地IE緩存中(Windows2000下為:C:\Documents and Settings\Administrator\Local Settings\Temporary Internet Files)。然后,名為 IEExec 的進程在具有有限安全設置的環境中啟動該應用程序。例如:您可以在IE的地址欄中輸入一個已發布在web服務器上的.net可執行程序(http://SmartClient/MyApplication.Exe),IE并不會像其他文件一樣提示您另存為,而是直接執行該程序。
??? 通過這種方式運行的應用程序擁有非常有限的安全設置(Internet權限集),該權限集中的權限包括:安全性、文件對話框、正在打印、獨立存儲文件、用戶界面。獨立存儲文件允許您的應用程序保存一些數據(Windows2000下為:C:\Documents and Settings\Administrator.TOMATO\Local Settings\Application Data\IsolatedStorage下的某個子目錄中,默認存儲空間大小為10MB),您可以通過System.IO.IsolatedStorage命名空間中的類來保存數據而不會拋出安全異常。
舉例:
//按用戶、域、程序集獲取獨立存儲區
IsolatedStorageFile isoStore = IsolatedStorageFile.GetStore(IsolatedStorageScope.User | IsolatedStorageScope.Domain | IsolatedStorageScope.Assembly, null, null);
//創建目錄
isoStore.CreateDirectory("TestDir");
//創建文件
IsolatedStorageFileStream isoStream1 = new IsolatedStorageFileStream("TestDir//test.txt", FileMode.Create, isoStore);
//寫入文件
StreamWriter writer = null;
writer = new StreamWriter(isoStream1);
writer.WriteLine("Hello Isolated Storage");
writer.Close();
isoStream1.Close();
??? 為了讓你的智能應用程序運轉,你需要改變一些客戶端的安全設置,實質上就是通知客戶端運行時間相信你的應用程序。一種方法就是將帶有你的程序集的站點添加到IE中可信任站點清單中,然后用安裝在你的管理工具目錄下的Microsoft .NET Framework Configuration工具來修改.NET Framework安全設置。打開Framework Configuration工具,選擇運行庫安全策略,然后選擇調整安全區域。對于受信任站點中指定的所有站點,將信任級別調整到完全信任。作為選擇,你也可以用Framework Configuaration工具來修改安全策略,使它信任你的應用程序的個別程序集。右擊運行庫安全策略,選擇提高程序集的信任級別。
??? 另一個可選擇的方法就是用代碼組,用Framework Configuration工具來幫助你提高應用系統的程序集的安全設置。你需要讓所有運用你的應用程序的桌面用戶做這種改變。為了幫助完成該任務,Framework Configuration工具可以創建一個包含安全策略的Microsoft Installer (MSI)部署包。MSI安裝了應用程序加載器來分布你的應用程序需要的安全策略和加載器裝配。右擊運行庫安全策略,選擇創建部署包。
??? 在網絡運行中,自動更新是依靠IE的緩存機制來完成的。即當您需要下載并運行一個應用程序時,IE將向Web服務器發送一個HTTP請求,該請求將獲取服務器上該程序的最新更新日期,如果該日期大于本地緩存的程序的日期或者本地緩存中不存在該程序,則從服務器上下載,否則直接使用本地緩存的程序。因此對于.net本身所具有的版本機制而言,不能作為版本更新的依據,只有在某個程序集文件引用另外一個程序集時,才會由.net運行時依據自身的版本機制判斷版本號。
注意事項:
- 這種運行方式通常需要在運行前先設置用戶的安全策略。
- 加載應用組件時,需要一個完整的url地址。
- 如果應用程序集中需要調用Web Service,該Web Service所在的服務器地址只能是最初下載程序集的服務器,可以構造一個重定向來解決該問題。
- 某些文件可能不能通過自動更新機制來完成版本更新,如:.Config應用程序的配置文件。
- 如果某些應用程序集文件的版本之間存在著某些關聯性,則在某些情況下(如:網絡突然中斷)可能會出現不能正確加載并導致客戶端應用程序出錯的問題。
- 如果用戶清空IE的緩存,則客戶端應用程序將不能離線工作。
??????? 2、本地運行
??? 顧名思義,這種運行方式客戶端應用程序和其他應用組件并不在IE緩存和.net下載緩存中運行,需要用戶首先下載客戶端程序集并保存到一個本地目錄下,然后運行。這樣客戶端應用程序以及其他應用組件就擁有了所有的本地安全權限。
??? 雖然不涉及安全性問題,但應用組件以及程序的自動更新如何實現?這就需要一個單獨的組件來完成這些任務。通過該鏈接地址可以下載一個非常完善且支持擴展的自動更新組件(http://www.gotdotnet.com/team/windowsforms/DotNetUpdater.zip),該打包文件中提供了源碼、一些例子以及文檔。該更新組件使用HTTP-DAV技術來完成文件在服務器和客戶端之間的傳輸,因此對Web服務器有一定的限制,IIS5.0和新版本的Apache支持該功能。具體使用方式請參見內含文檔。
注意事項:
- 由于需要自己來實現更新和下載功能,所以會增加一定的工作量。(就是使用第三方的更新組件,也需要對其進行完善以滿足自己的要求)
- 基本解決了網絡運行的缺點,但需要每次更新時重新下載所有的文件(如果采用增量更新的話,某些情況下會出現某個版本的文件被遺漏的問題),會增加網絡流量。
- 應該在后臺線程中執行更新和下載,不影響用戶的正常操作。
??? 三、創建程序
??? 客戶端應用程序的執行步驟:
??? 客戶端應用程序基本包含了登錄窗體、主窗體和應用組件加載器。加載器內有一個應用組件集合類,同時還提供一些方法用于主程序和應用組件之間以及不同應用組件之間的通訊,某些應用組件是作為公共組件為其他應用提供數據,因此應該通過統一的方法來獲取數據。
注意事項和建議:
??? 1、對于網絡運行方式,程序集在動態加載的過程從服務器被下載到本地緩存中,而本地運行方式的下載過程由更新組件執行,加載過程則客戶端主窗體執行。
在.net中動態加載程序集的方法:
using System.Reflection;
//網絡運行方式,加載的程序集路徑為服務器上的url地址
assemblyFileName = "http://SmartClient/AppComponent1.dll";
//本地運行方式,加載的程序集路徑為本地的目錄路徑
assemblyFileName = @"c:\SmartClient\AppComponent1.dll";
Assembly asm = Assembly.LoadFrom(assemblyFileName);
??? 2、客戶端應用程序的主窗體作為應用組件的容器,可以通過兩種方法來顯示應用組件的用戶界面:
??? 第一種方式是將客戶端應用程序設計為多文檔界面(MDI)應用程序,每個應用組件都包含有各自的啟動主窗體,客戶端應用程序執行每個應用組件時,將構造并顯示該組件的啟動窗體類型。MDI 應用程序中常有包含子菜單的“窗口”菜單項,用于在主窗口或應用之間進行切換。
??? 另一種方式是在客戶端應用程序的主窗體界面中預留一塊應用界面區域,而每個應用組件作為一個用戶控件在執行時被添加到應用界面區域的控件數組中。應用界面區域通常是一個面板(Pane)控件,通過更改用戶控件的Z順序在各個應用之間進行切換(Control. BringToFront())。
??? 3、在客戶端應用程序根據配置信息加載相應的應用組件時,同時需要在客戶端主窗體的工具欄或菜單上創建對應的按鈕和菜單項,并添加事件以便于用戶操作。客戶端應用程序和應用組件之間應盡量保持獨立性,減少關聯,以體現客戶端應用程序結構清晰和簡單。可以通過.net中的回調(事件委托)等方法實現這一點。
??? 4、.net由于緩存的原因,在加載程序集時會出現以下問題:
//第一次加載
Assembly asm = Assembly.LoadFrom (@"c:\SmartClient\AppComponent1.dll");
Activator.CreateInstanceFrom(asm.GetType("AppComponent1.MainForm"));
//第二次加載一個不同目錄下的文件名稱相同但內容不同的程序集
Assembly asm = Assembly.LoadFrom (@"c:\test\AppComponent1.dll");
Activator.CreateInstanceFrom(asm.GetType("AppComponent1.MainForm"));
第二次加載后,沒有正確的構造出不同目錄下的程序集中的窗體類型,而是使用了緩存中的第一次加載時的構造類型。
為了解決上述問題,必須在不同的應用程序域(Domain)中構造這兩個類型實例。
//第二次加載一個不同目錄下的文件名稱相同但內容不同的程序集
AppDomain newDomain = AppDomain.CreateDomain("newDomain");
newDomain.CreateInstanceFromAndUnwrap(@"c:\test\AppComponent1.dll", "AppComponent1.MainForm");
使用此方法時需要注意,如果您構造的類型實例包含一個帶參數的構造函數,則這些參數對象必須是可跨應用程序域訪問的對象,即是可序列化的對象。可以通過繼承MarshalByRefObject對象或使用[Serializable]特性標記類,同時設置遠程對象的生存期策略。
示例:
public class ParameterClass : MarshalByRefObject
{
??? public override Object InitializeLifetimeService()
??? {
??????? //定義遠程處理生存期服務所使用的生存期租約對象
??????? ILease lease = (ILease)base.InitializeLifetimeService();
??????? if (lease.CurrentState == LeaseState.Initial)
??????? {
??????????? //設置租約的初始時間。該租約將永遠不會到期,并且與之關聯的對象將具有無限長的生存期。
??????????? lease.InitialLeaseTime =TimeSpan.Zero;
??????? }
??? }
}
??? 四、發布程序
??? 1、在發布和更新服務器上設置一個虛擬目錄(如:SmartClient)將應用組件的所有文件放置在相應的目錄下。
??? 虛擬目錄的設置屬性中必須包括:讀取和目錄瀏覽權限,執行許可為純腳本。
??? 對于本地運行方式,需要根據客戶端應用程序的版本號設置多個目錄,每個目錄存放不同版本的所有文件。(也可以在新版本目錄下只存放更新了的文件,但需要修改更新組件。當用戶更新版本時,必須下載大于當前版本的所有新版本目錄下的文件,以防止某些情況下會出現某個版本的文件被遺漏的問題)。
??? 在本地運行方式中,還需要在根目錄下維護一個更新版本清單文件,因為它允許用戶以老版本客戶端應用程序登錄。
??? 2、發布一個Web Service。該Web服務主要完成以下任務:
- 執行客戶端用戶的身份驗證
- 從整個應用系統的安全模塊中獲取該用戶允許執行的應用組件的清單,包含應用組件的位置、文件名稱和應用組件本身所需的配置信息。(在本地運行方式下,該清單還和版本有關)
- 從數據庫中獲取該用戶的個性化配置信息,和上一步獲取的信息合并為一個XML文件流。
- 將該配置文件流作為返回參數返回給客戶端應用程序。
??? 3、將客戶端應用程序放置在虛擬根目錄下作為應用組件程序集的加載器,同時在企業內部網站上增加一個指向客戶端應用程序的鏈接。對于網絡運行方式,還將提供一個安全策略部署包(MSI)文件的鏈接。
??? 用戶第一次運行時的執行步驟
??? 網絡運行方式:
- 下載并安裝安全策略部署包
- 通過點擊客戶端應用程序的鏈接,下載并執行客戶端應用程序
- 將該鏈接添加到收藏夾中或建立桌面快捷方式,以便于運行
??? 本地運行方式:
- 不直接點擊客戶端應用程序的鏈接,將此鏈接另存到用戶選擇的目錄下
- 在資源管理器中執行客戶端應用程序
- 在桌面上建立可執行文件的快捷方式,以便于運行
??? 五、更新程序
??? 網絡運行方式的更新步驟較為簡單,只須將更新了的文件直接覆蓋老文件即可。其缺點是某些程序集附帶的引用文件不能自動下載新版本,只有清空客戶端的IE緩存后才能實現更新。
??? 本地運行方式的更新步驟如下:
- 在服務器虛擬根目錄下新建一個以新版本號命名的目錄,增量更新只需將更新了的文件復制到該目錄下,否則需要將所有文件都復制到目錄。
- 修改保存所有版本清單的文件,并指明當前活動的最新版本號,用于和客戶端進行版本比較。
??? 六、擴展應用組件
??? 為了實現企業應用系統的可擴展性,通過接口定義,可以使應用開發商通過實現這些接口將自己的應用組件方便的添加到客戶端應用程序中。以下介紹一些接口中主要包含的方法和屬性。
??? 對于MDI應用程序,可以在啟動窗體的關閉事件中處理而不需要該方法。
??? 客戶端應用程序內的應用組件加載器可以通過枚舉組件程序集內的類型來判斷該組件是否符合借口定義。同時可以將多個應用組件打包在一個應用程序集中。此過程非常耗時。
示例:
//根據程序集文件名稱,加載程序集
Assembly asm = Assembly.LoadFrom(assemblyFile);
Type[] types = asm.GetTypes();
//搜索程序集中的所有類型
foreach (Type t in types)
{
??? //指示類型是否由引用封送,支持遠程處理
??? if (!t.IsMarshalByRef)
??? continue;
??? //判斷該程序集的類型是否有符合應用組件接口的類型
??? if (Array.IndexOf(t.GetInterfaces(), pluginType) > 0)
??? {
??????? ...
??? }
}
小結
??? 上述僅僅是對創建智能客戶端應用程序作了簡單的描述和示范,并對其中可能遇到的問題給與了必要的解釋,希望能對您創建更為強大、靈活、便捷的應用程序提供幫助。
參考資源鏈接
1、Security and Versioning Models in the Windows Forms Engine Help You Create and Deploy Smart Clients
http://msdn.microsoft.com/msdnmag/issues/02/07/NetSmartClients/default.aspx
2、Smart Client Application Model and the .NET Framework
http://msdn.microsoft.com/netframework/techinfo/articles/smartclient/default.asp
3、State Sanity Using Smart Clients
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnforms/html/Winforms05202002.asp
4、Increasing Permissions for Web-Deployed Windows Forms Applications
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnforms/html/winforms11122002.asp
5、.NET Application Updater Component
http://www.gotdotnet.com/team/windowsforms
轉載于:https://www.cnblogs.com/devilmsg/archive/2008/12/09/1350824.html
總結
以上是生活随笔為你收集整理的智能客户端(SmartClient)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [转]对C#泛型中的new()约束的一点
- 下一篇: 惠普前总裁孙振耀指点职业规划