



版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
Duwamish架構分析篇Duwamish是Microsoft提供ー個企業(yè)級的分布式系統(tǒng)架構,如果開發(fā)企業(yè)級的分布式系統(tǒng),可以模仿這種架構,如果是開發(fā)ー些簡單的系統(tǒng),則完全可以簡化。以前也學習過Duwamish范例,只是發(fā)現不同時間,不同經歷,有不同的體會。正如盧彥所說的一樣:通過研究Duwamish示例,高手能夠領悟到.Net應用架構的設計思想,低手能夠學習到Net的編程技巧,實在是老少皆宜。因此,這里再次學習并體驗一次Duwamish范例。1,Duwamish7.0結構分為四個邏輯層(FROMMSDN):Web層—PresentationWeb層為客戶端提供對應用程序的訪問。這ー層是作為Duwamish.sin解決方案文件中的Web項目實現的。Web層由ASP.NETWeb窗體和代碼隱藏文件組成。Web窗體只是用HTML提供用戶操作,而代碼隱藏文件實現各種控件的事件處理。業(yè)務外觀層—BusinessFacade業(yè)務外觀層為Web層提供處理帳戶、類別瀏覽和購書的界面。這ー層是作為Duwamish.sln解決方案文件中的BusinessFacade項目實現的。業(yè)務外觀層用作隔離層,它將用戶界面與各種業(yè)務功能的實現隔離開來。除了低級系統(tǒng)和支持功能之外,對數據庫服務器的所有調用都是通過此程序集進行的。業(yè)務規(guī)則層ーBusinessRules業(yè)務規(guī)則層是作為Duwamish.sln解決方案文件中的BusinessRules項目實現的,它包含各種業(yè)務規(guī)則和邏輯的實現。業(yè)務規(guī)則完成如客戶帳戶和書籍訂單的驗證這樣的任務。數據訪問層ーDataAccess數據訪問層為業(yè)務規(guī)則層提供數據服務。這ー層是作為Duwamish.sln解決方案文件中的DataAccess項目實現的。除了上述四個邏輯層外,Duwamish7.0還包含封裝在Duwamish.sln解決方案文件中的Common項目內的共享函數?!巴ㄓ?(Common)層包含用于在各層間傳遞信息的數據集。Common項目還包含Duwamish.sln解決方案文件中的SystemFramework項目內的應用程序配置和跟蹤類。
2,各個邏輯層之間的關系圖(FROMMSDN)2,各個邏輯層之間的關系圖(FROMMSDN)及其調用Sequeance圖示例:數?庫〇SQLServer下面是Categories.aspxweb頁面獲取Category的Description的整個調用過程。(1)實例化Productsystem對象(2)調用Productsystem的GetCategories。方法(3)檢測參數的合法性(4)倉リ建Categories::DataAccess對象實例(5)返回上述對象(6)調用Categories::DataAccess對象的GetCategories()方法(7)倉リ建CategoryData::Common對象實例(8)返回上述對象(9)返回CategoryData:zCommon對象實例,該實例中已經包含了需要的數據(10)返回CategoryData::Common對象實例給web/Client端(11)檢測數據的合法性(12)讀取并顯示結果:Category的Descriptionr一 !1 |1Createaninstanceobjel>uJ2:GetCategoriesQ;1:t3:CheckCjnditionQg1ProductSvstem二BusinessFacadeADDlicationAssert二SystemFrameworkCategories二DataAccessCateqories.aspx.es二CateqorvData::Cateqories.aspx.es二CateqorvData::4:Createaninstanceol蟻Ct*5:Return^Categories二DataAccessobject7:Createaninstanceobject6:GetCategoriesQ10:: 甘9:ReturnCategoryDataobject十10:: 甘9:ReturnCategoryDataobject十 :8:ReturnCate^oryDataobjectReturnCategoryDataobject: 1:1:CheckConditionQ12:ReadanddisplaythedescriptionfortheCategory: :尸[;:] 1 1 ? i 1 KAnothercallingprocessonProductsystem.GetCategoryltemsOisalmostthesamewiththeabowprocedure.TheonlydifferencesareusingBooks::DataAccessandBookData::Commonclasses,insteadofCategories::DataAccessandBookData::Commaonclasses.SystemFramework項目包含ー些application需要的配置參數,ApplicationLog日志類和ApplicationAssert參數校驗類。SystemFramework項目為所有其他的項目所引用。Common項目包含了用于在各層間傳遞信息的數據集,如上述的CategoryData繼承System.Data.DataSet,既不是所謂的typedDataSet,也不是一般的DataSet,不過簡單實用,這是基于.NetRemoting開發(fā)分布式系統(tǒng)用來tier與tier之間交互數據的ー種方法。Common項目也被其他的項目引用,SystemFramework項目除外。BusinessFacade項目中所有的Classes繼承MarshalByRefObjectclass,顯然是讓準備將BusinessFacadetier部署為Remote〇bjects。不過,實際上默認這里并沒有將其部署為RemoteObjects,Web層仍然調用本地對象(《Duwamish部署方案篇》將分析這個問題)。3,Summary在開發(fā)基于.NetFramework企業(yè)級分布式系統(tǒng)時,上述架構值得推薦,但也并非完美無暇,實際上存在ー些值得改進的地方。顯然,不可能一個范例適合所有的實際情況么,要求太苛刻了。其實,EnterpriseSamples中的另外一個范例FitchandMather7.0,其架構和Duwamish就有些不同了。
如果是開發(fā)本地的系統(tǒng),就不要模仿Duwamish架構(看看上面獲取Category的Description調用過程就知道了,太費勁。),如BusinessFacade和BusinessRules中Classes應采用fine-grainedinterface設計,層與層之間的交互參數也不必全部采用DataSet,適當的時候采用setter/getter就可以了,這樣不僅可以提高開發(fā)效率,而且有助于提咼performance,maintainabilityandreusabilityoDuwamish部署方案篇Duwamish部署方案篇Duwamish7.0支持兩種多計算機部署方案。非分布式部署方案在一臺Web主機上部署Web層、業(yè)務外觀、業(yè)務規(guī)則和數據訪問層,但可以在群集間復制該Web主機以達到負載平衡。分布式方案在單獨的服務器上部署特定的組件。例如,業(yè)務外觀、業(yè)務規(guī)則和數據訪問層可能位于獨立于Web主機的服務器上。在實際部署中數據庫服務器通常位于單獨的計算機上。1S非分布式部署方案
在一臺Web主機上部署Web層、業(yè)務外觀、業(yè)務規(guī)則和數據訪問層,然后通過軟件(如ApplicationCenter2000)或硬件來實現網絡場(WebFarm)內各個WebServer的負載平衡。在本機默認安裝Duwamish7.0時,是采用非分布式部署萬案。2s分布式部署方案使用.NETFramework遠程處理技術將應用程序分布到多臺計算機中。簡單而言,就是IISWebServer和ApplicationServer分離,其中Web層(包括SystemFramework和Common項目)部署在IISWeb上,BusinessFacde/BusinessRules/DataAccess(包括SystemFramework和Common項目)ー起部署在ApplicationServer±〇ApplicationCenterNLB群集NIC110.2.2.xxNIC210.2.3.XX管理
通信量HS群集控制器(計宜機A)NIC310.2.4.xxxx防火墻xxNIC110.2.2.xx 管理NIC2通信量10.2.3.XXHS群集成員(計苴機B)NIC310.2.4.xxNIC110.2.2.xxZApplicationCenterNLB群集NIC110.2.2.xxNIC210.2.3.XX管理
通信量HS群集控制器(計宜機A)NIC310.2.4.xxxx防火墻xxNIC110.2.2.xx 管理NIC2通信量10.2.3.XXHS群集成員(計苴機B)NIC310.2.4.xxNIC110.2.2.xxZDuwamishNIC2恢?10.2.3.XX1^HS料族成員(計算機C)組件:WebSystemFrameWorkCommonNIC310.2.4.XX10.2.4.xx防火墻NIC110.2.5.xxNIC1xxNIC110.2.5.xxNIC210.2.6.XX管理
通信量NIC210.2.6.XX管理
通信量集sas(計算機X)NIC310.2.7.XX(計算機Y)NIC310.2.7.XXxx集^(計宜機Z)uwamish組件:BusinessFacadeBusinessRulesDataAccessSystemFrameworkCommonNIC310.2.7.xx.NET遠程處理:HTTP/二進制
10.2.5.XXApplicationCanterNLB群集10.2.7.XX?SQLServerDuwamish7.0使用HTTP/二進制而不是HTTP/S0APo使用HTTP的決定基于要通過端口80上的防火墻的要求。使用二進制而不是SOAP的決定基于性能上的考慮。對于大的數據塊,二進制的性能優(yōu)于SOAPo因此,如果要傳遞大的數據塊(例如,數組、數據集或數據表),則使用二進制格式化程序。如果要傳遞小的數據塊,則選擇使用SOAP還是二進制格式化程序是無關緊要的。傳遞整數時兩者的性能都很好。3,如何將Duwamish7.0部署為基于.NetRemoting的分布式系統(tǒng)下面采用Microsoft提供的Deploytool工具自動進行(其實手工也很方便):C:\ProgramFilesXMicrosoftVisualStudio.NET2003\EnterpriseSamplesXDuwamish7.0CS>deploytooldeployRemoteMachine=localhostpath=MC:\ProgramFilesXMicrosoftVisualStudio.NET2003XEnterpriseSamplesXDuwamish7.0CS\Duwamish7_Remote,,在commandline窗口輸入上述命令行代碼。[10/29/20046:43:43AM]CreatingdirectoryC:\ProgramFilesXMicrosoftVisualStudio.NET2003\EnterpriseSamplesXDuwamish7.0CS\Duwamish7_RemoteonW1MIS38[10/29/20046:43:43AM]StoppingallinternetservicesonW1MIS38[10/29/20046:43:59AM]DeployingDuwamish7BusinessFacadeonW1MIS38[10/29/20046:43:59AM]CreatingwebsiteonW1MIS38[10/29/20046:44:00AM]Generatingremotingconfigurationfiles[10/29/20046:44:00AM]StartingallinternetservicesonW1MIS38[10/29/20046:44:02AM]StartingDefaultWebSiteonW1MIS38[10/29/20046:44:02AM]Deploymentsuccessful運行結果:(1)在IIS創(chuàng)建中創(chuàng)建WebApplication(Duwamish7_Facade),本地路徑為:C:\ProgramFilesXMicrosoftVisualStudio.NET2003\EnterpriseSamplesXDuwamish7.0CS\Duwamish7_RemoteXweb作為RemoteServer端,Bin目錄下是BusinessFacde/BusinessRules/DataAccess層(包括SystemFramework和Common項目)DLL文件。其中web.config文件中包含所有RemoteObjects的配置,如<wellknownmode="Singleton"type="Duwamish7.BusinessFacade.Productsystem,Duwamish7.BusinessFacade"objectUri="ProductSystem.rem"/>Web層創(chuàng)建remotingclient.cfg配置文件,對ApplicationServer而言,Web層相當與Client端。remotingclient.cfg配置文件中包含formatter的設置(binary),選擇二進制格式化程序來序列化消息,注意是出于性能的考慮。Webapplication加載remotingclient.cfg配置文件Webapplication在global.asax文件包括如下代碼,在Application_OnStart事件中加載Retmoting配置文件。voidApplication_OnStart()Applicationconfiguration.OnApplicationStart(Context.Server.MapPath(Context.Request.ApplicationPath));stringconfigPath=Path.Combine(Context.Server.MapPath(Context.Request.ApplicationPath),,,remotingclient.cfgu);if(File.Exists(configPath))RemotingConfiguration.Configure(configPath);)其中前面代碼Applicationconfiguration.〇nApplicationStart。是調用Duwamish7.SystemFramework.ApplicaitonConfiguration的〇nApplicationStart。方法,用來初始化applicationroot和讀取web.config中的配置信息(將在《Duwamish代碼分析篇》中進行具體分析)。Duwamish代碼分析篇Duwamish代碼分析篇Writtenby:RickieLeeNov.02,2004繼續(xù)前面的2篇POSTWuwamish架構分析篇》和Wuwamish部署方案篇》,這里在代碼層次上分析Duwamish7.0范例,主要目的是解析Duwamish范例中值得推薦的編碼風格和提煉出可以重用的代碼或Classo1,讀取配置文件類ーSystemFrameworkXApplicationConfiguration.csApplicationconfiguration類用來讀取web.config文件中自定義section的配置信息,初始化一些基本設置。Applicationconfiguration類實現IconfigurationSectionHandler接口,并需要實現[C#]objectCreate(objectparent,objectconfigContext,XmlNodesection)方法,以分析配置節(jié)的XMLo返回的對象被添加到配置集合中,并通過GetConfig訪問。部分代碼片段解釋:CodeSnippet1—Applicationconfiguration.OnApplicationStart。方法publicstaticvoidOnApplicationStart(StringmyAppPath){appRoot=myAppPath;System.Configuration.Configurationsettings.GetConfig("Applicationconfiguration");System.Configuration.Configurationsettings.GetConfig("DuwamishConfiguration");System.Configuration.Configurationsettings.GetConfig("SourceViewer");)Configurationsettings類還提供了一個公共方法ConfigurationSettings.GetConfig()用于返回用戶定義的配置節(jié)的配置設置,傳入的參數sectionname,如"ApplicationConfiguration",表示要讀取的配置節(jié)。NameValueCollectionnv=newNameValueCollection();〃實例化NameValueCollection類對象nv=(NameValueCollection)ConfigurationSettings.GetConfig("ApplicationConfiguration");〃返回用戶定義的配置節(jié)的設置returnnv["SystemFramework.Tracing.Enabled"].ToString();〃返回特定鍵值,如SystemFramework.Tracing.Enabled不過,Configurationsettings.GetConfig。方法在調用時,自動調用Create。方法,可以看到Applicationconfiguration.Create。方法正是用來讀取指定section的配置,并初始化設置參數。Global.asax的ApplicationOnStart事件處理程序向SystemFramework的Applicationconfiguration類OnApplicationStart方法發(fā)出調用,正是上述的代碼片斷。CodeSnippet2—Global.asax中Application_OnStart()方法voidApplication_OnStart(){AppHcationConfiguration.OnApplicationStart(Conlext.Server.MapPath(Context.Request.ApplicationPath));stringconfigPath=Path.Combine(Context.Server.MapPath(Context.Request.ApplicationPath),"remotingclient.cfg");if(File.Exists(configPath))RemotingConfiguration.Configure(configPath);)該方法肩負二大任務:(1)調用AppHcationConfiguration.OnApplicationStart。方法,并傳入application的根目錄(RootDirectory)〇(2)檢測Client端的remoting配置文件是否存在(其實是webserver端),如果存在,則讀取并初始化remoting配置信息,如配置通道Channel等等,詳見《Duwamish部署方案篇》。2t讀取web.config中Duwamish相關的ー些配置ーCommonXDuwamishConfiguration.csCommonXDuwamishConfiguration.cs也實現IconfigurationSectionHandler接口,與SystemFrameworkXApplicationConfiguration.cs類オ目似。DuwamishConfiguration配置節(jié)包括如下ー些配置信息:Databaseconnectionstring(Database連接串)Duwamish.DataAccess.Connectionstring,是否允許頁面緩存Duwamish.Web.EnablePageCache,頁面緩存過期時間Duwamish.Web.PageCacheExpiresInSeconds,是否允許SSL連接Duwamish.Web.EnableSsl等等。如上所述,調用DuwamishConfigurationClass是由SystemFrameworkXApplicationConfiguration.cs的〇nApplicationStart()方法完成的:System.Configuration.Configurationsettings.GetConfig("DuwamishConfiguration");看看頁面緩存配置在webpage中如何使用的(web'book.aspx.cs文件為例):////Ifeverythingsucceeded,thenenablepagecachingasindicated//bythecurrentapplicationconfiguration.//if(DuwamishConfiguration.EnablePageCache){//EnablePageCaching...Response.Cache.SetExpires(DateTime.Now.AddSeconds(DuwamishConfiguration.PageCacheExpiresInSeconds));Response.Cache.SetCacheability(HttpCacheability.Public);在Page_Load事件中最后判斷是否允許頁面緩存。3,驗證數據合法性類ーSystemFrameworkXApplicationAssert.csSystemFrameworkXApplicationAssert.csClass用來進行錯誤檢測,并調用SystemFrameworkXApplicationLog.csClass記求錯誤1—I心、〇學習其中的部分代碼片斷:CodeSnippet1—CheckMethod[ConditionalAttribute("DEBUG")]publicstaticvoidCheck(boolcondition,StringerrorText,intlineNumber){if(!condition){StringdetaiiMessage=String.Empty;StringBuilderstrBuilder;GenerateStackTrace(lineNumber,outdetaiiMessage);strBuilder=newStringBuilder();strBuilder.Append("Assert:").Append("\r\n").Append(errorText).Append("\r\nH).Append(detailMessage);ApplicationLog.WriteWarning(strBuilder.ToStringO)3System.Diagnostics.Debug.Fail(errorText,detaiiMessage);))[C〇nditionalAttribute("DEBUG")]定義Check()方法為conditionalmethod?如果預處理符號(preprocessorsymbol)沒有定義,compiler不僅忽略該方法,而且忽略對該方法的調用,和#ifDEBUG/#else/#endif有些類似。該方法用來判斷條件condition是否為true,如果為false,則調用SystemFramework\ApplicationLog.WriteWarning()方法記錄錯誤日志。CodeSnippet2—CheckConditionMethodpublicstaticvoidCheckCondition(boolcondition,StringerrorText,intlineNumber)//Testtheconditionif(!condition){//AssertandthrowiftheconditionisnotmetStringdetaiiMessage;GenerateStackTrace(lineNumber,outdetaiiMessage);Debug.Fail(errorText,detaiiMessage);thrownewApplicationException(errorText);))該方法一般用來在進行前置條件判斷,如condition為false,則拋出exception〇4,log日志類ーSystemFrameworkXApplicationLog.csApplicationLog類實現Duwamish7.0中的記錄和跟蹤。Web.Config文件中的配置設置確定是輸出到EventLog文件、跟蹤日志文件還是兩者。下面是Web.Config文件中的<ApplicationConfiguration>節(jié),它指定EventLog設置:<ApplicationConfiguration><!—Eventlogsettings—><addkey="SystemFramework.EventLog.Enabled"value="True"/>oddkey="SystemFramework.EventLog.Machine"value="."/><addkey="SystemFramework.EventLog.SourceName"value="Duwamish7"/>oddkey="SystemFramework.EventLog.LogLever,value="1"/><!"UsethestandardTraceLevelvalues:0=Off=Error=Warning=Info=Verbose—>Web.Config文件的同一節(jié)還指定跟蹤配置。Duwamish7.0跟蹤日志的默認位置是:[安裝VisualStudio.NET的驅動器號]:'ProgramFiles'MicrosoftVisualStudio.NET2003\EnterpriseSamples'Duwamish7.0CS'Web'DuwamishTrace.txt在實際的應用系統(tǒng)開發(fā)中,用來提供Log功能的類應該比這個ApplicationLog類要好,這樣就不去分析了,如MicrosoftExceptionManagementApplicationBlock就不錯。Web.config配置文件一使用Web.congfig文件存儲application設置Duwamish7.0通過使用Forms身份驗證來實現安全性。Forms身份驗證將未經授權的用戶重定向到Web窗體,該窗體提示用戶輸入其電子郵件地址和密碼。(1)配置Forms身份驗證Web.config文件中的設置配置Forms身份驗證。對于Duwamish7.0,Web.Config文件按如下所述指定Forms身份驗證的使用:<authenticationmode="Forms"><formsname=".ADUAUTH"loginllrl="secure\logon.aspx"protection="AII"></forms></authentication><authorization><allowusers="*"/></authorization>authentication元素只能在計算機、站點或應用程序級別聲明。如果試圖在配置文件中的子目錄或頁級別上進行聲明,則將產生分析器錯誤信息。如上所示,Web.Config將.ADUAUTH指定為身份驗證Cookie的名稱。當用戶請求受限資源時,公共語言運行庫將未經授權的用戶重定向到在上面的Web.Config設置中指定的Login.aspxoprotection="AII"設置指定應用程序使用數據驗證和加密來保護Cookieo若要進ー步限制資源,Duwamish7.0會將安全資源放置到名為secure的子文件夾中并使用額外的Web.Config文件(在secure文件夾),在該文件中指定只有經過身份驗證的用戶オ可訪問該子文件夾的內容。<authorization><denyusers="?"/><allowusers="*"/></authorization><denyusers="?"/>標記指定拒絕對所有匿名用戶的訪問。vallowusers="*"/>標簽允許訪問所有已驗證身份的用戶。經過secureMogon.aspx認證通過的請求,重新定向最初的URLo〃將已驗證身份的用戶重定向回最初請求的URLoFormsAuthentication.RedirectFromLoginPage("*false);(2)用戶定義的配置節(jié)<configSections><sectionname="ApplicationConfigurationHtype="Duwamish7.SystemFramework.ApplicationConfiguration,Duwamish7.SystemFramework"/><sectionname="DuwamishConfiguration"type="Duwamish7.Common.DuwamishConfiguration,Duwamish7.Common"/><sectionname="SourceViewer"type="System.Configuration.NameValueSectionHandler,System,Version=1.0.5000.0,Culture=neutral,PublicKeyToken=b77a5c561934e089"/></configSections>section元素包含配置節(jié)聲明,name指定配置節(jié)的名稱,type指定從配置文件中讀取節(jié)的配置節(jié)處理程序類的名稱。配置節(jié)處理程序(即實現IConfigurationSectionHandler接口的類)讀取設置。上面定義了3個配置節(jié)處理程序:Duwamish7.SystemFramework.ApplicationConfigurationDuwamish7.Common.DuwamishConfigurationSystem.Configuration.NameValueSectionHandler前面兩個配置節(jié)處理程序是由application提供的,后面的System.Configuration.NameValueSectionHandler是.NetFramework提供的,該類也實現了IconfigurationSectionHandler接口,用來提供配置節(jié)中的名稱/值對配置信息。webXPageBase.es最后談談web'PageBase.cs基類吧,所有Duwamish7.0中的所有web頁都繼承名為PageBase的基類,該類實現Duwamish7.0應用程序的ASP.Net頁中使用的常見屬性和方法,這種設計方法值得推薦。CodeSnippet分析:///<summary>///Handleserrorsthatmaybeencounteredwhendisplayingthispage.//////<paramname="e">AnEventArgsthatcontainstheeventdata.</param>///</summary>protectedoverridevoidOnError(EventArgse){ApplicationLog.WriteError(ApplicationLog.FormatException(Server.GetLastError(),UNHANDLED_EXCEPTION));base.OnError(e);)重載OnError方法,使application遭遇到未處理錯誤的時候,自動調用ApplicationLog.WriteError。來記錄錯誤日土另外,覺得Duwamish的password處理有些特別,是以byte形式存放在Database中,避免明文的方式,以提高安全性(將在《Duwamish密碼分析篇》進行中分析)。Duwamish深入剖析ー結構篇摘要:本文深入詳細的介紹了Duwamish網上電子書店例程的結構框架,并詳細的分析了該結構的若干特點和設計模式。目錄:引言Duwamish介紹結構分析設計思想代碼示例總結作者引言:能夠作為VisualStudio.Net附帶的例子,Duwamish—定包含了微軟.Net設計隊伍希望向開發(fā)者傳達的某些信息,而事實上,Duwamish也的確能夠稱作是ー個.Net開發(fā)者學習的經典示例,無論是從其設計架構,編程技巧或代碼風格,都向我們展示了一個標準的.Net企業(yè)級應用程序所應該具有的特點。所以,通過研究Duwamish示例,高手能夠領悟到.Net應用架構的設計思想,低手能夠學習到.Net的編程技巧,實在是老少皆宜。:)不過,本文的目的更多的是針對中級.Net學習者,這類讀者往往已經熟悉了C#或者是VB.NET的語法,會用ー些基本的類庫,并已經會做一些比較小的程序。但是當他們開始著手開發(fā)ー個真正具有實用價值的企業(yè)級應用的時候,卻有種無處下手的感覺。如果你正巧屬于這類學習者,請跟著我深入到Duwamish的世界中去,相信你一定會得到收獲。Duwamish介紹:Microsoft公司每次推出新技術,總是會相應的推出ー些公開源代碼的應用范例來說明該項新技術的特點,而開發(fā)者也能通過研究該范例的代碼來達到迅速掌握新技術并與以實施的目的。Microsoft通過對ー個虛擬的在網上銷售圖書的電子商務公司網上銷售系統(tǒng)應用的創(chuàng)建,向用戶展現了典型的網上購物實踐中最為普遍的電子商務企業(yè)對客戶(B2C)模式,它包括成員資格、帳戶管理、購物車、搜索和結帳過程等基本功能。Duwamish經歷了三個版本4.0,5.0和7.0版,每ー個版本的發(fā)布都印證了技術進步的過程,每ー個版本都代表了當時最先進的技術動向。這里將要研究和討論的是Duwamish的最高版本7.0版,經歷了COM/C〇M+技術以及Microso代DNA架構的Duwamish,在最新的版本中完全采用了.Net技術及架構,比以前顯得更加先進和成熟。
如果您安裝了VisualStudio.Net的話,您可以在您的VS.Net的EnterpriseSamples目錄下找到并安裝它,例如:C:\ProgramFilesXMicrosoftVisualStudio.NETXEnterpriseSamplesX,或者您還可以到http:〃/Duwamish7Vb/這個地址去看看它在Internet的ー個演示實例。其它有關Duwamish的詳細介紹資料請參考VisualStudio.Net附帶的MSDN幫助,地址是:ms-help://MS.VSCC/MS.MSDNVS.2052/dwamish7/html/vtoriDuwamishBooks70.htm,這里不再贅述。Duwamish結構分析:Duwamish7.0是ー個典型的N層架構,其結構分為四個邏輯層:Web層Web層為客戶端提供對應用程序的訪問。這ー層是作為Duwamish.sln解決方案文件中的Web項目實現的。Web層由ASP.NETWeb窗體和代碼隱藏文件組成。Web窗體只是用HTML提供用戶操作,而代碼隱藏文件實現各種控件的事件處理。業(yè)務外觀層業(yè)務外觀層為Web層提供處理帳戶、類別瀏覽和購書的界面。這ー層是作為Duwamish.sln解決方案文件中的BusinessFacade項目實現的。業(yè)務外觀層用作隔離層,它將用戶界面與各種業(yè)務功能的實現隔離開來。除了低級系統(tǒng)和支持功能之外,對數據庫服務器的所有調用都是通過此程序集進行的。業(yè)務規(guī)則層業(yè)務規(guī)則層是作為Duwamish.sln解決方案文件中的BusinessRules項目實現的,它包含各種業(yè)務規(guī)則和邏輯的實現。業(yè)務規(guī)則完成如客戶帳戶和書籍訂單的驗證這樣的任務。數據訪問層數據訪問層為業(yè)務規(guī)則層提供數據服務。這ー層是作為Duwamish.sln解決方案文件中的DataAccess項目實現的。比較令人困惑的是其中的業(yè)務外觀層和業(yè)務規(guī)則層,很多人在學習N層結構開發(fā)的時候,聽得最多的是三層結構,分別為:表示層,中間層和數據層。Duwamish的WEB層和數據訪問層比較好理解,也就是傳統(tǒng)意義上的表示層和數據層,那么業(yè)務外觀層和業(yè)務規(guī)則層和我們熟悉的中間層有什么聯系呢?設計思想:在Web應用程序中,有部分操作只是簡單的從數據庫根據條件提取數據,不需要經過任何處理,而直接將數據顯示到網頁上,比如查詢某類別的圖書列表。而另外一些操作,比如計算定單中圖書的總價并根據顧客的級別計算回扣等等,這部分往往有許多不同的功能的類,操作起來也比較復雜。我們可以先想象一下,如果我們采用三層結構,這些商業(yè)邏輯一般是會放在中間層,那么對內部的這些大量種類繁多,使用方法也各異的不同的類的調用任務,就完全落到了表示層。這樣勢必會增加表示層的代碼量,將表示層的任務復雜化,和表示層只負責接受用戶的輸入并返回結果的任務不太相稱,并增加了層與層之間的耦合程度。為了解決這個問題,我們先來看看《設計模式》一文中對Facade模式的描述:意圖:為子系統(tǒng)中的ー組接口提供ー個一致的界面,Facade模式定義了一個高層接口,這個接口使得這一子系統(tǒng)更加容易使用。適用性;當你要為ー個復雜子系統(tǒng)提供ー個簡單接口時。子系統(tǒng)往往因為不斷演化而變得越來越復雜。大多數模式使用時都會產生更多更小的類。這使得子系統(tǒng)更具可重用性,也更容易對子系統(tǒng)進行定制,但這也給那些不需要定制子系統(tǒng)的用戶帶來ー些使用上的困難。Facade可以提供ー個簡單的缺省視圖,這ー視圖對大多數用戶來說已經足夠,而那些需要更多的可定制性的用戶可以越過Facade層??蛻舫绦蚺c抽象類的實現部分之間存在著很大的依賴性。引入Facade將這個子系統(tǒng)與客戶以及其他的子系統(tǒng)分離,可以提高子系統(tǒng)的獨立性和可移植性。當你需要構建一個層次結構的子系統(tǒng)時,使用Facade模式定義子系統(tǒng)中每層的入口點。如果子系統(tǒng)之間是相互依賴的,你可以讓它們僅通過Facade進行通訊,從而簡化了它們之間的依賴關系。結構圖:
上文提出的這個矛盾,正好和設計模式中Facade模式中所描述的需要解決的問題非常吻合,在《設計模式》中提出的解決的辦法就是引入ー個Facade對象,讓這個Façade來負責管理系統(tǒng)內部類的調用,并為表示層提供了一個單一而簡單的接口。這個Façade對象,在我們的Duwamish的設計中,就是BusinessFacade(業(yè)務外觀)層。以下是Duwamish的結構關系圖:.NETg^m業(yè)務外理身瀏寬器專瀏覚鵲身瀏覽器結構關系忸客尸篇下列系統(tǒng)的公共入口點:.NETg^m業(yè)務外理身瀏寬器專瀏覚鵲身瀏覽器結構關系忸客尸篇下列系統(tǒng)的公共入口點:??窖尸系統(tǒng)?訂單系線?產品系故用于莒理以下方面的業(yè)務黑則:?訂單-客戶散砧ジ問莒理所有低級數據訪問的英?SQLServer系統(tǒng)框架?應用程序配置-異常處理-日志記錄通用-用于書0、類別、客戶和訂単的自定義生成的數將集A?應用程序配置注我:衛(wèi)頭應解再為“.使用 "-例如:“數據訪問”子系統(tǒng)正在使用“系統(tǒng)框架”子系我?我們從圖中可以清楚的看到,瀏覽器首先調用的是表示層WEB,然后WEB將請求發(fā)送給業(yè)務外觀層,業(yè)務外觀層對請求進行初步的處理,判斷是否需要調用業(yè)務規(guī)則層,還是直接調用數據訪問層獲取數據。最后由數據訪問層訪問數據庫并按照來時的步驟返回結果到瀏覽器(對于圖中涉及到其它的結構模塊以后會分別予以詳細介紹)。代碼示例:以下是兩種不同處理路徑的代碼示例:獲取商品目錄表示層調用業(yè)務外觀層:productsystem=newProductSystem();categorySet=productsystem.GetCategories(categoryID);業(yè)務外觀層直接調用數據層:publicCategoryDataGetCategories(intcategoryId)(if(dsCommand==nulI)(thrownewSystem_ObjectDisposedException(GetType()_Fu11Name);}returnFiIICategoryData(MGetCategoriesM5“?CategoryId",categoryId);}添加定單表示層調用業(yè)務外觀層:publicvoidAddOrder()AppIicationAssert.CheckCondition(cartOrderData!=null,"Orderrequiresdata",AppIicationAssert.LineNumber);AppIicationLog.WriteTrace("Duwamish7.Web.Cart.AddOrder:\r\nCustomerId:"+cartOrderData.Tables[OrderData.CUSTOMER_TABLE].Rows[0][0rderData.PKID_FIELD].ToString());cartOrderData=(new0rderSystem()).AddOrder(cartOrderData);}業(yè)務外觀層調用業(yè)務規(guī)則層:publicOrderDataAddOrder(0rderDataorder){AppIicationAssert.CheckCondition(order!=null,''Orderisrequired",AppIicationAssert.LineNumber);(newBusinessRules.Order()).InsertOrder(order);returnorder;}業(yè)務規(guī)則層調用數據層:publicboolInsertOrder(OrderDataorder){//此處省略復雜的處理邏輯if(isValid)(using(DataAccess.OrdersordersDataAccess=newDataAccess.0rders())return(ordersDataAccess.InsertOrderDetaiI(order))>0;}}elsereturnfalse;}總結:通過分析Duwamish7的結構設計,我們掌握了Façade模式,并學習到了如何通過Façade模式對應用結構進行改進,同時了解了Duwamish7的基本概念和處理流程,為以后深入分析和學習Duwamish7的的其它部分打下了一個基礎。PetShop的系統(tǒng)架構設計《解剖PetShop》系列之ー前言:PetShop是一個范例,微軟用它來展示.Net企業(yè)系統(tǒng)開發(fā)的能力。業(yè)界有許多.Net與J2EE之爭,許多數據是從微軟的PetShop和Sun的PetStore而來。這種爭論不可避免帶有濃厚的商業(yè)色彩,對于我們開發(fā)人員而言,沒有必要過多關注。然而PetShop隨著版本的不斷更新,至現在基于.Net2.0的PetShop4.0為止,整個設計逐漸變得成熟而優(yōu)雅,卻又很多可以借鑒之處。PetShop是ー個小型的項目,系統(tǒng)架構與代碼都比較簡單,卻也凸現了許多頗有價值的設計與開發(fā)理念。本系列試圖對PetShop作一個全方位的解剖,依據的代碼是PetShop4.0,可以從鏈接/library/default.asp7url=/library/en-us/dnbda/html/bdasamppet4.asp中獲得。ー、PetShop的系統(tǒng)架構設計在軟件體系架構設計中,分層式結構是最常見,也是最重要的ー種結構。微軟推薦的分層式結構一般分為三層,從下至上分別為:數據訪問層、業(yè)務邏輯層(又或成為領域層)、表示層,如圖所示:
圖ー:三層的分層式結構數據訪問層:有時候也稱為是持久層,其功能主要是負責數據庫的訪問。簡單的說法就是實現對數據表的Select,Insert,Update,Delete的操作。如果要加入ORM的元素,那么就會包括對象和數據表之間的mapping,以及對象實體的持久化。在PetShop的數據訪問層中,并沒有使用〇RM,從而導致了代碼量的增加,可以看作是整個設計實現中的一大敗筆。業(yè)務邏輯層:是整個系統(tǒng)的核心,它與這個系統(tǒng)的業(yè)務(領域)有關。以PetShop為例,業(yè)務邏輯層的相關設計,均和網上寵物店特有的邏輯相關,例如查詢寵物,下訂單,添加寵物到購物車等等。如果涉及到數據庫的訪問,則調用數據訪問層。表示層:是系統(tǒng)的UI部分,負責使用者與整個系統(tǒng)的交互。在這ー層中,理想的狀態(tài)是不應包括系統(tǒng)的業(yè)務邏輯。表示層中的邏輯代碼,僅與界面元素有關。在Petshop中,是利用ASP.Net來設計的,因此包含了許多Web控件和相關邏輯。分層式結構究竟其優(yōu)勢何在?MartinFowler在《PatternsofEnterpriseApplicationArchitecture》ー書中給出了答案:1、開發(fā)人員可以只關注整個結構中的其中某ー層;2、可以很容易的用新的實現來替換原有層次的實現;3、可以降低層與層之間的依賴;4、有利于標準化;5、利于各層邏輯的復用。概括來說,分層式設計可以達至如下目的:分散關注、松散耦合、邏輯復用、標準定義。ー個好的分層式結構,可以使得開發(fā)人員的分工更加明確。一旦定義好各層次之間的接口,負責不同邏輯設計的開發(fā)人員就可以分散關注,齊頭并進。例如UI人員只需考慮用戶界面的體驗與操作,領域的設計人員可以僅關注業(yè)務邏輯的設計,而數據庫設計人員也不必為繁瑣的用戶交互而頭疼了。每個開發(fā)人員的任務得到了確認,開發(fā)進度就可以迅速的提高。松散耦合的好處是顯而易見的。如果一個系統(tǒng)沒有分層,那么各自的邏輯都緊緊糾纏在ー起,彼此間相互依賴,誰都是不可替換的。一旦發(fā)生改變,則牽ー發(fā)而動全身,對項目的影響極為嚴重。降低層與層間的依賴性,既可以良好地保證未來的可擴展,在復用性上也是優(yōu)勢明顯。每個功能模塊ー旦定義好統(tǒng)一的接口,就可以被各個模塊所調用,而不用為相同的功能進行重復地開發(fā)。進行好的分層式結構設計,標準也是必不可少的。只有在一定程度的標準化基礎上,這個系統(tǒng)オ是可擴展的,可替換的。而層與層之間的通信也必然保證了接口的標準化?!敖馃o足赤,人無完人”,分層式結構也不可避免具有一些缺陷:1、降低了系統(tǒng)的性能。這是不言而喻的。如果不采用分層式結構,很多業(yè)務可以直接造訪數據庫,以此獲取相應的數據,如今卻必須通過中間層來完成。2、有時會導致級聯的修改。這種修改尤其體現在自上而下的方向。如果在表示層中需要增加一個功能,為保證其設計符合分層式結構,可能需要在相應的業(yè)務邏輯層和數據訪問層中都增加相應的代碼。前面提到,PetShop的表示層是用ASP.Net設計的,也就是說,它應是ー個BS系統(tǒng)。在.Net中,標準的BS分層式結構如下圖所示:圖二:.Net中標準的BS分層式結構隨著PetShop版本的更新,其分層式結構也在不斷的完善,例如PetShop2.0,就沒有采用標準的三層式結構,如圖三:PresentationTierBusinessLogicTierDAABSQLServer2000
Accounts,ProductsSQLServer2000
OrdersPresentationTierBusinessLogicTierDAABSQLServer2000
Accounts,ProductsSQLServer2000
Orders圖三:PetShop2.0的體系架構從圖中我們可以看到,并沒有明顯的數據訪問層設計。這樣的設計雖然提高了數據訪問的性能,但也同時導致了業(yè)務邏輯層與數據訪問的職責混亂。一旦要求支持的數據庫發(fā)生變化,或者需要修改數據訪問的邏輯,由于沒有清晰的分層,會導致項目作大的修改。而隨著硬件系統(tǒng)性能的提高,以及充分利用緩存、異步處理等機制,分層式結構所帶來的性能影響幾乎可以忽略不計。PetShop3.0糾正了此前層次不明的問題,將數據訪問邏輯作為單獨的ー層獨立出來:PresentationTierASP.NETPresentationTierASP.NETWebFormsUserInterraceProcessingBusinessLogicTierBusinessComponentsEnterpriseServicesBusinessEnsesDataAccessLayerDALInterfaceDALFactoryBusinessLogicTierBusinessComponentsEnterpriseServicesBusinessEnsesDataAccessLayerDALInterfaceDALFactory圖四:PetShop3.0的體系架構PetShop4.0基本上延續(xù)了3.0的結構,但在性能上作了一定的改進,引入了緩存和異步處理機制,同時又充分利用了ASP.Net2.0的新功能Membership,因止匕PetShop4.0的系統(tǒng)架構圖如下所示:BusinessL09C
U)tfDMaAccess
UytrPresentationCt&ieinttiUmpont^iCMtoty.P^duainventorynemi0foMcirtMeflbtnhip
齢他rOmhMtabenhip^oviderProfleDALinterteFtOory[oetde]ISO”(HerEmoc
Cooo*"ot)OABusinessCoopootntshveolwyandOfdvsDaoAccess
iMrWeIE]FOftde||SQLIIQAi[ID/^JSQLM/SQL2K5
€hde1H
UemMh9DtibMe
SO.MlSOUKS
Oodtflg
PiolieOObese
SCIHHSOUKS
OrxZ"
OlderDiuuse
SQLHHSOUKS
Orach*
mwrtoryOitMe
"S''JAsyncfronotAOrders圖五:PetShop4.0的體系架構比較3.0和4.0的系統(tǒng)架構圖,其核心的內容并沒有發(fā)生變化。在數據訪問層(DAL)中,仍然采用DALInterface抽象出數據訪問邏輯,并以DALFactory作為數據訪問層對象的工廠模塊。對于DALInterface而言,分別有支持MS-SQL的SQLServerDAL和支持Oracle的OracleDAL具體實現。而Model模塊則包含了數據實體對象。其詳細的模塊結構圖如下所示:
圖六:數據訪問層的模塊結構圖可以看到,在數據訪問層中,完全采用了“面向接口編程”思想。抽象出來的IDAL模塊,脫離了與具體數據庫的依賴,從而使得整個數據訪問層利于數據庫遷移。DALFactory模塊專門管理DAL對象的創(chuàng)建,便于業(yè)務邏輯層訪問。SQLServerDAL和OracleDAL模塊均實現!DAL模塊的接ロ,其中包含的邏輯就是對數據庫的Select,Insert,Update和Delete操作。因為數據庫類型的不同,對數據庫的操作也有所不同,代碼也會因此有所區(qū)別。此外,抽象出來的IDAL模塊,除了解除了向下的依賴之外,對于其上的業(yè)務邏輯層,同樣僅存在弱依賴關系,如下圖所示:業(yè)務邏輯層對業(yè)務、(策略的抽象封裝。IBLLStrategy——K 業(yè)務避風層?核心的業(yè)、個 ~~ 務代64都在本模塊屮?BLL圖七:業(yè)務邏輯層的模塊結構圖圖七中BLL是業(yè)務邏輯層的核心模塊,它包含了整個系統(tǒng)的核心業(yè)務。在業(yè)務邏輯層中,不能直接訪問數據庫,而必須通過數據訪問層。注意圖中對數據訪問業(yè)務的調用,是通過接口模塊IDAL來完成的。既然與具體的數據訪問邏輯無關,則層與層之間的關系就是松散耦合的。如果此時需要修改數據訪問層的具體實現,只要不涉及到IDAL的接口定義,那么業(yè)務邏輯層就不會受到任何影響。畢竟,具體實現的SQLServerDAL和〇racalDAL根本就與業(yè)務邏輯層沒有半點關系。因為在Petshop4.0中引入了異步處理機制。插入訂單的策略可以分為同步和異步,兩者的插入策略明顯不同,但對于調用者而言,插入訂單的接口是完全一樣的,所以PetShop4.0中設計了IBLLStrategy模塊。雖然在IBLLStrategy模塊中,僅僅是簡單的10rderStategy,但同時也給出了一個范例和信息,那就是在業(yè)務邏輯的處理中,如果存在業(yè)務操作的多樣化,或者是今后可能的變化,均應利用抽象的原理。或者使用接口,或者使用抽象類,從而脫離對具體業(yè)務的依賴。不過在PetShop中,由于業(yè)務邏輯相對簡單,這種思想體現得不夠明顯。也正因為此,PetShop將核心的業(yè)務邏輯都放到了一個模塊BLL中,并沒有將具體的實現和抽象嚴格的按照模塊分開。所以表示層和業(yè)務邏輯層之間的調用關系,其耦合度相對較高:圖八:表示層的模塊結構圖在圖五中,各個層次中還引入了輔助的模塊,如數據訪問層的Messaging模塊,是為異步插入訂單的功能提供,采用「MSMQ(MicrosoftMessagingQueue)技術。而表示層的CacheDependency則提供緩存功能。這些特殊的模塊,我會在此后的文章中詳細介紹。Microsoft.NETPetShop4架構與技術分析分類:.NET技術開發(fā)2006-04-1722:1510886人閱讀評論(7)收藏舉報1.項目概述與架構分析微軟剛推出了基于ASP.NET2.0下的PetShop4,該版本有了ー個全新的用戶界面。是研究ASP.NET2.0的好范例啊,大家都知道,一直以來,在.NET和Java之間爭論不休,到底使用哪個平臺開發(fā)的企業(yè)級應用性能最好、結構最優(yōu)、生產カ最高。為了用事實說話,通過對項目各方面的性能評估進而在比較.NET和Java的高下。用戶做比較的這個項目就是Petshop〇正因為Petshop肩負著上面所說的重任,各方面必須是最優(yōu)的,架構設計應該是經過慎重考慮的。所以其ー經推出,便成為了開發(fā)者、架構師等人學習、研究的典范。
日前微軟推出了基于.NETFramework2.0開發(fā)的Petshop4〇新的Petshop4實現了與Petshop3相同甚至更多的特性,由于采用了MasterPages,Membership,以及Profile,SqlCacheDependency,但是代碼量卻減少了四分之一。同時,在事務、數據緩存、安全方面使用了.NET2.0附帶的特性,構建了一個靈活的最佳實踐的應用程序。TH€.H€TP€TSHOPTH€.H€TP€TSHOPExploreourwideselectionofwhatcouldb9yourfuturepetOurCstegorieBIRDSBUGSBACKYARDENDANGEREDFISH他們利用了ProjectConversionWizard把項目從ASP.NET1.1移植至リ了ASP.NET2.0,然后做了以下改動:.用System.Transactions代替了原來的ServicedComponent提供的事務功能代碼實現:PetShop.BLL.OrderSynchronous的publicvoidInsert(PetShop.Model.Orderinfoorder)〇.用強類型的范型集合代替了原來的弱類型集合publicIList<ProductInfo>publicGetProductsByCategory(stringcategory)//Returnnewifthestringisemptyif(string.IsNullOrEmpty(category))returnnewListくProductInfo〉();//Runasearchagainstthedatastorereturndal.GetProductsByCategory(category);}.采用ASP.NET2.0Membership來做認證和授權.創(chuàng)建了針對Oracle10g的CustomASP.NET2.0MembershipProvider.利用ASP.NET2.0的CustomOracle和SQLServerProfileProviders做用戶狀態(tài)管理,包括購物車等.采用了MasterPages,取代了原來的用戶控件,來實現統(tǒng)一的界面效果.使用了ASP.NET2.0Wizard控件實現check-out.使用了SqlCacheDependency來實現數據庫層次的緩存更新(cacheinvalidation)功能.使用了消息隊列來實現異時訂單處理。
2.整體架構:ASPNET20ASPNETForms,UserControls.MasterPage.WizardCacheDependencyPresentation
LayeriCacheDependencyFAeni)er>hipRoviderRofileProviderCacheOependencyfactoryBusinessLogic
LayerDataAccess
LayerMembershipSecuhty.Useraccosts.Login
ControlsRofileShoppngCart.Wish
LstUsersProiieTableCacheDependencyBusinessComponentsClBusinessComponentsCategory.Product.Inventory.Items.Ordeo.CartSynchOrderOrderStratSqlMembershipRoviderSQL20M2.整體架構:ASPNET20ASPNETForms,UserControls.MasterPage.WizardCacheDependencyPresentation
LayeriCacheDependencyFAeni)er>hipRoviderRofileProviderCacheOependencyfactoryBusinessLogic
LayerDataAccess
LayerMembershipSecuhty.Useraccosts.Login
ControlsRofileShoppngCart.Wish
LstUsersProiieTableCacheDependencyBusinessComponentsClBusinessComponentsCategory.Product.Inventory.Items.Ordeo.CartSynchOrderOrderStratSqlMembershipRoviderSQL20M/SQLMS
Oracle10g
Membemh<)DatabaseSQLX”/SQL2K5Oode10g
ProiieDatabaseSQL2WI/SQL2K5Orach10g
OrderDatabaseSQL2MI/SOrachInventoryD數據庫:(暫略)項目列表:從整體可以看出,PetShop4的項目體系已經很龐大,考慮的方面也較3.0更全面復雜。;解決方案’PetShop'(22個項目)J.SolutionItems田就BLL+.Jp]CacheDependencyFactory用_<D:\...\feb\\±).車DALFactoryf.5]DBUtility+.司IBLLStrategy上@!ICacheDependency:±序IDAL土,,摩!IMessaging+,項!ProfileDAL+.JpMembership+MessagingFactory.豆!Model+?yHSMQMessagingナ必OracleDAL+33OracleProfileDAL+孕OrderProcessor\±i@1Profile+33ProfileDALFactory比.車SQLProfileDAL+33SQLServerDAL+.JpTableC
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 【假期提升】五升六語文暑假作業(yè)(九)-人教部編版(含答案含解析)
- 酒店用品銷售代理合同(2篇)
- 采購分包配送合同(2篇)
- 廣告行業(yè)廣告創(chuàng)意版權保護協(xié)議
- 社區(qū)農業(yè)服務提供合同書
- 企業(yè)采購流程管理與成本控制手冊
- 金融行業(yè)風險控制實踐操作指南
- 山東省濱州市鄒平市2024-2025學年八年級上學期期末生物學試題(含答案)
- 旅游景區(qū)旅游資源開發(fā)與利用策略分析
- 酒店客房入住信息表格
- 計算機應用基礎教程(Windows10+Office2016)PPT全套完整教學課件
- 部編人教版二年級道德與法治下冊同步練習(全冊)
- 消化內科實習生入科教育
- 第二章-幼兒園課程的基礎課件
- 后路腰椎椎間融合翻修術
- 食材配送企業(yè)管理制度(完整)
- (帶答案)初中物理第八章運動和力重難點歸納
- 梅毒的診斷與治療資料
- 報價單模板完整版
- GB/T 18658-2018擺錘式沖擊試驗機間接檢驗用夏比V型缺口標準試樣
- 罰款單的模板
評論
0/150
提交評論