EAS BOS编程模型

更新时间:2024-07-07 16:24:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

EAS编程模型

目 录

1. 简介 ........................................................................................................................ 4

1.1. 1.2. 1.3. 1.4.

目的 ..................................................................................................................................... 4 范围 ..................................................................................................................................... 4 适用对象 ............................................................................................................................. 4 参考资料 ............................................................................................................................. 4

2. EAS业务开发过程 ................................................................................................ 4

2.1. 2.2.

EAS应用架构简介 ............................................................................................................. 4 EAS开发流程 ..................................................................................................................... 5

2.2.1. 2.2.2. 2.2.3. 2.2.4.

2.3. 设计业务对象 ................................................................................................... 6 调整数据库结构 ............................................................................................... 7 设计查询对象 ................................................................................................... 7 设计界面 ........................................................................................................... 8 小结 ..................................................................................................................................... 8

3. 基本编程模型与操作过程 .................................................................................... 8

3.1. 3.2. 3.3.

样例需求简要描述 ............................................................................................................. 8 准备阶段 ............................................................................................................................. 9 实现一个单据编辑功能 ..................................................................................................... 9

3.3.1. 3.3.2.

3.4. 元数据建模 ....................................................................................................... 9 编写业务逻辑 ................................................................................................. 16 实现一个单据序时簿功能 ............................................................................................... 17 元数据建模 ..................................................................................................... 17 编写业务逻辑 ................................................................................................. 19 让程序运行起来 ............................................................................................................... 20 为单据加上打印功能 ....................................................................................................... 21 列表打印 ......................................................................................................... 21 单据打印 ......................................................................................................... 21 为业务操作加上日志功能 ............................................................................................... 23 为单据加上工作流 ........................................................................................................... 24

定义事件 ......................................................................................................... 25 定义业务功能 ................................................................................................. 26 定义流程 ......................................................................................................... 27 发布流程 ......................................................................................................... 27

3.4.1.

3.4.2.

3.5. 3.6.

3.6.1. 3.6.2.

3.7. 3.8.

3.8.1. 3.8.2. 3.8.3. 3.8.4.

4. 编程注意事项 ...................................................................................................... 28

4.1.

协议类 ............................................................................................................................... 28

4.1.1. 4.1.2. 4.1.3. 4.1.4. 不要在协议类中引用客户端或服务端特有的类 ......................................... 28 尽量使用Selector来限制查询数据量 .......................................................... 28 所有的金额、数量属性统一用BigDecimal类型 ........................................ 28 正确地构造BigDecimal................................................................................. 28

4.2. 服务端 ............................................................................................................................... 29

4.2.1. 4.2.2. 4.2.3. 4.2.4. 4.2.5. 4.2.6.

4.3. 不要用对象级的变量存储信息 ..................................................................... 29 在EJB组件中不要启动多线程 .................................................................... 29 获取当前登录信息 ......................................................................................... 29 数据库资源的正确释放 ................................................................................. 29 尽量使用参数化的SQL ................................................................................ 30 避免写只适用于特定数据库的SQL ............................................................ 30 客户端 ............................................................................................................................... 30

获取当前登录信息 ......................................................................................... 30 获取组件的远程接口 ..................................................................................... 30 侦听器的挂接和卸载 ..................................................................................... 30 菜单、工具栏、快捷键的禁用与启用 ......................................................... 31 后台线程更新UI ............................................................................................ 31

4.3.1.

4.3.2. 4.3.3. 4.3.4. 4.3.5.

5. 总结 ...................................................................................................................... 31

EAS编程模型

1. 简介 1.1. 目的

以一个简单的单据业务处理案例为例,描述EAS的开发流程和具体实现过程及细节,形成全面的编程模型供开发人员参考。

1.2. 范围

范围包括:开发实现过程, BOSStudio中的设计开发操作步骤、开发业务逻辑的细节和部分样例代码。

1.3. 适用对象

本文档适用于: ? 系统设计师 ? 开发工程师

1.4. 参考资料

2. EAS业务开发过程

2.1. EAS应用架构简介

EAS的客户端采用Swing作为界面展现方式,服务端采用J2EE应用服务器的无状态Session Bean组件模型,两者间的通讯由自定义的ORM RPC服务提供。相对于直接采用EJB远程接口的方法,ORM RPC可以跨越防火墙,客户端不依赖于J2EE平台;相对于Servlet响应HTTP请求的方法,ORM RPC有效率上的优势,可以在不同的通讯协议间切换。 以下是EAS应用架构的概要图:

UI通过远程接口向服务端发送请求,ORM RPC服务接受请求后转发给相应的EJB组件。在EJB组件中,我们可以通过ORMapping来访问数据库,对于特别复杂的业务,也可以直接编写符合KSQL规范的查询语句,由Kingdee JDBC Driver运行。KSQL针对不同的目标数据库对查询语句作必要的翻译。最终查询语句被送至各厂商提供的JDBC Driver执行并返回结果。

UI与服务端之间属于无状态连接,所以框架在服务端维护了一个会话信息(Context)的列表,在同一次会话的多次请求间建立了联系。登录等功能模块在这个会话信息中存储了当前财务组织、当前用户等业务数据,在实现业务逻辑时,可以直接从中获取相关数据。框架也将该信息缓存到客户端,只是在名字上有所不同(SysContext)。

上述步骤中网络通讯与数据库访问是耗时较大的过程,在编写业务逻辑时要尽量减少UI与应用服务器的交互,减少对数据库的访问,尤其注意不要在循环中执行这样的代码。

2.2. EAS开发流程

元数据是支撑框架运行的基础。定义元数据、发布元数据、在发布代码中添加业务逻辑成为当前开发工作的基本模式。在应用架构中,各业务功能需要重点处理的是UI与EJB组件的逻辑。BOS集成开发环境与应用框架类库为实现这两个任务提供了很大的便利。基于BOS和应用框架的开发流程主要由四个步骤组成:设计业务对象、调整数据库结构、设计查询对象、设计界面。 2.2.1. 设计业务对象

我们可以从Together的设计模型中导出BOS业务对象,也可以在BOS中手工定义。一般来说,详细设计模型中的一个“实体类”对应一个BOS业务对象。下图展示了定义一个业务对象的大致过程:

KINGDEE DOC ID:KDSP_EAS_T_V3.0.0 软件构架设计文档 第 7 页 共 31 页 在定义一个业务对象前,应该详细分析它的特征,在应用框架中选择合适的基类,这样定义出来的业务对象就具备了一些典型业务的逻辑,例如从DataBase继承的业务对象自动具有新增、保存等基本功能。有关应用框架类库体系的介绍,详见《应用框架编程制南》。 业务对象的继承分抽象继承与非抽象继承两种。两者的区别在于数据存储结构不同,在业务逻辑上没有区别。前者将基类属性存储到子类对应的表,后者将基类属性存储到基类对应的表。

业务对象的属性分为两种:自有属性与连接属性,后者是与其它业务对象关联的属性,在建立连接属性前必须先定义对象间的关系。有两种特殊的自有属性须特别注意:一种是枚举类型,详见TODO;另一种是多语言属性,当指定某属性为多语言后,BOS发布工具将为该属性生成多个字段,每个字段对应一种语言,ORMapping会根据当前系统语言确定存取哪个字段。

业务对象可以拥有一个逻辑主键,主键是对象的唯一标志,由若干个属性组成。必须注意的是,在某些特殊场合下,例如只批量地更新或查找,不操作单个记录,我们不应该额外地去设置一个逻辑主键,否则将给批量操作带来很多麻烦。

定义业务方法时应根据该方法执行的操作正确设置事务属性,通常将只进行查询操作的方法设置为“Supports”,否则为“Required”。若该方法须抛出业务异常,则在异常列表处添加EASBizException声明。 根据需要,我们可能配置一些业务对象类及其属性的扩展属性,这些扩展属性用于实现编码规则、BOTP、权限等功能,详细列表请参见TODO。 一个业务对象发布后将生成协议类、远程与本地接口、EJB组件类,以及用于部署的组件描述符。我们可以在EJB组件类中编写业务逻辑。 2.2.2. 调整数据库结构

业务对象相关的表可以用BOS的“实体导出为表”功能创建,但默认生成的存储结构不是非常合理,需要手工调整。 首先,根据“$/KDSP3.0/PDSP-EAS/过程&指南/2_G_设计指南_数据建模规范.doc”调整表名、字段名、主键名、索引名、外键名。其次,根据字符型字段将要存储的数据选择是否支持Unicode以及字段长度等。最后,根据需要增加索引,以提高程序运行效率。 2.2.3. 设计查询对象

BOS提供的查询对象为实现一些简单的查询提供了很大的便利。查询对象可以与F7控件、通用过滤排序对话框、列表界面直接绑定,只需写少量代码就可以完成一个基本的业务功能。 查询对象的字段可以由主对象及其子对象的属性导入,也可以定义成计算式。对于专用于F7控件的查询对象,一般要定义它的默认排序条件。如果要支持虚模式取数,查询对象还须定义一个主键。在执行虚模式查询时,程序首先得到一个主键列表,之后的查询都将直接通过主键而不是原始过滤条件查询,此方式大大提升了分页性能。

KINGDEE DOC ID:KDSP_EAS_T_V3.0.0 软件构架设计文档 第 8 页 共 31 页 查询对象及其属性都有相关的扩展用于实现F7查询、通用过滤排序等功能,详见TODO。

2.2.4. 设计界面

对应于服务端组件,UI在应用框架中也有一整套典型业务的基类,设计界面前应该选择合适的基类。为适应不同的显示分辨率,界面通常采用KDLayout布局。人机界面规范(http://uiserver/Guide/EAS/index.htm)对控件的选择、排列、规格等都作出了明确规定,建议一开始就严格遵守界面规范,以免后期返工。 界面可以是一个空容器,也可以与业务对象或查询对象绑定。一般来说,编辑性质的界面与它操作的业务对象绑定,而序时簿性质的界面与一个查询对象绑定。绑定后的界面会自动根据对象属性类型分配不同的控件,并添加装载与保存的代码。

设计期的一个重要任务是定义Action,每个Action可能与界面的菜单、按钮或快捷键对应,用户对界面元素的操作将触发不同的Action事件。BOS将Action的功能作了扩展,不仅用它来控制相关界面元素的状态,而且将它与权限控制(详见TODO)、工作流(详见TODO)等基础服务联系起来,以一种可配置的方式提供基础服务。

2.3. 小结

本节简要地介绍了EAS的应用架构以及开发的基本流程,目的是给初学者一个整体的映像,明确在开发过程中的主要任务以及框架运行的基本原理。后面的章节将以一个实例详细地描述开发流程的各个方面,包括打印、工作流等高级应用。

3. 基本编程模型与操作过程 下面通过

3.1. 样例需求简要描述

本节为了重点是说明开发技术,选择了一个相对简单的需求:实现一张单据的维护功能,该单据可以在序时簿中查找、过滤,具有新增、修改、删除等基本功能,支持打印与打印预览,单据提交后经过多级审批到达工作流结束点。通过这些实现来描述EAS的基本编程模型和操作过程。 单据头属性列表: 名称 公司 单据类型 编号 业务日期 类型 业务对象 枚举 字符串 日期 描述 单据所属财务组织,默认为当前公司 只有两种类型:甲、乙 单据的编号。为简单起见,由用户输入,系统保证编号不重复。 说明业务发生的日期 KINGDEE DOC ID:KDSP_EAS_T_V3.0.0 软件构架设计文档 第 9 页 共 31 页 制单

单据体属性列表: 名称 摘要 科目 金额

业务对象 类型 字符串 业务对象 数字 单据创建者,默认为当前用户 描述 用户可以选择或直接输入 可以选择,按单据头公司隔离 本位币金额,需处理币别精度,提供千分号 3.2. 准备阶段

(1) 从\\\\192.168.16.62\\eas4.1 下拷贝setup.bat执行,安装开发环境;

(2) 执行W:\\admin\\pt.bat更新最新的日构件,将W:\\eas\\deploy\\apusic\\metas.jar解压到

W:\\apusic\\metas目录下,然后修改配置文件: i. W:\\eas\\deploy\\apusic\\bosconfig*.xml

ii. W:\\eas\\deploy\\client\\config.xml

(3) 从192.168.16.5/bos3.0上Check out整个eas工程,并且在BOS透视图中作为解决方案打开,并且设置解决方案的属性:

如此设置后,程序运行时将从W:\\apusic\\metas目录下读取最新发布的元数据。

(4) 新建一个Java工程,取名为sample,建立一个src目录用于存放源文件,classes目录为输出

路径,并且将classes路径加入W:\\eas\\dev下的配置文件server-user.liblist。这样,程序运行时将优先读取工程最新编译的类文件,而不是部署包。工程依赖的包统一放置于W:\\eas\\lib\\debug。

3.3. 实现一个单据编辑功能

3.3.1. 元数据建模

参照前一节“基本开发流程”的描述,我们需要进行四个步骤的建模。

3.3.1.1. 定义业务对象—单据头

经过详细设计阶段,我们可以分析出该功能有一个唯一的实体类—单据,查找应用框架类层次,

KINGDEE DOC ID:KDSP_EAS_T_V3.0.0 软件构架设计文档 第 10 页 共 31 页 发现BillBase这个基类最适合派生,因为它包含了单据共有的一些属性,而且提供了单据的一般操作方法。选择基类点击确定后,我们可以得到如下的类信息:

注意:由于控制器相关的类将被部署在服务端,所以将它放在app包中。我们可以手工输入表对象的名称,该表不一定物理存在,在使用“实体导出为表”时,BOS将根据表对象名称新建或覆盖数据表。

3.3.1.1.1. 定义属性

切换到第二个页签“属性”,我们发现大多数单据头属性基类都已经提供,只需要额外定义一个枚举类型的属性“单据类型”。我们首先定义一个枚举对象:

该枚举类将被业务对象的协议类引用,所以必须定义在com.kingdee.eas.sample包下,部署程序会将该包下的类同时发布到服务器与客户端。

之后就可以基于枚举对象定义“单据类型”属性了,如图:

KINGDEE DOC ID:KDSP_EAS_T_V3.0.0 软件构架设计文档 第 11 页 共 31 页

其中的字段“FBillType”与前面的表对象一样,不一定要存在。根据命名规范,字段名以F开头,这样可以防止与数据库系统的内部变量冲突。 3.3.1.1.2. 定义逻辑键

定义好属性列表后,就可以指定其中的某些属性作为逻辑键,此处我们保留默认的继承属性id为逻辑键。

KINGDEE DOC ID:KDSP_EAS_T_V3.0.0 软件构架设计文档 第 12 页 共 31 页 3.3.1.1.3. 定义方法

业务对象的方法最终被发布为EJB组件的接口方法,可以远程调用。方法可以直接从基类导入或者手工创建。一般来说,我们只导入getCollection系列方法,这样可以提供强类型的集合对象返回值(注意:SampleBillCollection直接从AbstractObjectCollection继承,与BillBaseCollection没有派生关系),其它方法可以直接在派生类中override。

我们还定义了一个方法fetchInitData,用于返回界面初始化需要的参数,该方法只执行查询,因此事务属性设置为“Supports”,返回值类型为java.util.HashMap,并且抛出com.kingdee.eas.common.EASBizException。注意,参数、返回值、已经异常声明必须从下拉列表中选择或者直接填写完整的类名(包含包名)。 3.3.1.2. 定义业务对象—单据体

单据体的定义过程与单据头类似,不再赘述。需要注意的是“金额”属性的数据类型应该选用BigDecimal,该属性类型可以提供任意精度的数字,在财务核算系统中这个特性尤为重要。 3.3.1.3. 定义业务对象的关联关系

单据头与单据体是一对多的关系。为了在程序中可以在两者直接相互导航,我们可以给这两个对象建立一个关联。首先定义一个关系对象:

KINGDEE DOC ID:KDSP_EAS_T_V3.0.0 软件构架设计文档 第 13 页 共 31 页

基于该关系对象,在单据头中定义entries属性关联到单据体,对应地,单据体上的bill属性关联到单据头:

同样地,定义出单据体与科目的关联关系。

3.3.1.4. 定义数据表

完成业务对象的定义后,我们可以利用BOS的导表功能轻松得到表结构元数据。在BOS的“包视图”中右键选择实体对象,并选择“实体导出为表”,就可以得到下列表结构:

KINGDEE DOC ID:KDSP_EAS_T_V3.0.0 软件构架设计文档 第 14 页 共 31 页 需要注意其中的FDesc字段,单据体的备注字段被设计成可以存储Unicode字符(NVARCHAR),最大长度为200。对于金额字段,不允许存储空值,可以设置默认值为0,当设计跨数据库程序时,这点非常重要,因为不同数据库对聚合函数中空值的处理可能不一致。对于FSeq和FBillID,这两个字段不允许为空,从数据库约束层面来保证业务逻辑。 之后右键选择数据表将它们导出到业务数据库。

3.3.1.5. 定义编辑界面

与业务对象相对应,应用框架在UI层也有一个类库体系,我们可以选择BillEditUI作为该功能的基类。在向导的第二步,可以指定界面与SampleBill实体绑定。在第三步中可以选择与控件绑定的属性。点击完成后,BOS自动生成了相关的控件,并按照默认布局排列。 为了适应不同的显示分辨率,应该界面的布局为KDLayout,该布局管理器可以根据窗口大小自动重排控件。 对于单据体上的科目属性,BOS目前无法生成绑定信息,必须手工在表格设计器中新建一列:

KINGDEE DOC ID:KDSP_EAS_T_V3.0.0 软件构架设计文档 第 15 页 共 31 页

然后手工增加绑定信息:

3.3.1.6. 发布元数据

至此,我们完成了编辑功能所需元数据的定义,现在可以右键选择它们发布。切换到Java透视图,刷新包资源管理器,我们可以看到src文件夹下新建了很多Java源文件。 (1) 协议类

com.kingdee.eas.sample包下放置的都是协议类,包括数据包、组件接口以及枚举对象等。最终部署时,客户端与服务器都将装载这些类。协议类中不要编写引用服务器或客户端特有类的代码,否则将出现类无法装载的异常。

协议类类型 类名 接口类 数据包 ISampleBill SampleBillFactory AbstractSampleBillInfo、 说明 SampleBill组件接口 创建组件接口的工厂 SampleBill的数据包,提供强类型的数

KINGDEE DOC ID:KDSP_EAS_T_V3.0.0 软件构架设计文档 第 16 页 共 31 页 SampleBillInfo、 据访问接口。其中抽象基类在每次发布AbstractSampleBillCollection、 时重新生成,所以不要在其中编写逻辑。 SampleBillCollection 枚举对象 SampleBillType 提供多语言支持的枚举类 (2) 服务端组件

com.kingdee.eas.sample.app包下放置的是EJB组件类,这些组件类与EJB规范相同, 不再赘述。 (3) 客户端代码

com.kingdee.eas.sample.client包下放置了客户端相关的代码。其中的抽象基类

AbstractSampleBillEditUI中包含了初始化界面、数据绑定相关的逻辑,每次发布元数据,该文件将被重新生成。我们可以在SampleBillEditUI中编写特定的逻辑,该文件在重新发布时不会被覆盖。

3.3.2. 编写业务逻辑

前面提到AbstractSampleBillEditUI中包含了初始化界面、数据绑定等基本逻辑,我们现在所要做的是在SampleBillEditUI中编写特定的业务逻辑。重点在于下列方法:

方法名称 onLoad 描述 界面初始化事件。可以在此: 1、 获取UI的上下文和初始化数据; 2、 设置控件风格; 3、 设置界面组件的状态; 将业务数据装载到控件。数据绑定代码在super.loadFields中。 从控件中获得最新的业务数据。数据绑定代码在super.storeFields中。 指定查询单据对象时需要的属性列表。 在客户端检查业务逻辑合法性,不合法时抛出异常。 此处的检查不能代替服务端的校验,只是为了在业务数据非法时尽量少地提交服务端。 创建一个新业务对象,在新增时被调用。 可以在此处为业务对象的属性赋默认值。 创建一个新分录对象,在新增分录时被调用。 可以在此处为分录对象的属性赋默认值。 在复制业务对象时,需要将它的一些属性置空或改变,例如对象的ID和分录的ID。 创建各个属性的编辑器,重点关注: 1、 带扩展解析器的F7; 2、 可支持模糊查询与专用对话框的F7; 3、 金额编辑器的创建; 创建各个属性的绘制器,重点关注: loadFields storeFields getSelectors verifyInput createNewData createNewDetailData setFieldsNull getXXXEditor getXXXRender KINGDEE DOC ID:KDSP_EAS_T_V3.0.0 软件构架设计文档 第 17 页 共 31 页 1、金额格式化输出;

这些方法中都有很详细的代码注释。

服务端的代码相对简单,重点关注3个方法: 方法名称 _fetchInitData _submit 描述 获取初始化数据,重点关注: 1、 如何从Context中获取登录信息; 提交业务数据,重点关注: 1、 如何使用_exists等方法; 2、 如何存取分录; 删除业务数据,重点关注: 1、如何删除分录; _delete 至此,我们已经完成了单据编辑的基本功能,具备了新增、修改、删除、复制等功能,支持各种编辑器和格式化的输出。

3.4. 实现一个单据序时簿功能

3.4.1. 元数据建模

3.4.1.1. 定义查询对象

通过定义查询对象(Query),我们可以快速地实现序时簿这种简单的查询功能。以SampleBill实体为主对象,我们定义了如下的Query:

KINGDEE DOC ID:KDSP_EAS_T_V3.0.0 软件构架设计文档 第 18 页 共 31 页 对于查询字段,需要注意“可见性”这个选项,若不选择该项,则Select字句中将不出现该字段,但它还可用于Where或Order by子句中。 为了使用通用的过滤排序对话框,我们还需要定制字段的扩展属性。如下: 名称 isCommonQueryFilter isCommonQuerySorter isUsingF7 defaultF7Query 类型 布尔 布尔 布尔 字符串 描述 字段是否出现在“自定义”页签的下拉列表中。 字段是否出现在“排序”页签的下拉列表中。 在“自定义”页签中,是否可以用F7输入比较值。 若isUsingF7为true,该属性制定一个F7 Query的全路经。 Query的主键指定为id,这样列表界面在查询时将先取ID列表,然后分批次用ID取实际数据;若不指定主键,则列表界面将采用SELECT TOP N方式查询,在数据量很大时,这种方式的性能表现不是非常理想。 3.4.1.2. 定义列表界面

以ListUI为父类,以上节定义的Query作为绑定对象,可以很容易地生成一个列表界面。该界面的绑定信息如下:

KINGDEE DOC ID:KDSP_EAS_T_V3.0.0 软件构架设计文档 第 19 页 共 31 页

3.4.1.3. 定义过滤页签

所有的过滤页签都必须从com.kingdee.eas.base.commonquery.client.CustomerQueryPanel继承。该页签主要用于放置一些无法用通用过滤形式表示的条件选项,例如多选一、对起始和结束日期有约束等。我们在SampleFilterUI中放置了起始日期和结束日期两个选项。 3.4.1.4. 发布元数据

发布后,client下将生成SampleBillListUI和SampleFilterUI相关的类文件。

3.4.2. 编写业务逻辑

由于列表界面SampleBillListUI功能相对简单,所需重写的方法较少: 方法名称 onLoad 描述 界面初始化事件。可以在此: 1、获取UI的上下文和初始化数据; 2、设置控件风格; 3、设置界面组件的状态; getDefaultFilterForQuery 返回默认的过滤条件,本例中,只过滤当前公司的单据。 initCommonQueryDialog 必要时构造一个通用过滤排序对话框,重点关注: 1、 如何设置对话框大小; 2、 如何预置过滤排序条件; 3、 如何添加特有的过滤页签;

过滤界面SampleFilterUI的重要方法: 方法名称 getParam setParam getFilterInfo verify clear 描述 将界面控件值封装到参数对象。 解析参数对象将数据装载到控件。 将参数对象转化成FilterInfo,让通用对话框组合出一个完整的过滤排序条件。 在按确定按钮前被调用,用于验证过滤条件的合法性。 新建一个过滤方案时将被调用,可以在此处赋方案的默认值。 KINGDEE DOC ID:KDSP_EAS_T_V3.0.0 软件构架设计文档 第 20 页 共 31 页

3.5. 让程序运行起来

如下定义一个Java应用程序:

为了调试服务端程序还必须保证W:/admin/StartServer.pl中Apusic的启动参数包含下列选项:-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000,然后在eclipse中配置一个远程Java应用程序:

启动Apusic后,在eclipse中先后启动server与client应用程序,我们就进入了调试程序的阶段。 首先利用EAS的菜单编辑功能增加一个菜单:单据序时簿。唯一重要的一个菜单属性“UI对象”设置为:com.kingdee.eas.sample.client.SampleBillListUI。重新登录后就可以直接双击打开单据序时簿了。 现在单据的查询、新增、修改、删除等功能基本上已经齐备了。

KINGDEE DOC ID:KDSP_EAS_T_V3.0.0 软件构架设计文档 第 21 页 共 31 页

3.6. 为单据加上打印功能

3.6.1. 列表打印

列表打印相当简单,由于控件与应用框架的良好支持,我们只要写很少的代码就可以将该功能集成进来。详见SampleBillListUI的方法: 方法名称 preparePrintPageHeader getPrintExtVarProvider 3.6.2. 单据打印

相对列表打印,单据打印复杂得多,主要由3个步骤组成:

描述 此处可以增加表头行。行格式中可以使用变量。 提供preparePrintPageHeader中定义的变量的具体取值。 3.6.2.1. 准备打印元数据

打印元数据与前面提到的业务对象、查询对象等BOS元数据不同,它实际上是一个XML格式的描述文件,列举了可用于绑定模板控件的字段。定义一个新的元数据文件时可以复制一个类似功能的文件,然后对表名和字段名稍做修改就可以了。 定义好元数据后,可以用EAS套打设计器的存储管理功能将它引入到报表服务器上:

KINGDEE DOC ID:KDSP_EAS_T_V3.0.0 软件构架设计文档 第 22 页 共 31 页 注:为每一类单据定义一个元数据目录和一个模板目录,两者必须对应,名称也必须相同。

3.6.2.2. 设计打印模板

模板设计工具的具体使用不再详述,这里着重强调几点: 数据源的类型选择“BOS元数据”,在备选来源中选择第一步定义的元数据。

设置分录循环区内第一个分组容器的分组属性为“单据唯一标志”:

KINGDEE DOC ID:KDSP_EAS_T_V3.0.0 软件构架设计文档 第 23 页 共 31 页

3.6.2.3. 编写代码调用套打功能

在SampleBillEditUI的invokePrintFunction方法中,首先同步界面控件与业务对象的状态,之后将绑定信息传递给公用的打印数据源对象BillPrintDataSource,最后以数据源对象为参数调用KDNoteHelper.printPreview显示出预览窗口。

3.7. 为业务操作加上日志功能

添加日志功能非常简单,甚至不用写一句代码,在BOS Studio中打开service.log文件,增加如下配置项:

KINGDEE DOC ID:KDSP_EAS_T_V3.0.0 软件构架设计文档 第 24 页 共 31 页

日志项与业务对象的方法绑定,即该方法被调用时,相应日志项信息就会被记录到上机日志中。例如我们执行了一个新增单据的操作,将在日志中看到:

日志很清晰地记录了操作人、操作对象、执行时间等信息。 注意:修改service.log文件后,直接用BOS Studio的发布功能无法正常使用日志配置项,必须手工将其拷贝到W:/apusic/metas下。

3.8. 为单据加上工作流

我们将设计这样一个工作流:制单人提交单据后,将启动一个工作流实例,之后经过多级审批走到结束点,在单据被审批前制单人可以修改或删除它。如图:

KINGDEE DOC ID:KDSP_EAS_T_V3.0.0 软件构架设计文档 第 25 页 共 31 页

3.8.1. 定义事件

工作流的驱动过程与事件相关,而事件是与业务对象的方法绑定的,当方法被调用时,相关的事件被触发,从而将工作流驱动到下一节点。 因此首先定义两个事件evtSubmit与evtDelete,分别与方法submit与delete绑定。

KINGDEE DOC ID:KDSP_EAS_T_V3.0.0 软件构架设计文档 第 26 页 共 31 页

3.8.2. 定义业务功能

业务功能与界面元素关联,并且被指定到工作流的某个节点上。消息中心处理消息时,将读取当前节点关联的业务功能,从而找到相应的界面,将其展现出来。例如ActionSubmit功能,当流转到该指定了该功能的节点时,SampleBillEditUI将被调出。

KINGDEE DOC ID:KDSP_EAS_T_V3.0.0 软件构架设计文档 第 27 页 共 31 页

3.8.3. 定义流程

在这个流程中我们定义了两个普通的人工节点和一个审批节点: 节点名称 提交 删除 审批

变量名称 billID billNumber maResult

任务 ActionSubmit ActionRemove <无须设置> 类型 内码 字符串 枚举 出口参数 单据ID ==> billID 单据编号 ==> billNumber 审批结果 ==> maResult 描述 单据ID 单据编号 多级审批的结果 在定义消息或者编写脚本时,可以引用流程变量: 注:为了测试方便,我们将参与人全部设置成流程发起人。

3.8.4. 发布流程

为了使用公共的工作流批量处理功能,我们还需要稍微修改一下SampleBill.entity的扩展属性:

KINGDEE DOC ID:KDSP_EAS_T_V3.0.0 软件构架设计文档 第 28 页 共 31 页

定义好流程后,右键选择发布,流程就即时生效了。现在提交一张单据,切换到消息中心看看有没有新的消息。双击未处理消息就可以调出相应的功能界面了。

4. 编程注意事项

以下是一些编程的注意事项,提醒开发人员注意。

4.1. 协议类

协议类包括数据封装类和接口等。

4.1.1. 不要在协议类中引用客户端或服务端特有的类

在部署EAS时,客户端和服务端特定的类是分离的,只有协议类在两端都部署。因此若协议类中引用了服务端特有的类,则在客户端使用协议类时就会出现类找不到的错误;反之亦然。 4.1.2. 尽量使用Selector来限制查询数据量

ORMapping引擎将根据Selector指定的属性列表,从数据库中查询数据并封装到协议类中。Selector信息将直接影响到查询的数据量,所以应该尽量只检索必需的属性。一般的原则是只将程序中引用到的属性加入Selector。

4.1.3. 所有的金额、数量属性统一用BigDecimal类型

ERP系统对金额、数量的精度要求很高, 而float、double这些类型能够处理的精度有限,只有BigDecimal才能够支持无限精度的数字。程序在执行数学运算时也应该始终使用BigDecimal。 4.1.4. 正确地构造BigDecimal

BigDecimal有多个重载的构造函数,这些函数表面差异不大,对程序运行却有着至关重要的影响。若是用BigDecimal(double)构造一个数字,则在传入JDBC存储到数据库时将可能出现OutOfArrayIndexError异常。

KINGDEE DOC ID:KDSP_EAS_T_V3.0.0 软件构架设计文档 第 29 页 共 31 页

4.2. 服务端

EAS的服务端代码主要包括EJB组件类。

4.2.1. 不要用对象级的变量存储信息

前面提到过,EAS的服务端组件采用的是无状态SessionBean,在两次调用方法期间,可能是不同的EJB对象在响应请求,因此如果在对象变量中存储信息,可能会导致这些信息的紊乱。若遇到必须在多个方法间共享信息的情况,请考虑一下是否可以用参数传递的方式解决。 4.2.2. 在EJB组件中不要启动多线程

EJB组件在当前线程上下文中存储了事务相关的信息,如果在组件中又启动了线程,则会出现事务的紊乱。与这条原则相关的一个比较隐蔽的场景出现在服务端调用Query查询中,Query查询时启动了一个新的线程获取记录ID,然后当前线程等待前者返回结果。所以绝对不要在服务端调用Query执行查询操作。

4.2.3. 获取当前登录信息

服务端的Context中存储了当前登录信息,可以通过工具类ContextUtil来获取当前组织、当前用户等信息。要对何时使用这些信息有个正确的认识,例如对单据的合法性进行校验时应该使用单据所属公司而不是登录信息中的当前公司。 4.2.4. 数据库资源的正确释放

数据库资源是非常有限的资源,若在使用完毕后长时间不释放,则可能导致资源耗尽,系统无法继续运行。这些资源包括结果集、语句、连接等,为了保证可以正常释放它们,一般要将释放代码放在一个finally子句中,如下:

Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { } finally { }

DBUtils.cleanup(rs, ps, conn); conn = getConnection(ctx); ps = conn.prepareStatement(sql); rs = ps.executeQuery();

KINGDEE DOC ID:KDSP_EAS_T_V3.0.0 软件构架设计文档 第 30 页 共 31 页 要保证有一个变量引用这些资源,以便在finally中释放它们。绝不允许下列代码出现: ps = getConnection(ctx).prepareStatement(sql);

这样,其它地方无法引用连接对象,也就无法释放它了。

4.2.5. 尽量使用参数化的SQL

一般数据库都会缓存执行过的SQL,若之后的查询SQL语句完全相同只是参数值不同,则可以直接执行,不需要再次翻译语句,可以大大提高执行效率。参数化的SQL还自动处理一些特殊字符如单引号等,避免了恶意攻击的发生。 4.2.6. 避免写只适用于特定数据库的SQL

尽管我们有了KSQL翻译引擎,可以写出标准的KSQL让引擎针对不同的目标数据库执行必要的翻译。但这仅仅是语法层次的翻译,有些语句从语法上看完全符合KSQL标准,引擎也可以正确翻译,但是可能带来意想不到的问题。例如Update T1 Select From T2这种语法只有SQL Server直接支持,若目标数据库是Oracle、DB2等,KSQL引擎翻译后的语句将是一个极其低效的查询。当遇到这种情况时应该考虑是否可能用循环更新来代替,以便程序具有更好的跨数据库能力。

4.3. 客户端

4.3.1. 获取当前登录信息

与服务端相对应,客户端也有一个对应的类存储当前登录信息:SysContext,其中存储 当前公司、当前用户等信息。 4.3.2. 获取组件的远程接口

组件的远程接口一般通过调用XXXFactory.getRemoteInstance()得到,这是一个比较耗时的过程,所以想到了将它缓存到界面上。但是绝对不要这么做,EAS现在提供了一个网络续连的功能,当出现网络问题时,自动弹出一个窗口,让用户选择“退出”还是“连接”,若选择“连接”,则再次获取远程接口进行调用。若缓存了该接口,则这个界面始终只能使用这个损坏的连接,无法支持网络续连。 4.3.3. 侦听器的挂接和卸载

Swing的事件模式采用了大量的Listener,这些Listener负责监视相关事件的发生,在必要时调用事件响应代码。当应用框架装载业务数据时(loadFields),数据被填充到相关控件中,这可能引起大量事件的触发。为了避免这个情况,一般在loadFields中采用以下逻辑: detachListeners; load data to controls; attachListeners;

KINGDEE DOC ID:KDSP_EAS_T_V3.0.0 软件构架设计文档 第 31 页 共 31 页 在装载数据前首先去掉所有的监听器,数据装载完毕后再次安装,从而避免了大量无效的事件响应。

4.3.4. 菜单、工具栏、快捷键的禁用与启用

EAS用一个Action将菜单、工具栏、快捷键联系起来,并且在Action上提供了Enable和Visible属性。只要直接设置Action的这些属性就可以控制三者的状态,不应该逐个去控制。 4.3.5. 后台线程更新UI

界面编程有时必须采用多线程,例如进度条的显示,此时UI线程显示一个进度窗口,后台工作线程则将实时进度反映到进度条中。由于Swing控件不直接支持多线程,后台线程应该调用SwingUtilities.invokeLater或invokeAndWait执行界面更新操作。

5. 总结

该文档以一个单据业务例子描述了EAS真个实现的过程和编程模型。 通过学习这个文档并结合样板工程的操作指导和范例代码,新开发人员应该能够比较快速地编写出高质量的代码。

KINGDEE DOC ID:KDSP_EAS_T_V3.0.0 软件构架设计文档 第 31 页 共 31 页 在装载数据前首先去掉所有的监听器,数据装载完毕后再次安装,从而避免了大量无效的事件响应。

4.3.4. 菜单、工具栏、快捷键的禁用与启用

EAS用一个Action将菜单、工具栏、快捷键联系起来,并且在Action上提供了Enable和Visible属性。只要直接设置Action的这些属性就可以控制三者的状态,不应该逐个去控制。 4.3.5. 后台线程更新UI

界面编程有时必须采用多线程,例如进度条的显示,此时UI线程显示一个进度窗口,后台工作线程则将实时进度反映到进度条中。由于Swing控件不直接支持多线程,后台线程应该调用SwingUtilities.invokeLater或invokeAndWait执行界面更新操作。

5. 总结

该文档以一个单据业务例子描述了EAS真个实现的过程和编程模型。 通过学习这个文档并结合样板工程的操作指导和范例代码,新开发人员应该能够比较快速地编写出高质量的代码。

本文来源:https://www.bwwdw.com/article/bni.html

Top