Dorado用法與示例
dorado用后總結
一.dorado概念
dorado的產品全名是“dorado展現中間件”。從產品形態上dorado由兩部分組成,第一部分是一個具有AJAX特征的Web應用表現層的快速開發框架,第二部分配套的IDE開發工具。開發工具又可分為獨立的dorado studio與eclipse插件兩個選擇,eclipse插件將在以后發布,本文的開發工具專指dorado studio。
Web表現層方面的產品主要技術流派有離散控件構架、后台衍伸構架、展現中間件構架等數種。離散控件構架多是一套各個控件互不相關的JavaScript庫,如bindows,后台衍伸構架多是為專有的后台業務邏輯框架服務,如工作流的表單設計器。展現中間件構架提Wedget Lib(表現層控件庫)並由展現層引擎統一驅動與管理。控件使用的個數越多種類越多,越有效用。可對接的業務邏輯層也不限於某種框架,可以廣泛地通過整合 接口與各種第三方后台邏輯框架相整合。還可以通過展現層引擎整合基於離散控件架構的Web表現層產品,進一步增強Web的展現力、操作性與承載量,同時提高開發效率。
二.dorado主要包含5個組成部分
- 富瀏覽器客戶端:基於標准瀏覽器技術,增強web界面的信息承載量、表現力與操作性。包含了應用客戶端常用表格、樹、表單、多頁標簽等一整套界面組件
- 展現引擎:支持AJAX特性,用於增強dorado客戶端的交互能力。
- MVC開發框架:包括數據持久層的實現、頁面流控制、展現層角色機制、國際化資源管理、配置管理與監控控制台等。既可自成體系,又可與各種開發模式與框架相結合。
- 集成開發工具:dorado專用的IDE,可進一步提升開發速度。
- 應用框架:又稱marmot,用於為基於Struts、WebWork、Spring、 Hibernate、iBatis等開源框架的開發模式提供與Dorado集成的范例性的實現代碼。其中包含了應用主框架、完整權限的框架、用戶 Profile管理、即時消息等實用功能的實現代碼。
三.在項目里引入dorado
1. 在web.xml里面追加如下代碼:
Xml代碼
- <!-- Dorado Serlvet -->
- <servlet>
- <servlet-name>dorado-servlet</servlet-name>
- <servlet-class>com.bstek.dorado.core.DoradoServlet</servlet-class>
- <load-on-startup>2</load-on-startup>
- </servlet>
- <servlet-mapping>
- <servlet-name>dorado-servlet</servlet-name>
- <url-pattern>*.d</url-pattern>
- 10. </servlet-mapping>
- 11.
- 12. <!-- Dorado Filter -->
- 13. <filter>
- 14. <filter-name>GZIPEncoder</filter-name>
- 15. <filter-class>com.bstek.dorado.core.GZIPEncodeFilter</filter-class>
- 16. </filter>
- 17. <filter>
- 18. <filter-name>dorado-filter</filter-name>
- 19. <filter-class>com.bstek.dorado.core.DoradoFilter</filter-class>
- 20. </filter>
- 21. <filter-mapping>
- 22. <filter-name>GZIPEncoder</filter-name>
- 23. <url-pattern>*.jsp</url-pattern>
- 24. </filter-mapping>
- 25. <filter-mapping>
- 26. <filter-name>dorado-filter</filter-name>
- 27. <url-pattern>*.d</url-pattern>
- 28. </filter-mapping>
- 29. <filter-mapping>
- 30. <filter-name>dorado-filter</filter-name>
- 31. <url-pattern>*.do</url-pattern>
- 32. </filter-mapping>
- 33. <filter-mapping>
- 34. <filter-name>dorado-filter</filter-name>
- 35. <url-pattern>*.action</url-pattern>
- 36. </filter-mapping>
- 37.
38. <jsp-config>
- 39. <taglib>
- 40. <taglib-uri>http://www.bstek.com/dorado</taglib-uri>
- 41. <taglib-location>/WEB-INF/dorado.tld</taglib-location>
- 42. </taglib>
43. </jsp-config>
2. 在lib目錄里加入如下jar包
Html代碼
- dorado5-action.jar
- dorado5-admin.jar
- dorado5-biz.jar
- dorado5-common.jar
- dorado5-core.jar
- dorado5-data.jar
- dorado5-designsrv.jar
- dorado5-i18n.jar
- dorado5-module.jar
10. dorado5-security.jar
11. dorado5-smartweb.jar
12. dorado5-utils.jar
13. dorado5-view.jar
3. 在項目中加入home目錄,跟src目錄同級別,里面的內容可以從doradosample里去拷貝過來。
四. 使用過程中遇到的問題
1. 如何使用項目中的自定義連接,不用dorado默認的連接
在dorado的說明文檔上有關於這個問題的說明,其中說明里寫道
<property name="common.transactionHandler" value=""/> |
這樣可以禁用 dorado本身的事務管理。
使用自定連接的時候,在home目錄的setting.xml文件里一定不要加入這句話。
2. 使用marmot框架的前提是項目必須要使用spring框架,如果沒有用spring的話,marmot就沒法用了。
因為marmot里指定的dataprovider必須是spring配置文件的bean別名。
五. dorado的優缺點
優點:畫面確實很美觀,簡單的業務邏輯開發效率極高。幾乎可以不用寫代碼就能完成,提供了豐富的到處
功能。對表格的展現不得不說是很棒的。
缺點:當開發復雜的業務邏輯是,感覺里面的屬性完全不夠用。由於封裝性,原本可以在客戶端的開發變得
麻煩。提供的api不夠豐富,詳細。尤其是訪問dataset的時候。而且必須要引入spring,對於只用struts
的項目來說,比較無賴。
Dorado知識點總結
- Dorado 展現中間件產品包含主要的功能 WEB客戶端 。IDE集成開發。服務端引擎
- DORADO是 WEB展現層的 中間件。
- Dorado7提供了以資源包的形式對 JavaScript和CSS 文件進行管理的功能,不但系統內部的庫文件以此種方式進行管理,用戶也可以將自己的庫文件納入這一管理機制。通過這一功能,用戶可以定義各資源包之間的依賴關系、實現庫文件的運行時自動合並、以及庫文件的按需裝載。這可以在性能優化、項目維護等方面帶來諸多好處。
- 立體數據模型 是Dorado7最重要的概念,也是Dorado7最為核心的設計思想,這使得Dorado7不再局限數據必須以二維表結構與DataSet對接,而是可以支持非常自由的數據形式。這些變化使得展現層中的數據更加純粹、更加貼切真實的業務含義。自然,也使開發變得更加便利、更加生動
- Dorado7以 XML 形式的視圖配置文件作為定義Web界面的主要手段。
- 智能方法匹配是指允許開發人員盡可能按照自己的意願、業務的需要來定義業務方法,然后由Dorado引擎自動根據場景、參數名、參數類型等因素來判斷應當怎樣調用該業務方法。“該功能”是Dorado7提供的一個非常有特色的功能,提供此功能的主要目的是盡量減少開發人員所需要掌握的Dorado API,讓業務方法的代碼更加”業務化”,更加易於閱讀。通過“該功能”也可以很好的體驗出Dorado7所提倡的“基於約定而非配置”進行開發的理念。在實際的應用場景中大部分實現了Dorado前端的功能中可能並不需要引入任何Dorado的API。
- Dorado7提倡 基於約定而非配置 的理念進行開發。
- Dorado7中的數據模型對象既支持 全局、私有、匿名等可見性,又支持類似面向對象的繼承和復寫。這些特性可以為配置信息的重用和維護提供很多的便利。
- Dorado7 IDE采用Plug-in技術,以插件形式與 Eclipse開發環境融為一體。
10. Dorado7的視圖配置文件后綴是 view.xml 網址默認是。D
11. DataType分為以下三類:簡單DataType、聚合DataType、實體DataType,List、Set 、Array 屬於聚合DataType。
12. EntityList 表示數據實體的集合,是Dorado中展現數據的載體
13. DataProvider是數據提供者,是一種用於為dorado展現層提供數據的對象。
“該功能”通常的作用是根據其自身的定義和外部傳入的參數調用后台業務邏輯層的業務方法,對得到的返回加以封裝,變成展現數據然后返回給外界。
盡管DataType具有自動根據數據的Class類型進行映射的功能,不過仍然可以通過“該功能”的resultDataType屬性為將要返回的數據手工指定“該對象”。
“該功能”具有類型的概念,可以用不同類型的“該功能”封裝不同種的展現數據獲取方式。用戶可以創建自己的“該功能”類型。如同Dorado5中的Dataset也可以有各種類型
14. DataType即數據類型,是dorado7中全新的、最關鍵的概念之一。
“該功能”實現的功能有點類似復雜的數據字典,用於描述各種數據。如描述某數據實體中每個屬性的標題、顯示格式、校驗規則等等。
對於基於ORM開發的Web應用而言,Dorado能夠自動的根據VO的Class類型為其分配適當的“該功能”。
“該功能”可以描述通常所見的所有類型的數據,既包含用戶定義的POJO,也包含了Java中的簡單數據類型。如定義一個“該功能”用來描述系統中的java.util.Date這種數據,這樣就可以通過“該功能”為所有的日期類數據定義默認的輸出格式。
“該功能”是一種在服務端和客戶端都存在生命周期的對象,即在服務端和客戶端都可以使用,因此“該功能”支持一些在客戶端才有的特性,如EntityDataType支持名為afterDataChanged的客戶端事件,每當有屬於該類型的實體對象的某屬性值在客戶端被修改時,此事件就會被觸發。
15. DataPath可稱為數據路徑,在Dorado的客戶端所使用的,用於描述如何提取、挖掘數據的表達式。
“該功能”是在Dorado的客戶端所使用的,用於描述如何提取、挖掘數據的表達式。作用比較類似於XML中所使用的XPath。
16. DataResolver是數據處理器,是一種用於將dorado中的展現數據提供給后台業務邏輯層的對象。
“該功能”的作用大致與DataProvider相反,一般而言“該功能”調用的,都是后台業務邏輯層中與數據持久化相關的操作。
“該功能”也具有類型的概念,不同類型的“該功能”封裝有不同種的展現數據處理或持久化方式。用戶可以創建自己的“該功能”類型。
17. DataSet是數據的容器,主要的生命周期是在客戶端,主要作用是用於包含展現數據。
“該功能”最主要的生命周期是在客戶端,主要作用是用於包含展現數據。主要作用是為一組展現數據起個別名,以便於數據敏感控件和開發人員使用,而“該功能”的id就是這堆展現數據的別名。
“該功能”本身是一個輕量級對象,與Dorado5中的“該功能”不同,沒有類型之分。“該功能”中所包含的數據由其中的DataProvider所返回的數據決定。
“該功能”支持利用DataPath對其中的數據進行快速的挖掘。
18. dorado工程在WEB-INF目錄下會包含一個dorado-home 的文件夾,用於定義dorado的一些系統全局配置和關鍵的spring配置
19. context.xml是dorado的核心配置文件
20. config.properties是dorado的屬性配置文件
21. packages-config.xml是JS文件和相關客戶端資源文件的打包規則設定文件。
22. servlet-context.xml是用於存放SpringMVC相關的配置文件
23. w3c-html4-template.html是dorado視圖的默認模板
24. dorado中默認提供了多種運行機制:production(生產環境),test(測試),debug(開發和測試)
25. 視圖配置文件view通常包含Arguments、 Model、View 、Context節點。
26. 在dorado中一般將控件區分為不可見控件和可見控件
27. DockLayout(停靠式布局)、FormLayout(表單式布局)、AnchorLayout(錨定式布局)是Dorado7目前提供的布局管理器
28. 在Dorado7中服務定位表達式是用來描述服務的查找方式,即Dorado7通過服務定位表達式來查找到具體服務,以便於對服務進行調用。基本格式:協議:服務名[#方法名]
29. 動態EL表達式是在普通EL表達式基礎上的進一步擴展,動態EL表達式以__ 的方式定義。$${expression}
30. Dorado7中量身定制了全新的Debugger,用於輔助開發人員做系統調試。可以在瀏覽器中直接按 F2 或 Ctrl+F2打開Dorado Debugger小工具。
31. AutoForm中stretchWidth 是否將表單的寬度自動擴展為撐滿容器
32. AutoForm中editorWidth用於統一設置內部AutoFormElement的文本編輯框的寬度。
33. 通常將一個二維表結構的數據,以 Grid形式展現給用戶
34. 在Grid中RowSelectorColumn為選擇器列,一般用於輔助表格的多選功能。
35. 在Grid中添加行號列應選擇RowNumColumn
36. 在Grid中添加組合列應選擇ColumnGroup
37. AjaxAction 用於執行遠程過程的動作控件。此控件僅在配合Dorado服務端的開發模式中有意義。
38. AjaxAction調用的服務一般都需要使用@Expose 標記注冊
39. UpdateAction用於提交動作控件。此控件僅在配合Dorado服務端的開發模式中有意義。
40. UpdateAction對應服務器端接受該請求的代碼一般都通過DataResolver 標記注冊。
41. Ajax檢驗 正則表達式長度檢驗,都是DORADO默認提供的校驗器。
42. SplitPanel的主要作用是通過分隔欄將頁面上的空間分為兩塊。
43. Data Pilot一般情況下都是與DataGrid控件配合使用,用於在Grid中數據的增刪改和當前記錄的定位功能,提供了翻頁數據顯示的功能。
44. Data DropDown一般用於顯示和選擇日期的下拉控件
45. DataTreeGrid一般用於樹狀表格展現控件是
46. Menu一般用於展現常見的菜單工具欄式的菜單的控件
47. BDF2中所有模塊,皆以 __ 形式存在,以於一些需要在頁面中展現的元素,諸如報表展現、用戶個性化、數據導出等,全部以標准Dorado7組件形式提供 Dorado7 Addon。
48. BDF2功能模塊可根據項目情況靈活選擇需要使用,同時創建的項目支持Maven與標准的Dynamic web project兩種格式。
49. BDF中提供了流程管理操作常用的API、流程模塊的管理與配置、流程模塊的在線調試等眾多常用的流程功能的模塊是UFLO。
50. BDF中提供了在應用服務端,定義一些可以周期性執行的動作任務調試的任務調試模塊是BDF2-JOB。
51. BDF中提供了報表在一個基於WEB的運行環境,利用該模塊,可以實現報表在WEB環境中導出、在線顯示、在線打印等功能的模塊是BDF2-JASPERREPORTS
52. BDF中提供了一個調用Webservice服務的客戶端,利用這個客戶端,通過幾行簡單的代碼,就可以實現對目標Webservice服務的調用的模塊是BDF2-WEBservice-CLENT
53. BDF中提供了權限下放管理功能的模塊是BDF2-AUTHORITYDELEGATION。(所謂權限下放管理即系統超級管理員,通過定義一些用戶為下級管理員,分配一些可以管理的用戶、部門、崗位、群組及URL資源,具有權限管理的功能。)
54. BDF中提供了以Datagrid或者Autoform為顯示模板,導出其數據為PDF或者Excel格式,支持Datagrid控件中filterBar數據過濾導出、列頭組合自定義、數據自定義導出等功能的模塊是BDF2-EXPORT。
55. BDF中提供了主要excel導入功能,可以將存放於Excel當中的數據批量導出到數據庫(或者其它存儲介質)的模塊是 BDF2-IMPORT
56. BDF中提供了可以在線瀏覽特定數據庫表信息,可以實現對數據庫信息進行跨平台維護的模塊是BDF2-DBCONSOLE
在實際開發中,都會面臨組件重用的問題, 面向對象的語言,可以通過各種設計模式,實現重用.那么。在dorado框架中如何進行重用呢? 對於dorado的重用問題,下面從三個方面進行說明.
1.通過使用jsp:include指令進行重用
將要重用的內容寫到一個jsp頁面中, 然后通過jsp:include標記在需要使用的位置進行重用, 該jsp中可再引用d:view標簽,比如定義一個jsp頁面:
- <%@ page contentType="text/html; charset=UTF-8"%>
- <%@ taglib uri="http://www.bstek.com/dorado" prefix="d"%>
- <d:View config="com.baiyao.workflow.component.ChargeType">
- <d:SubWindow id="winChargeType" title="選擇類型" width="300" height="200"
- draggable="true" resizable="true" status="hidden"
- showMinimizeButton="false" showMaximizeButton="false"
- showCloseButton="true">
- <d:Layout type="border" width="100%" height="100%">
- <d:Pane position="center">
- 10. <d:DataTable id="tblType" />
- 11. </d:Pane>
- 12. <d:Pane position="bottom" align="center">
- 13. <d:Button id="btnOK" />
- 14. </d:Pane>
- 15. </d:Layout>
- 16. </d:SubWindow>
17. </d:View>
在另外一個頁面中進行引入:
- <d:View config="com.baiyao.workflow.charge.ChargeInput">
- <d:AutoForm id="frmForm">
- <d:FormElementRenderer group="group1" element="render1">
- <d:Layout type="border">
- <d:Pane position="center">
- <d:DataTable id="tblFormItem" />
- </d:Pane>
- <d:Pane position="bottom" align="center">
- <d:Button id="btnAdd" />
- 10. <d:Button id="btnDelete" />
- 11. </d:Pane>
- 12. </d:Layout>
- 13. </d:FormElementRenderer>
- 14. </d:AutoForm>
- 15. <jsp:include page="/workflow/component/win_charge_type.jsp" />
16. </d:View>
該重用方式比較原始, 主要是利用了jsp:include指令, 會編寫jsp的人都會用, 相對來說還是非常簡單的。比較適合組件在頁面中的布局中規中矩的情況, 比如實現某一類功能的組件都集中在頁面中的某一區域。如果某一類功能的組件在頁面中的分布跨度比較大的話, 則會因為沒法封裝在一個jsp中而無法實現重用。由於重用范圍僅限於jsp頁面中, 因此其維護性還是非常不錯的。但是如果對單個簡單組件專門寫一個jsp從而在多個jsp頁面重用顯然有些得不償失。而且如果對於page1頁面中適用到了conrol1,conrol2,conrol3幾個組件, 同樣在page2頁面中也有這3個組件, 大部分屬性都差不多, 但是只有少數幾個屬性不同, 那么只能對jsp進行重用, 而jsp對應的view.xml文件則需要寫兩個。因此重用性會大一定的折扣
易用程度:★★★★★
適用范圍:★★★☆☆
重用粒度:★★☆☆☆
可維護性:★★★★★
2. 對view組件定義進行重用
view重用分為兩種, 一種是通過調用Server API來創建客戶端所需要的組件, 另外一種就是將多個view.xml中定義的組件進行組合。
2.1.通過調用Server API來創建客戶端所需要的組件
通過調用Server API使用java代碼在后台來來創建頁面所需要的各種Control和Dataset, 而不是在view.xml文件中定義需要的control和dataset, 因為采用這種方式就可以通過利用java的OO特性(封裝, 繼承和多態), 如一個保存按鈕, 可能在一個涉及到編輯操作的頁面中都會用到, 因此可以創建一個ViewModel基類,在基類的initControls()方法中通過new Button()的方式來創建該按鈕, 然后指定按鈕的屬性, 有時間的還要加上事件的javascript腳本, 這樣所有從該基類繼承的ViewModel所對應的view所在的頁面都可以適用該按鈕了。
- @Override
- protected void initControls() throws Exception {
- Button btnSave = (Button) createControl("Button", "btnSave");
- btnSave.setCommand("cmdSave");
- btnSave.setValue("保存");
- btnSave.setWidth("70");
- UpdateCommand cmdSave= (UpdateCommand) createControl(
- "UpdateCommand", "cmdSave");
- 10. cmdSave.setMethod("save");
- 11. DatasetInfo info = cmdSave.addDatasetInfo("dsEntity");
- 12. info.setSubmitScope(DatasetInfo.ALL_CHANGE);
- 13. return btnSave;
14. }
該重用方式實際上就是將在view.xml配置文件中定義的control或者dataset通過java代碼來實現, 實際上是換了一種寫法而已, 但是相對於配置文件中的定義來說, 不夠直觀, 而且要寫更多java的代碼, 如果該該組件比較復雜的話, 比如寫有復雜的事件代碼, 需要去拼javascript字符串腳本, 這樣維護性將非常差。但是這種方式的重用粒度非常細, 比如可以只對一個button中的某幾個屬性進行重用。而且對於基類定義的組件可以根據需要進行重載, 這樣靈活性將非常好。
易用程度:★★★☆☆
適用范圍:★★☆☆☆
重用粒度:★★★★★
可維護性:★☆☆☆☆
2.2.多個view.xml中定義的組件進行組合重用
在前面介紹jsp重用方式的時候, 知道是將一個jsp頁面分解成多個頁面來進行重用, 而這里換一個角度: 將一個view.xml根據重用的需要分解成多個view.xml文件, 其實在jsp重用中, 也使用了多個view.xml文件(進行了view.xml的分解), 但是二者的合並時機是不同的, jsp重用是在jsp頁面的時候做的view.xml合並, 這里的合並是在ViewModel初始化中進行的。
這里先來介紹一下JSP Dorado Taglib, ViewModel和view.xml之間的關系(僅限個人理解)
在dorado的view tag中, 根據給定的view文件所在的位置, 創建ViewModel對象, 該對象中會包含一個ViewModelConfig, 對應的view.xml文件的一個解析, 接着進行ViewModel的初始化工作, 初始化就是實際創建組件的過程, 這里面有一些細節這里不做研究(比如對於不同的control, 創建的時機是不同的)。最后得到的是一個個組件的Java對象, 可以將其看成一個個javabean, jsp頁面上的dorado taglib就會根據這些組件對象來生成html或者js腳本。
三者之間的關系大致是這樣, 接着開始探討將多個view.xml合並的時機, 最開始采用在生成ViewModel的時候將要組合的其他view.xml引入, 來生成最終需要的ViewModelConfig對象(在原有基礎上添加了其他view.xml中的組件), 后來這種做法失敗了(這個過程太多復雜, 比如還涉及到緩存問題, 很容易出現在第一次展現沒有問題, 但是在通過command發送ajax請求找不到對應的對象而出錯), 在ViewModel初始化(就是init方法)的時候將要組合的view.xml引入進去, 這時候成功了, 沒有出現問題。可能dorado原來的設計沒有考慮到合並多個view.xml的做法, 因此ViewModel在這一方面還是很封閉的, 很多相關的方法都是private的, 因此需要copy出來。
- public class BaseViewModel extends DefaultViewModel {
- protected static ControlFactory controlFactory;
- protected List<ViewModelConfig> compositedViewModelConfigs;
- protected List<String> compositedConfigNames;
- private int state;
- @Override
- public void init(int state) throws Exception {
- List<String> result = new ArrayList<String>();
- 10. addViewModelConfig(result);
- 11.
- 12. // 因為在初始化其他viewModelConfig的時候需要使用到狀態, 而此時還沒有執行super的init方法,
- 13. // 因此sate還是最初的STATE_VIEW狀態
- 14. setState(state);
- 15.
- 16. initCompositedViewModelConfigs(state, result);
- 17. super.init(state);
- 18. }
- 19.
- 20. protected void setState(int state) {
- 21. this.state = state;
- 22. }
- 23.
- 24. public int getState() {
- 25. return state;
- 26. }
- 27.
- 28. /**
- 29. * 添加需要組合的view.xml文件路徑
- 30. *
- 31. * @param result
- 32. */
- 33. protected void addViewModelConfig(List<String> result) {
- 34. result.add(JbpmConstants.VIEW_TASK_INSTANCE);
- 35. }
- 36.
- 37. /**
- 38. * 根據ViewModelConfig初始化創建組件
- 39. *
- 40. * @param state
- 41. * @param configNames
- 42. * @throws Exception
- 43. */
- 44. protected void initCompositedViewModelConfigs(int state,
- 45. List<String> configNames) throws Exception {
- 46. for (String configName : configNames) {
- 47. ViewModelConfig config = getViewModelConfig(configName);
- 48.
- 49. loadDatasetConfigs(config);
- 50. loadControlConfigs(config);
- 51. if (state == STATE_VIEW) {
- 52. loadEventConfig(DoradoContext.getContext(), config);
- 53. }
- 54. }
- 55. }
- 56.
- 57. /**
- 58. * 根據view.xml文件名得到ViewModelConfig對象
- 59. *
- 60. * @param configName
- 61. * @return
- 62. * @throws Exception
- 63. */
- 64. protected ViewModelConfig getViewModelConfig(String configName)
- 65. throws Exception {
- 66. ViewModelConfig config = null;
- 67. if (compositedViewModelConfigs == null) {
- 68. compositedViewModelConfigs = new ArrayList<ViewModelConfig>();
- 69. compositedConfigNames = new ArrayList<String>();
- 70. }
- 71. if (!compositedConfigNames.contains(configName)) {
- 72. ViewModel viewModel = ViewModelManager.getViewModel(null,
- 73. configName, getNamespace(), "request");
- 74. config = viewModel.getConfig();
- 75. compositedViewModelConfigs.add(config);
- 76. compositedConfigNames.add(configName);
- 77. }
- 78. return config;
- 79. }
- 80.
- 81. @SuppressWarnings("unchecked")
- 82. protected static ControlFactory getControlFactory() {
- 83. if (controlFactory == null)
- 84. try {
- 85. String clazz = Setting.getString("view.controlFactory");
- 86. Class cl = Class.forName(clazz);
- 87. controlFactory = (ControlFactory) cl.newInstance();
- 88. } catch (IllegalAccessException ex) {
- 89. Log.error(ex);
- 90. } catch (InstantiationException ex) {
- 91. if (System.getProperty("java.version").compareTo("1.4") >= 0)
- 92. Log.error(ex.getCause());
- 93. else
- 94. Log.error(ex);
- 95. } catch (ClassNotFoundException ex) {
- 96. Log.error(ex);
- 97. }
- 98. return controlFactory;
- 99. }
- @SuppressWarnings("unchecked")
- protected void loadDatasetConfigs(ViewModelConfig viewModelConfig)
- throws Exception {
- if (viewModelConfig == null)
- return;
- List keys = viewModelConfig.datasetNodes();
- int count = keys.size();
- for (int i = 0; i < count; i++) {
- String id = (String) keys.get(i);
- XmlNode node = viewModelConfig.getDatasetNode(id);
- if (state != 2 && state != 3)
- createDataset(node);
- }
- }
- @SuppressWarnings("unchecked")
- protected void loadControlConfigs(ViewModelConfig config) throws Exception {
- if (config == null)
- return;
- List keys = config.controlNodes();
- int count = keys.size();
- for (int i = 0; i < count; i++) {
- String id = (String) keys.get(i);
- XmlNode node = config.getControlNode(id);
- String type = node.getAttribute("type");
- Class typeClass = getControlFactory().getControlType(type);
- if (typeClass != null) {
- if ((com.bstek.dorado.view.control.Logical.class)
- .isAssignableFrom(typeClass)) {
- createControl(type, id);
- continue;
- }
- if (state == STATE_VIEW
- && !(com.bstek.dorado.view.control.Placeable.class)
- .isAssignableFrom(typeClass))
- createControl(type, id);
- } else {
- throw new IllegalArgumentException("Unknown control type '"
- + type + "'!");
- }
- }
- }
- protected void loadEventConfig(DoradoContext context, ViewModelConfig config) {
- if (config == null)
- return;
- XmlNode eventNodes[] = null;
- XmlNode eventsNode = config.getRoot().getChild("Events");
- if (eventsNode != null)
- eventNodes = eventsNode.getChildren();
- if (eventNodes != null) {
- for (int i = 0; i < eventNodes.length; i++) {
- XmlNode eventNode = eventNodes[i];
- String script = XmlConfigUtils.getNodeContent(eventNode,
- context);
- EventHandler event = new EventHandler(eventNode
- .getAttribute("name"), script);
- addEventHandler(event);
- }
- }
- }
- public Control getControl(String id) throws Exception {
- ViewModelConfig config = getConfig();
- Control control = getControl(config, id, true);
- return control;
- }
- /**
- * 在多個view.xml文件中遍歷直到找出要對應的javabean模型數據來創建control
- *
- * @param config
- * @param id
- * @param loop
- * 是否循環查找, 如果是在compositeViewModelConfigs中查找的話應該避免循環查找, 否則會死循環
- * @return
- * @throws Exception
- */
- private Control getControl(ViewModelConfig config, String id, boolean loop)
- throws Exception {
- Control control = (Control) controls.get(id);
- if (control == null && config != null) {
- XmlNode node = config.getControlNode(id);
- if (node != null) {
- String type = node.getAttribute("type");
- control = createControl(type, id);
- } else if (loop) {
- // 注意順序, 添加組合的view.xml文件的原則是后添加的同id的control或dataset將覆蓋前面的
- for (int i = compositedViewModelConfigs.size() - 1; i >= 0; i--) {
- compositedViewModelConfigs.get(i);
- control = getControl(compositedViewModelConfigs.get(i), id,
- false);
- if (control != null) {
- break;
- }
- }
- }
- }
- return control;
- }
- public Control createControl(String type, String id) throws Exception {
- Control control = (Control) controls.get(id);
- if (control == null) {
- control = constructControl(type, id);
- ViewModelConfig config = getConfig();
- if (config != null) {
- initControl(control, config, id);
- }
- controls.forceAdd(id, control);
- initControl(control);
- }
- return control;
- }
- private void initControl(Control control, ViewModelConfig config, String id)
- throws Exception {
- XmlNode node = config.getControlNode(id);
- if (node == null) {
- for (int i = compositedViewModelConfigs.size() - 1; i >= 0; i--) {
- config = compositedViewModelConfigs.get(i);
- node = config.getControlNode(id);
- if (node != null) {
- break;
- }
- }
- }
- control.init(DoradoContext.getContext(), node);
- }
- protected ViewDataset createDataset(String type, String id, XmlNode node)
- throws Exception {
- ViewDataset dataset = constructDataset(type, id);
- DoradoContext context = DoradoContext.getContext();
- if (node != null) {
- dataset.init(context, node);
- if (state == STATE_REPORT)
- dataset.setAutoLoadData(true);
- }
- datasets.forceAdd(id, dataset);
- initDataset(dataset);
- return dataset;
- }
- public ViewDataset createDataset(XmlNode node) throws Exception {
- String type = node.getAttribute("type");
- String id = node.getAttribute("id");
- return createDataset(type, id, node);
- }
- @Override
- public ViewDataset getDataset(String id) {
- // 在當前config中找, 如果找不到, 將在組合config中去找
- ViewDataset dataset = super.getDataset(id);
- if (dataset == null) {
- for (ViewModelConfig config : compositedViewModelConfigs) {
- if (dataset == null && config != null) {
- XmlNode node = config.getDatasetNode(id);
- if (node != null)
- try {
- String type = node.getAttribute("type");
- dataset = createDataset(type, id);
- if (dataset != null)
- break;
- } catch (Exception ex) {
- Log.error(ex);
- }
- }
- }
- }
- return dataset;
- }
- @Override
- public ViewDataset createDataset(String type, String id) throws Exception {
- XmlNode node = null;
- ViewModelConfig config = getConfig();
- if(config != null) {
- node = config.getDatasetNode(id);
- if (node == null) {
- for (ViewModelConfig vmc : compositedViewModelConfigs) {
- node = vmc.getDatasetNode(id);
- if (node != null) {
- break;
- }
- }
- }
- }
- return createDataset(type, id, node);
- }
- }
該重用方式集成了jsp重用的優點, 在一定程度上消除了缺點, 與jsp重用相比, 優點在於,不會受到組件在頁面中的位置布局的影響。在重用粒度上能對單個的組件進行重用, 相比jsp重用要細, 但是比Server API的重用方式要粗一些。因為只是配置文件上的重用, 因此主要是對配置文件的維護, 可維護性要比Server API方式要好, 該方式需要使用者對view.xml配置文件, jsp dorado taglib, ViewModel類三者之間的關系有非常好的認識。
易用程度:★★☆☆☆
適用范圍:★★★★☆
重用粒度:★★★★☆
可維護性:★★★★★
其他重用技巧
如果view.xml文件都一樣(說明界面一樣), 只是ViewModel不同(說明后台業務邏輯不同)的情況下, 可以讓其公用同一個view.xml, 只是在d:view的配置上加上clazz屬性指定二者不同的ViewModel即可。比如這樣的寫法:
- <d:View config="com.baiyao.workflow.settlement.SettlementInput"
- clazz="com.baiyao.workflow.settlement.ExpenseSettlementInputViewModel">
- <jsp:include page="/workflow/settlement/settlement_input.jsp" />
- </d:View>
如何選擇
其實這幾種重用方式互相之間並不矛盾, 可以在一個功能模塊中根據需要結合起來適用。但是如果使用太多的重用方式, 會提高項目的復雜程度, 這樣就會影響到可維護性, 因此重用也應該適可而止, 否則就是過猶不及。
參考鏈接:
https://www.iteye.com/blog/xiangtui-675693
https://www.cnblogs.com/linsond/archive/2010/02/26/1674409.html
https://blog.csdn.net/weixin_30448603/article/details/98497684