Dorado 5 : 2.3.Dorado5 Servlet数据交互过程 (T32)

Dorado5 Servlet数据交互都是通过AJAX来完成的,客户端组装成的XML数据通过AJAX提交到服务端,服务端ViewModel接收到XML数据后解析成一些属性或者数据,然后通过服务端得到的数据结果在服务端组装成XML数据通过AJAX返回到客户端,客户端BRich Engine根据返回的XML数据再重新创建客户端Dataset的数据记录,这个当中会触发Dataset绑定的一些控件的展现重构(Control的Html通过DHtml来重新组装Html内容)。

Dorado5 数据刷新

Dorado5的数据刷新一般是通过客户端Dataset的flushData (file:///D:\\Dorado\\Dorado\\dorado5-20071203\\doc\\client-api\\Dataset.html#flushData)(包括flushDataAsync)来执行的。当客户端Dataset执行flushData之前,一般会动态改变Dataset的parameters(Dataset的参数集合)来进行参数的交互;执行flushData的时候,BRich Engine会根据Dataset的一些信息(与数据相关的,比如Dataset要查询的页数pageIndexs等。最新的Dorado5版本中还把Dataset的一些定义信息也提交到后台,比如Dataset的Type、objectClazz、fields、pageSize、originPageCount、originPossibleRecordCount等,这些都是为了方便在ViewModel没有定义的Dataset能在服务端创建起来)和parameters等组装成XML数据,再通过AJAX把XML数据提交到DoradoServlet,DoradoServlet根据提交上来的ViewModel Id和Dataset的定义信息等,先创建ViewModel实例,然后通过ViewModel里的定义和提交上来的Dataset的定义信息来创建Dataset,如果ViewModel里查找不到定义的Dataset,则通过提交上来的Dataset的定义信息来在ViewModel里创建Dataset,然后根据提交上来的XML数据把Dataset的一些与数据相关的属性和parameters填充。
在ViewModel创建Dataset的过程当中,都会先查找view.xml的datasets节点下有没有该id的Dataset定义,如存在就根据view.xml里的配置信息来创建Dataset,然后进入ViewModel的init、initDataset、initDatasets方法。
当Dataset在ViewModel存在,Dataset就进入ViewModel处理Dataset的流程,一般如果Dataset的监听器Listener存在就进入Listener处理,在处理到dataset.load的时候会根据Listener beforeLoadData的返回值(为true)时才进入dataset.load处理。当然,如果Listener不存在就直接进入dataset.load处理。dataset.load的处理方法和内容就根据不同的Dataset类型和属性决定的。
通过dataset.load或者在Dataset的Listener里,一般会得到Dataset的数据集Records。ViewModel会根据Dataset的信息和Records的数据组装成XML数据,DoradoServlet把ViewModel组装成的XML数据通过AJAX返回到客户端,BRich Engine通过解析返回的XML数据,根据Dataset的fulshData方式增加记录或者重新创建Dataset的客户端数据集。BRich Engine根据Dataset跟Controls的绑定关系加上各自的Event来重新构造Controls的页面展现。
我们通过2.1中HelloWorld例子的查询来说明上面的原理:

  1. 当我们在上面的表单中填好Form中的员工编号或者部门,再按查询按钮。按钮的事件触发了commandForm.execute(),QueryCommand其实就是把conditionDataset的当前记录内容组装成queryDataset的parameters。因为datasetForm存在两个Field:EMPLOYEE_ID(员工编号)和DEPT_ID(部门),这个时候datasetCustom的parameters就存在两个参数:EMPLOYEE_ID(值为ANLIN)和DEPT_ID(值为D12)。commandForm.execute执行了datasetCustom. flushData (file:///D:\\Dorado\\Dorado\\dorado5-20071203\\doc\\client-api\\Dataset.html#flushData)()。


图 2.3:HelloWorld查询操作

  1. 客户端Dataset提交过程中,BRich Engine根据datasetCustom的信息和parameters信息组装成XML数据通过AJAX提交到服务端。
  2. 服务端根据提交上来的XML数据创建了Sample2_1ViewModel对象,并在Sample2_1ViewModel对象中创建了datasetCustom,datasetCustom根据sample2_1.view.xml的内容进行了初始化,然后客户端把提交上来的datasetCustom的信息和parameters信息赋值给Sample2_1ViewModel对象里的相应属性和方法。
  3. 根据Sample2_1ViewModel的执行方式,先调用了datasetCustom的CustomDatasetListener,执行了里面的方法,其中在beforeLoadData里做了数据的查询动作(看代码2.2),根据parameters的两个参数:EMPLOYEE_ID(值为ANLIN)和DEPT_ID(值为D12),datasetCustom进行了Records的增加,其中方法返回了false(返回false是不再去执行dataset.load,因为这里已经模拟了查询并返回结果,但一般都是通过dataset.load来取数据的)。
  4. Sample2_1ViewModel根据datasetCustom现在的对象内容组装成XML数据。
  5. DoradoServlet把XML数据通过AJAX返回到客户端。
  6. 客户端BRich Engine先清空datasetCustom在客户端的数据集,再根据返回的XML数据为datasetCustom新增数据集。
  7. datasetCustom由于跟tableCustom、datapilotCustom绑定了关系,这个时候客户端BRich Engine根据他们的关系把tableCustom的内容重新构造了Html把datapilotCustom的按钮状态重新设定。


图 2.4:HelloWorld查询结果

Dorado5 数据提交

Dorado5的数据提交都是通过各种Command来实现的,最常用的就是UpdateCommand。
当客户端执行command.execute之前,一般会跟Dataset一样,一般会动态改变Command的parameters(Command的参数集合)来进行参数的交互。既然是数据提交,那肯定是还有Dataset的一些数据提交到服务端去。Command会根据DatasetInfos定义的Dataset和数据的提交方式,BRich Engine会把所有Dataset的属性信息和要提交的数据集,以及Command的parameters等组装成XML数据,再通过AJAX把XML数据提交到DoradoServlet,DoradoServlet根据提交上来的ViewModel Id、Command信息、DatasetInfos下所有Dataset的属性信息和数据信息以及Command parameters参数等,先创建ViewModel实例,然后通过ViewModel里的定义和提交上来的Command和Datasets的定义信息来创建Command和Dataset,然后根据提交上来的XML数据把Dataset的一些与数据相关的属性、Records数据集以及Command的parameters填充。
ViewModel会根据Command的定义在ViewModel里执行Update方法,默认情况下如Command不填写method,会执行doUpdateData(ParameterSet,ParameterSet)方法。一般在doUpdateData方法或者自己定义的Command method方法里对提交上来的Parameters和Datasets的数据进行判断和处理。Datasets的数据处理一般通过开发者编写代码来完成,如果是AutoSqlDataset或者SqlDataset,他们的dataset.update方法是可以完成一些默认的数据Update,在dataset.update方法了会触发了Dataset的Listener,在处理到dataset.update的时候会根据Listener beforeUpdateData的返回值(为true)时才进入dataset.update处理。当然,如果Listener不存在就直接进入dataset.update处理。dataset.update的处理方法和内容就根据不同的Dataset类型和属性决定的。
通过执行完Update方法,一般已经对提交上来的Datasets的Records进行处理,比如Records某个Field是通过服务端处理之后得到值的。ViewModel会根据处理完的结果(已经改变的Records)对每一条数据进行状态设定,比如提交一条新增的记录上来,跟数据库交互了之后,这条记录应该是一个none状态。ViewModel还会通过Command outParameters把一些信息返回到客户端。
ViewModel会根据处理完的outParameters、所有Datasets的Records等信息组装成XML数据,DoradoServlet把ViewModel组装成的XML数据通过AJAX返回到客户端,BRich Engine通过解析返回的XML数据,先根据返回的信息来得到服务端处理成功还是失败。如果是失败则触发Command的onFailure事件,如果是成功,就做以下一些动作:根据outParameters数据新增客户端Command outParameters的返回参数,根据DatasetInfos返回的所有Datasets和Records的状态和内容改变来改变客户端Datasets的Records状态和值。BRich Engine根据Dataset跟Controls的绑定关系加上各自的Event来重新构造Controls的页面展现。BRich Engine还会根据Command里各自Dataset一些设置来处理Dataset的Records,比如Dataset设置了clearSelectionOnSuccess的值为true,这个时候BRich Engine就把Dataset所有打勾的记录去掉打勾。最后触发Command的onSuccess事件。
我们通过2.1中HelloWorld例子的数据提交来说明上面的原理:

  1. 我们对tableCustom的记录进行增删改操作,我们对员工编号为Default的数据进行修改,删除员工编号为Default2的数据,新增员工编号为Insert的数据。


图 2.5:HelloWorld修改页面数据提交前数据信息

  1. 按下提交按钮的时候,执行了commandSave.execute()。在commandSave的beforeExecute事件里执行了command.parameters().setValue("test","true");代码,用过parameters提交一些参数到服务端。
  2. 客户端commandSave提交过程中,BRich Engine根据commandSave的信息、parameters信息以及DatasetInfos下Datasets信息、Records信息组装成XML数据通过AJAX提交到服务端。
  3. 服务端根据提交上来的XML数据创建了Sample2_1ViewModel对象,并在Sample2_1ViewModel对象中创建了commandSave和DatasetInfos下的datasetCustom,他它们根据sample2_1.view.xml的内容进行了初始化,然后客户端把提交上来的datasetCustom的信息、Records信息和commandSave的parameters信息赋值给Sample2_1ViewModel对象里的相应属性和方法。这个时候datasetCustom的RecordSets里存在着3条记录,他们的状态分别为modify、delete、new;commandSave的parameters的存在名为test值为true的参数。
  4. 根据commandSave的定义,数据提交是执行Sample2_1ViewMode下save方法。方法里把上传上来的参数test的值打印出来;得到datasetCustom改变过的数据,在这里做出来,比如新增的把EMPLOYEE_NAME改变为STATE_NEW等,修改过得记录再修改EMPLOYEE_NAME的值为STATE_MODIFIED,直接在datasetCustom删除掉在页面已经删除的数据,并且把Record状态设置为页面Record的状态,回传页面的时候会把这些修改过得内容返回到页面;最后通过outParameter把结果参数信息success回传到页面。

     public void save(ParameterSet parameter, ParameterSet outParameter)
                throws Exception {
            String test = parameter.getString("test");
            System.out.println("提交上来的test参数值为:" + test);
            Dataset datasetCustom = this.getDataset("datasetCustom");
            RecordIterator recordIterator = datasetCustom.recordIterator();
            recordIterator.setVisibility(Dataset.FILTER_CHANGED);
            // 模拟update数据
            while (recordIterator.hasNext()) {
                Record record = (Record) recordIterator.next();
                switch (record.getState()) {
                case Record.STATE_NEW:
                    record.setString("EMPLOYEE_NAME", "STATE_NEW");
                    record.setDate("BIRTHDAY", new Date());
                    record.setState(Record.STATE_NONE);
                    break;
                case Record.STATE_MODIFIED:
                    record.setString("EMPLOYEE_NAME", "STATE_MODIFIED");
                    record.setDate("BIRTHDAY", new Date());
                    record.setState(Record.STATE_NONE);
                    break;
                case Record.STATE_DELETED:
                    datasetCustom.deleteRecord(record);
                    break;
                default:
                    break;
                }
            }
            // super.doUpdateData(parameter, outParameter);
            outParameter.setString("success", "success");
        }

    代码 2.2:Dataset数据提交

  5. Sample2_1ViewModel根据commandSave的outParameter内容和datasetCustom现在的对象和数据内容组装成XML数据。
  6. DoradoServlet把XML数据通过AJAX返回到客户端。
  7. 客户端BRich Engine先把outParameter的参数success赋值给客户端commandSave,如何根据datasetCustom返回的RecordSets的状态和改变内容来改变客户端datasetCustom的数据集。
  8. datasetCustom由于跟tableCustom、datapilotCustom绑定了关系,这个时候客户端BRich Engine根据他们的关系把tableCustom的内容显示更新,所有员工姓名和出生日期的值也改变成在服务端更新过的内容。
  9. 最后触发commandSave的onSuccess事件的内容:alert(command.outParameters().getValue("success"));,通过commandSave的outParameter得到返回的success参数alert出来。


图 2.6:HelloWorld提交结果