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>
- 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