Dorado用法与示例
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> -
</servlet-mapping> -
<filter-name>GZIPEncoder</filter-name> -
<filter-class>com.bstek.dorado.core.GZIPEncodeFilter</filter-class> -
<filter-name>dorado-filter</filter-name> -
<filter-class>com.bstek.dorado.core.DoradoFilter</filter-class> -
<filter-name>GZIPEncoder</filter-name> -
<url-pattern>*.jsp</url-pattern> -
<filter-name>dorado-filter</filter-name> -
<url-pattern>*.d</url-pattern> -
<filter-name>dorado-filter</filter-name> -
<url-pattern>*.do</url-pattern> -
<filter-name>dorado-filter</filter-name> -
<url-pattern>*.action</url-pattern> -
<taglib> -
<taglib-uri>http://www.bstek.com/dorado</taglib-uri> -
<taglib-location>/WEB-INF/dorado.tld</taglib-location> -
</taglib> -
在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
-
dorado5-security.jar
-
dorado5-smartweb.jar
-
dorado5-utils.jar
-
dorado5-view.jar
-
在項目中加入home目錄,跟src目錄同級別,里面的內容可以從doradosample里去拷貝過來。
四. 使用過程中遇到的問題 -
如何使用項目中的自定義連接,不用dorado默認的連接
在dorado的說明文檔上有關于這個問題的說明,其中說明里寫道
Dorado重用最佳實踐
在實際開發中,都會面臨組件重用的問題, 面向對象的語言,可以通過各種設計模式,實現重用.那么。在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"> -
<d:DataTable id="tblType" /> -
</d:Pane> -
<d:Pane position="bottom" align="center"> -
<d:Button id="btnOK" /> -
</d:Pane> -
</d:Layout> -
</d:SubWindow> - </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" /> -
<d:Button id="btnDelete" /> -
</d:Pane> -
</d:Layout> -
</d:FormElementRenderer> -
</d:AutoForm> -
<jsp:include page="/workflow/component/win_charge_type.jsp" /> - </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"); -
cmdSave.setMethod("save"); -
DatasetInfo info = cmdSave.addDatasetInfo("dsEntity"); -
info.setSubmitScope(DatasetInfo.ALL_CHANGE); -
return btnSave; - }
該重用方式實際上就是將在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>(); -
addViewModelConfig(result); -
// 因為在初始化其他viewModelConfig的時候需要使用到狀態, 而此時還沒有執行super的init方法, -
// 因此sate還是最初的STATE_VIEW狀態 -
setState(state); -
initCompositedViewModelConfigs(state, result); -
super.init(state); -
} -
protected void setState(int state) { -
this.state = state; -
} -
public int getState() { -
return state; -
} -
/** -
* 添加需要組合的view.xml文件路徑 -
* -
* @param result -
*/ -
protected void addViewModelConfig(List<String> result) { -
result.add(JbpmConstants.VIEW_TASK_INSTANCE); -
} -
/** -
* 根據ViewModelConfig初始化創建組件 -
* -
* @param state -
* @param configNames -
* @throws Exception -
*/ -
protected void initCompositedViewModelConfigs(int state, -
List<String> configNames) throws Exception { -
for (String configName : configNames) { -
ViewModelConfig config = getViewModelConfig(configName); -
loadDatasetConfigs(config); -
loadControlConfigs(config); -
if (state == STATE_VIEW) { -
loadEventConfig(DoradoContext.getContext(), config); -
} -
} -
} -
/** -
* 根據view.xml文件名得到ViewModelConfig對象 -
* -
* @param configName -
* @return -
* @throws Exception -
*/ -
protected ViewModelConfig getViewModelConfig(String configName) -
throws Exception { -
ViewModelConfig config = null; -
if (compositedViewModelConfigs == null) { -
compositedViewModelConfigs = new ArrayList<ViewModelConfig>(); -
compositedConfigNames = new ArrayList<String>(); -
} -
if (!compositedConfigNames.contains(configName)) { -
ViewModel viewModel = ViewModelManager.getViewModel(null, -
configName, getNamespace(), "request"); -
config = viewModel.getConfig(); -
compositedViewModelConfigs.add(config); -
compositedConfigNames.add(configName); -
} -
return config; -
} -
@SuppressWarnings("unchecked") -
protected static ControlFactory getControlFactory() { -
if (controlFactory == null) -
try { -
String clazz = Setting.getString("view.controlFactory"); -
Class cl = Class.forName(clazz); -
controlFactory = (ControlFactory) cl.newInstance(); -
} catch (IllegalAccessException ex) { -
Log.error(ex); -
} catch (InstantiationException ex) { -
if (System.getProperty("java.version").compareTo("1.4") >= 0) -
Log.error(ex.getCause()); -
else -
Log.error(ex); -
} catch (ClassNotFoundException ex) { -
Log.error(ex); -
} -
return controlFactory; -
} -
@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
總結
以上是生活随笔為你收集整理的Dorado用法与示例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何在CPU上优化GEMM矩阵乘法
- 下一篇: 自研GPU之火(续)