Dorado on the way - final

      本来想继续前面陆陆续续的两篇关于Dorado的文章,但想想为了大家查阅方便,干脆来一个final版,一次性写出来。



 

20061225


今天是圣诞节,进入公司已经四个月了,可是对公司的产品Dorado还几乎是一个门外汉,(我要说明一下,不是我太笨,刚刚进入公司就接受了一个传统项目的开发,再加之学校的事情,在此我想我应该声明一点,我还是一个大四的学生,快结束大学四年的学习了,到最后,乱七八糟的事情实在是太多了,这个报告那个报告的。)

Thomas(我们公司的产品经理),还有范经理,实在是不好意思,还有公司的同事,虽然我比他们中的好多人进入公司都早,可惜我不是最厉害的,至少现在不是。

到上个星期为止,学校的事情基本上已经完了,毕业设计的课题也选了,选的课题是《基于智能Agent的分布式移动计算处理》,本来一开始自作聪明,以为题目为“移动计算”嘛,就是移动设备的计算处理,智能Agent嘛~估计就是一种形式而已,我自从从大学二年级自学Java开始,接触了Java中的JavaSEJavaEE两个体系,正好可以借此课题,让我对JavaME有所了解,也实现了完成毕业设计的作用。结果后来导师选好了以后,看着导师给的材料,我才知道,我陷入泥潭了~(导师,原谅我这么说,呵呵·)

今天是我真正学习Dorado的第一天,公司给了我一些资料,所以我信心十足,我要赶上公司的其他同事,呵呵~争取超过他们哦~已经习惯了要做到最好,我是不是太自大了??

还是跟我学习Java一样,首先在公司的官方网站(http://www.bstek.com/)下载了Dorado的最近版本,我下载的版本是Dorado-5.0 061129.1132,一并还下载了Dorado 5 快速入门,组件使用技巧,当然还有DoradoAPI--我的最爱。

首先看了Benny(我们公司的CTO)录制的两段视频说明,依照Dorado安装自带的doradosample,把dorado的大致功能作了一个讲解说明,个人感觉dorado还是挺有市场前景的,只是需要更大的宣传。

好了,闲话不多说了,开始我的Dorado之旅吧~


首先,需要了解的是:视图模型Dorado开发当中非常重要的对象,它封装了Dorado的界面逻辑和操作逻辑,即主要包含什么数据dataset ,以及这些数据通过什么形式来展现。

下面是我今天学习中,觉得需要注意的一些地方和术语。


  • Dataset

    1. getDataset(“datasetName”) ; 获取对dataset的引用

    2. RecordIterator ri = dataset.recordIterator() ; 获取对dataset的迭代器引用。

    3. dataset的遍历

      while(ri.hasNext()){

Record record = ri.nextRecord() ;

// 对每条记录的操作

    }

    4. 可是通过getControl(“controlName”) ; 获取组件的引用

      注意,这里得到的是Control对象,需要进行类型的强制转换。

    5. ”Module数据坞”的说明。

      1). 数据坞里面的dataset对象可以被不同的视频模型索引用,以达到数据共享的作用。

2). Module不应该包含任何的业务逻辑,这是一种良好的设计模式。

3). Module的创建和销毁由Dorado提供的容器来管理,可以当做一个Singleton使用。

所以在绝大部分情况下,在Module里面添加非静态的属性都不是正确 (或者是不太明智)的做法。

4). Module中的dataset的创建和销毁使用dorado提供的容器来管理的,但开发人员可以强制通过scopetimeout来定制dataset的生命周期。

5). scope有三种取值,分别是request (默认)session application

需要特别注意的是,在同一个request连续以不同pageIndex pageSize parameters的不同组合来获取Module中的dataset,但将获得多个不同的dataset 实例。

6). 如果为了提高效率而将scope设置为application ,则应该注意让此dataset中的数据量不要过大。常用在大型系统中的代码表。

6. 通过dataSet.getCurrent() ; 方法,可以从dataSet获取当前记录。由于dataSet具有

当前记录”这个,所以大多数操作都是对“当前数据”来说的。

  • Mapping

    1. 所有的Mapping单元都是通过名为global的管理单元来进行管理的。

2. 在请求映射的过程中,dorado有着自己独特的,不同于Struts的映射机制,

例如:对于请求:action=”access.login.d”

access 与对应的controller的名称一致,

login与对应的action的名称一致。

3. controllerclazz属性所表示的是用于处理这个请求的class ,类似于Struts中的 Action ,而提交的数据,就从Struts 中的ActionFrom转换成了Doradodataset.

4. 对于页面的访问安全控制(即只能通过dorado式的请求,而不容许以文件结构路径来访问,即../demo/XX.jsp),可以将view中的safe属性设置为true来控制。

或者通过dorado默认的setting中的security.accessChecher来控制。不过我可以自主创建一个AccessChecker类型的java类来进行控制。但需要将setting.xml里面的 “security.accessChecker”属性修改为自己创建的类路径。

5. 可以通过DoradoContext来访问dorado的上下文信息,并通过标记量来告诉dorado 的上下文从哪里获取需要的变量。

例如,

Object obj = doradoContext.getAttribute(DoradoContext.SESSION,”username”) ;


  • i18n

    1. 你需要在i18n目录下新建一些I18Nproperties类型文件。此类文件与java中的

    一致,都是以键-值对的形式存在。

    2. dataset中的Fields里面设置为${Resource.fileName.key}的形式进行设置。这个就

    有点类似于JSP2.0中的EL,其中,fileName是资源文件的文件头,不包括_cn_ZH

    等类似的字样。而key是在文件中的键。这些都是在系统的setting.xml中的

    common.locale.language”和“common.locale.country ”来进行的配置。同样,你可

    以通过修改这两个属性来启用不同的I18N文件。

3. 对于动态更改用户的国际化资源的情况,可以使用

LocalHelper.getLocale(“language”,”country”),

ResourceManager.getInstance().setDefaultLocale(context,

DoradoContext.SESSION,

locale) ; 来设置。

  • EL

    JSP2.0方面的书籍中有大量的经典介绍,这里就不再记录。

    开发时,只需记住Dorado内置的隐式变量,即可。

  • Skin

    1. 皮肤文件夹存放的位置是在skins文件夹下面的。

    在使用新皮肤时,只需要修改setting.xml中的view.smartweb2.skin对应的值即可。

    2. 同时可以通过修改skin.css文件来修改dorado中的标签库的所有展示风格。

    3. 同时也支持传统的JSP开发,即在<head>标签中设置相信的各种属性,以完成让

    dorado以用户自定义的形式进行展现。



200711



关于Dataset


  1. 可以通过RecordIterator dataset中的数据进行遍历(包括已经在客户端“删除”的记录)

    为什么在客户端已经“删除”的记录,dataset仍然可以遍历到?

    原因就在于Dorado出于对性能的考虑,在客户端做的删除并没有立刻更新服务器段的记录,而仅仅是在客户端的dataset中做了删除的标记。在用户提交了以后,才会对服务器端的记录做修改。所以用户在客户端做的删除操作后,如果刷新页面,删除的记录将会重新出现。

    可以通过如下代码对dataset中已经标记为“删除”的记录进行遍历:

RecordIterator rit dataset.recordIterator() ; // 获取dataset的遍历器

rit.setVisibility(Dataset.FILTER_DELETED) ; // 设置遍历器的可见属性

while(rit.hasNext()){

Record record = rit.nextRecord() ; // 取得当前的Record对象

// 对记录进行操作

}



  1. isFirst 以及 isLast的理解

    dataset中容易犯下的错误就是对isFirstisLast的误解。

    isFirstisLast并不像大家想象当中的那样,代表着Dataset的当前记录(注意,所有对Dataset的操作,都是对“当前记录”而言)是否是第一条记录或者是最后一条记录。他们真正的含义如下:

isFirst

官方解释:

isFirst表示Dataset已经在试图继续向前移动当前记录的过程失败,亦即dataset的当前记录从第二条记录转到第一条记录时isFirst仍然是 false,只有当Dataset试图继续向前移动当前记录后,isFirst才会变成 true,此时dataset的当前记录仍然是第一条记录。

我的理解:

对于isFirst,你可以于Java当中的Iterator作对比。我们假设Java中的 Iterator具有previous(),就是next()倒着遍历(),那么当当前记录从第二条作previous()成功到达第一条记录的时候,isFirst仍然返回false,为什么?因为在移动过程中没有受阻,它成功的前移了。下面要注意了,现在当前记录已经在第一条了,现在如果当前记录再试图向前移动时,此时受阻了,因为在当前记录前面已经没有记录可以移动了,此时 isFirst()返回true

如下图:

图1
dorado的设计过程中,数据导航条的数据前移和后移过程中,并不会查看当前记录是否是第一条或者是最后一条数据,而是默认前或者后还有数据,从而继续作向前或向后的操作,只有在移动受阻后,才修改是否到边界的标记,这样或许在移动操作中可能会对移动的性能有一定的帮助。

个人认为,这里把isFisrt()看作是对当前记录的操作时候“越界”的标志更为合适。

IsLast

官方的解释:

isLast表示Dataset已经在试图继续向后移动当前记录的工程失败,亦即dataset试图继续向前移动当前记录后,isFirst才会变为true,此时 Dataset的当前记录仍然是倒数第一条记录。

我的理解:

可以对比isFirst来理解,我觉得我已经解释的比较清楚了。



  1. moveFirst moveLast方法

    当用户调用了DatasetmoveFirstmoveLast之后,DatasetisFirstisLast立刻被置为true

    dataset没有任何可见记录的时候,isFirstisLast将同时为true,并且当前记录为null

    想必在前面理解了我对isFirstisLast的讲解之后,对这两个方法的理解应该不会出现什么偏差了。

不过我想提醒大家一下,注意我这里的用词,是“可见记录”,即是说,如果在客户端删除了所有的记录,虽然没有向服务器提交,但此时isFirstisLast都会同时返回true。这里就很好的统一了对用户的“体验一致性”,即用户认为已经没有数据了。



  1. 不知道大家有没有在浏览器中查看过Dorado生成的jsp文件的源代码,其实这些源代码都是通过htmlxml界面模板信息共同展现的。



  1. Dorado内部加载顺序:第一步: 客户端发出请求

                                                         第二步:初始化 视图模型

                                                         第三步:初始化 Dataset

                                                         第四步:初始化 组件

                                                         第五步:完成组件与Dataset之间的绑定

                                                         第六步: Dataset向外部请求数据,完成数据加载

                                                         第七步:向客户端返回HTML/XML界面模板信息

                                                         第八步:完成,显示页面





200718


  1. Dataset中最重要的方法: flushData()

功能我想我不说大家也知道,就是通过不刷新页面来实现数据更新与交换。

  • 在设置对象的属性于视图模型中的字段的时候,可是使用在试图模型中的objectClazz来帮助我们实现这个一一对应的关系。-fromDO方法

    注:因为这里是根据java class中的属性名称一一映射的,所以如果出现属性名称于试图模型中所希望的字段名称不一致的时候,可以使用property属性来辅助我们。

  • 异步交互:

      dataset中设置autoLoadDatafalse,并且设置asynctrue

  • MasterLink

    主从表的设置:

    • 方法一: 修改主表的Dataset中的afterScroll事件。

    • 方法二: 在masterLink中设置,便可以完成同样的功能。

      • 特点:可以缓存已经下载的数据

  • 在中设置多个监听器,各个监听器之间用逗号分隔。

    在监听器中分别提供了beforeXXafterXX方法,其中afterXX的返回值为voidbeforeXX的返回值为boolean型,这样如果在beforeXX方法中返回false,就可以实现中止标准的dataset.XX()以及监听器本身的afterXX()方法的操作。

  • ViewProperties

    • 在传统的开发方式中,常常通过getParameter()方法来获取页面的参数信息。但是需要注意以下的提示:

      dorado中,可以通过两种方式来发送request请求,一种是通过JSP页面来发送request请求,还有一种是通过客户端的datasetflushData()方法来发送request请求,但需要注意的是,通过这两种方式产生的request请求是完全不通的request对象。所以通过类似于DoradoContext.getContext().getParameter(“pageSize”)这样的方法在第一种request请求中是正确的,可以获得通过JSP页面传送的pageSize参数,但在第二种request中,通过这样的方法所得到的就是null,需要特别的注意。

      所以,在开发中常常遇到的问题就是你第一页显示的没有问题,但是当你点击下一页的时候,就会有问题。这是因为第一页是通过JSP页面发送的请求,而当点击下一页的时候,就是通过客户端的Dataset来发送的请求。

      如果通过ViewProperties方式,就不存在这样的问题。

      具体使用如下:

        DoradoContext.getContext().getAttribute(DoradoContext.VIEW,”pageSize”) ;

      这个方法返回的是Object类型的返回值,你只需要做适当的强制转型即可。


    • 我们可以从服务器端或者客户端来访问、存贮ViewProperties,用“推”的形式来实现客户端于服务器端之间的数据传递

      • 服务器端:

        DoradoContext.getContext().setAttribute(DoradoContext.VIEW, key, value) ;

        DoradoContext.getContext().getAttribute(DoradoContext.VIEW, key) ;

      • 客户端:

        getViewModel().properties().getValue(key) ;

        getViewModel().properties().setValue(key, value) ;

      • 同时,我们也可以通过EL表达式来方便的访问viewProperties属性:

        ${ViewProperties.XXX},

        ${ViewProperties.getString(“XXX”)}

  • 数据校验

    dataset中添加校验器来完成

      datasetbeforeChange()方法中添加代码。

      例如可以使用如下方式:

        switch(field.getName()){

case “key1” : {

// code here

}

...

}

  • 记录状态

    • none -无状态: 当数据下载到客户端,此时记录是“无状态”的,这是 Dorado的默认状态。

    • new -新增状态:表示该记录刚刚被添加到数据集,并且尚未得到验证和确认。如果此时我们执行了对该记录的撤销,那么该记录将被从数据集中移除。

    • insert -已添加状态:表示这是一条新增的并且已经经过验证和确认的记录。

    • modify -已修改状态:表示这是一条数据已经被修改的并且已经经过验证和确认的记录。

    • delete - 已删除状态:表示这是一条被标记为已删除的记录。默认形式下此种记录是不可见的,我们对数据集的遍历操作也不会得到该记录。但是我们前面还是接受了一种方法,可以遍历到这类记录。

可以通过Rocord.getState()方法获得记录的状态信息。

并且可以通过dataset.getOldRecord(Record r)来获取记录r的原始值。




组件开发


. DataTable

  1. 分配下载功能: 设置autoLoadPagetrue

  2. 在表格中,列标题常常需要汉化成为中文,我们不建议您在DataTable里直接修改,尽管这样做也可以达到目的,我们建议您在与DataTable绑定的Dataset中的Fields中进行修改。

  3. 设置fixedColumn来设置锁定的列数。

  4. 设置confirmCancelconfirmDelete属性可以设置对表格进行快捷键的操作时,是否弹出相应的提示信息。

  5. 设置editable来设置表格是否可编辑。

  6. 通过headerHeight可以设置表格头的高度。

  7. ignored属性是控制表格向客户端输出,一旦设置为true,在客户端将不会有这个表格元素存在。

  8. topleft用来设置表格在屏幕的绝对位置。

  9. 在修改事件的时候,返回值为false,表明不需要再继续执行系统默认的执行方式,而只执行我们自定义的执行方式即可。

  10. 我们可以通过dataset.getField(“fieldName”).setReadOnly(true) 来控制具体某一个单元格的只读属性。

    对表格可编辑状态控制的具体总结:

    行状态:利用datasetafterScroll动态设定datasetreadOnly属性实现。

    列状态:利用columnreadOnly属性实现。

    指定mn列的所在单元格状态:在datasetafterScroll动态设定fieldreadOnly属性实现。