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-servlet -
com.bstek.dorado.core.DoradoServlet -
2 -
-
-
dorado-servlet -
*.d -
-
GZIPEncoder -
com.bstek.dorado.core.GZIPEncodeFilter -
dorado-filter -
com.bstek.dorado.core.DoradoFilter -
GZIPEncoder -
*.jsp -
dorado-filter -
*.d -
dorado-filter -
*.do -
dorado-filter -
*.action -
-
http://www.bstek.com/dorado -
/WEB-INF/dorado.tld -
-
在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”%>
-
-
draggable="true" resizable="true" status="hidden"
-
showMinimizeButton="false" showMaximizeButton="false"
-
showCloseButton="true">
-
-
-
-
-
-
-
-
-
在另外一个页面中进行引入:-
-
-
-
-
-
-
-
-
-
-
-
-
-
该重用方式比较原始, 主要是利用了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
compositedViewModelConfigs; -
protected List
compositedConfigNames; -
private int state;
-
@Override
-
public void init(int state) throws Exception { -
List
result = new ArrayList (); -
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;
-
}
-
-
protected void addViewModelConfig(List
result) { -
result.add(JbpmConstants.VIEW_TASK_INSTANCE);
-
}
-
-
protected void initCompositedViewModelConfigs(int state,
-
List
configNames) throws Exception { -
for (String configName : configNames) { -
ViewModelConfig config = getViewModelConfig(configName);
-
loadDatasetConfigs(config);
-
loadControlConfigs(config);
-
if (state == STATE_VIEW) { -
loadEventConfig(DoradoContext.getContext(), config);
-
}
-
}
-
}
-
-
protected ViewModelConfig getViewModelConfig(String configName)
-
throws Exception { -
ViewModelConfig config = null;
-
if (compositedViewModelConfigs == null) { -
compositedViewModelConfigs = new ArrayList
(); -
compositedConfigNames = new ArrayList
(); -
}
-
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;
-
}
-
-
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即可。比如这样的写法:
clazz="com.baiyao.workflow.settlement.ExpenseSettlementInputViewModel">
如何选择
其实这几种重用方式互相之间并不矛盾, 可以在一个功能模块中根据需要结合起来适用。但是如果使用太多的重用方式, 会提高项目的复杂程度, 这样就会影响到可维护性, 因此重用也应该适可而止, 否则就是过犹不及。
参考链接:
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



