中国联通云门户-流程服务项目-开发及编码规范

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

中国联通云门户项目
流程服务
项目开发及编码规范
中国联合网络通信集团有限公司
2022-03-22
产权说明
本文件中出现的任何文字叙述、文档格式、插图、照片、方法、过程等内容,任何个人、机构未经授权许可,不得复制或引用本文件的任何片断,无论是通过电子形式或非电子形式。

文档信息
项目名称:中国联通云门户项目
项目经理:肖永威文档版本号:v 1.1
项目阶段:设计阶段文档版本日期:2012年12月120日起草人:张玉明起草日期:2012年12月13日评审人:评审日期:
评审方式:会议评审【】、邮件评审【】
版本历史
版本号版本日期作者说明
v 1.0 2012-12-13 张玉明创建文档
v 1.1 2012-12-17 张玉明修订文档,
增加WS配置classpath
增加流程建模复用组件配置及使用规范
v 1.2 2012-12-18 张玉明增加4.5 Identifiers数据提取v 1.3 2012-12-18 张玉明、刘彦利增加 3.3.5 方法集和命名空间v 1.4 2012-12-20 张玉明增加 4.8 4.9节
v 1.5 2013-01-22 张玉明增加 3.3.7节
目录错误!未找到引用源。

1概述
指导云流程服务项目开发,提供设计、开发、编码的参考、执行规范。

1.1 目标
规范项目各环节实施、开发、编码规范,以及故障处理、调优问题汇总记录。

此文档会在整个项目实施过程中不断维护,保持版本更新。

1.2 名词解释
Cordys
CWS
REST
BinLog
2功能设计
2.1 页面设计
2.1.1 页面设计一般原则
2.1.2 XFORM开发原则
2.1.3 菜单
菜单项应当赋予角色,而不是直接赋给用户
2.1.4 调试
可以使用fiddler、httpwatch、firebug、IE developerToolbar来对Http请求及JS脚本进行调试和性能调优。

2.2 数据库设计
2.2.1 原则
数据库设计必须符合第一范式。

数据库只保留基本逻辑约束,包括以下方面:
●主键
●主子表关联外键约束
属性表不添加外键约束。

所有数据库设计的内容体现在数据模型文档中,针对特定字段的约束体现在该字段的属性和注释中,需要特别说明的,可以在物理模型图中加Notes。

注意:由于本项目中使用的是Cordys BOP平台产品,在BOP中能够提供API来解决的或者可以通过查询平台系统表提取数据的,原则上不要再增加新表来辅助设计和逻辑实现,以避免后期与应用耦合性过高。

2.2.2 主键
以单一整形或字符串类型字段做主键。

2.2.3 关联
当一个表通过外键引用另一个表时,往往主表的删除意味着相关记录的删除,如果确认这里的业务逻辑是正确的,而且没有其他的影响,可以使用“级联删除”选项来简化代码,但必须在相应的数据库模型上有所体现。

同样的,“级联更新”也起到类似的作用。

2.2.4 触发器
对于一些简单的,基本业务无关的数据操作,可以使用触发器来实现:比如生成序列号。

但业务相关的,复杂的逻辑,则避免在触发器中实现。

2.2.5 索引
对于查询频度远高于修改的数据表,或者需要经常对查询结果排序的表,创建相应的索引。

2.3 流程设计
2.3.1 原则
以详细设计为准,模型设计摘要如下。

1.创建流程模型时修改流程的namespace,如下所示:
/laiyifen/tbpm
2.泳道颜色使用双色交替,循环使用cordys提供的第1个颜色和第2个颜色,
3.泳道间的间距1px
4.泳道的长度要统一
5. decision的描述用“...是否...”,条件描述为“是”“否”,摆放位置应在连接线的起始端,水平连线上方、垂直连线右侧,偏移位移在5px以内
6.当decision的出口在3条或3条以上,根据实际业务情况进行描述
7.活动节点间的连线,水平或垂直平行时用直线,除此之外用带直角的连线
8. group组件上下边框应大于泳道边界1px,group的描述有实际的业务含义
9.流程中的组件大小用default。

如果文字太多(超过50字时),可根据实际情况调整
10.相同组件的大小在同一流程模型中保持一致
11.流程的起始位置在上方,结束位置在下方
循环中驳回节点尽可能共用,以减少驳回节点个数
3项目构建与编码规范
本项目开发基于Cordys BOP 4.1平台进行开发。

Cordys层使用SOAP WS进行服务开发,中间层使用RESTful的WS对外暴露资源和服务。

REST风格的WS使用Jboss Resteasy作为框架的基础上进行开发,开发测试服务器使用Apache Tomcat 7.0,JDK 统一使用1.6,Eclipse需要 eclipse-jee-juno 版,并整合Cordys CoE插件作为WS开发IDE。

开发数据库使用 MySQL 5.5+,推荐使用5.5.19版,生产环境使用MySQL Master/Slave模式,前端连接使用MySQL Proxy模式进行JDBC连接。

开发工程包DEMO中提供了Ant打包脚本,方便进行服务打包,第三方常用的lib库则都包含在EIP DEMO 工程中,请避免使用其他版本的库。

每个EIP服务的客户端是一个Jar文件,命名为XXX_impl.jar,最新的客户端jar文件以现网运行的版本为准。

开发工程包请向开发人员索取。

3.1 项目开发工具一览表
平台:Cordys BOP4.1 Cu7
MySQL Server:MySQL Server Community 5.5.19
Eclipse IDE:eclipse javaee juno with
Cordys CoE plugin
Svn plugins:
Eclipse update site URL: /update_1.8.x
MySQL Tools:Navicat for MySQL 10.0.11 enterprise edition
Web Contanier:Apache Tomcat v7.0
Web Browser: Google Chrome 最新版,Mozilla Firefox,IE 8 +,推荐使用Chrome浏览器进行开发。

SSH客户端:Xmanager 3.0 +,SecureCRT 7.0,推荐使用XME 3.0,可以直接使用图形界面,
FTP客户端:Xftp,Filezilla
XML格式化工具:foxe(XML 格式化工具)、XPathVisualizer 1.3.0
文本编辑工具:Notepad++ 6.22

3.2 开发资源及服务器信息
3.2.1 SVN服务器
1、项目开发服务器地址:
https://10.64.6.98:8443/svn/cloudbpm
项目开发人员帐号,联系配置管理员获取。

开发服务器管理员帐号:
远程桌面:adminstrator 密码:联系相关人员
IP:10.64.6.98
SVN客户端需使用TortoiseSVN 1.7.*
2、公司SVN服务器:
项目根路径:http://10.64.8.160/svn/20121123/YMHLCFW/
注意:本节以下所述SVN地址均相对此项目SVN根路径
开发工程SVN地址:
✧Cordys中CWS创建项目工程时绑定的SVN地址:
00Developing/02code/cloudbpm/trunk/projects/bpm-cordys-cws-all
✧Cordys中CWS中创建的Java代码在Eclipse中编辑时,需下载Eclipse工程,下载地
址:
00Developing/02code/cloudbpm/trunk/project/bpm-cws-java
✧项目基础类库开发的Eclipse工程SVN地址:
00Developing/02code/cloudbpm/trunk/project/bpm-common
✧项目REST服务开发的Eclipse工程SVN地址:
00Developing/02code/cloudbpm/trunk/project/bpm-rest
✧项目java版本SDK开发的Eclipse工程SVN地址:
00Developing/02code/cloudbpm/trunk/project/bpm-sdk-java
✧项目php版本SDK开发的工程SVN地址:
00Developing/02code/cloudbpm/trunk/project/bpm-sdk-php
类库Jar包发布地址
✧项目基础类库编译后jar包发布的SVN地址:
00Developing/02code/cloudbpm/trunk/projects/bpm-cordys-cws-all/rest-ws/Java/Java Archives/bpm-lib
✧第三方厂商-HP提供的类库发布的SVN地址:
00Developing/02code/cloudbpm/trunk/projects/bpm-cordys-cws-all/rest-ws/Java/Java Archives/hp-eip-lib
开发工具下载地址
00Developing/02code/cloudbpm/trunk/tools
版本标签创建地址
00Developing/02code/cloudbpm/tags/
注意:各模块在模块目录下创建版本标签
个人目录地址:
00Developing/04personal
每人的文件夹下有三个文件夹
根据每天的任务,将相应的成果放到这三个文件夹里
每天都得将当天成果放入文件夹中提交,并在svn备注中写明当天提交的是什么,多少个功能点3.2.2 Cordys BOP4 开发服务器
CordysBOP4:
服务器访问地址http://10.64.8.149/cordys/
位置:黑龙江集成公司
按开发人员建立租户,在各自的租户下进行开发
开放服务:SSH FTP
MySQL数据库:
数据库名:eipdb
数据库地址:10.64.8.149
端口:3306
用户名:eip_app1
密码:True
Tomcat Server:
地址:10.64.8.149
端口:8080
管理用户:admin / admin
webappRoot:/usr/local/tomcat-7.0.33/webapps
FTP用户
ftp://10.64.8.149
用户:ftpuser
密码:ftpTrue
Cordys Bop集团服务器:
访问地址http://10.0.3.157/cordys/
位置:集团
按开发人员建立租户,在各自的租户下进行开发
3.3 Cordys BOP平台
3.3.1 测试环境租户建立规范
EIP云门户端是按省分分配的应用ID。

EIP云门户中的‘EIP应用ID’、‘EIP租户ID’与Cordys流程平台中的‘CARS租户’的对
应规则为:
‘EIP应用ID’-‘EIP租户ID’=‘CARS租户ID’
由于Cordys中租户为LDAP的DN格式,所以‘CARS租户ID’对应的‘CARS租户DN’
为:
cn=zhangym195,cn=organizational users,o=CARS租户ID,cn=cordys,cn=defaultInst,o=
例如:EIP中的某XX系统的应用ID为na999,某YY的租户ID为hl328,其对应的Cordys中
的租户ID为hl328-na999,对应的Cordys中的租户DN为:cn=zhangym195,cn=organizational users,o=hl328-na999,cn=cordys,cn=defaultInst,o=
3.3.2 CWS项目构建方案
集成平台的各个基础通用组件分别建立独立的workspace主要包括:统一用户管理,附件和报
表,日志模块,工作台其他应用功能在一个workspace中分别建立独立的project。

Is the reversed domain name really required to be used as part of the qualified name?
It is strongly recommended, because this prevents name collisions with content from another software vendor. Product uniqueness within your domain, is at your own responsibility.
In case, you are the one and only consumer of the developed application, you could consider to skip the reversed domain name part of the folder structure and hence from the qualified name. Disadvantage is that you could get name collisions in future.
svn目录结构如下:
i.tags、branches和trunck是SVN标准结构,trunck下面workspaces是工作空间窗
口,bpmservices为本项目工作空间,rest-ws是REST服务开发的项目,还可以按以后规划建立其他项目
ii.以上SVN内容在导出到CWS后,目录结构如下
iii.其他开发人员可以按此格式在CWS中建立项目,使用‘3.2.1节svn服务器’中‘Cordys中CWS创建项目工程时绑定的SVN地址’提供的地址对项目进行检出,然
后再本地开发
iv.
其中:
rest-ws为工作空间中的项目名称,一般一个服务分类独立一个项目
Business Process Model为流程模型(business process models 和 case management models)目录,此目录下面一般以流程级联目录进行命名,此目录不会部署到流程模型的名称路径中。

采用
Set Start Point of Qualified Name,将此目录下级目录作为命名起始位置。

●DB Metadata为数据库元数据目录
●Java目录下面包含Java archives 和 Java sources目录,
Application packages can contain Java Archives (JARs, for short) that include Java classes developed as part of the application, or JARs from external providers (so called third party JARS). In the former case, you need to define a Java Archive Definition;
detailed instructions on this can be found in this webinar. In the latter case, there are two options:
the required JAR is available itself and can therefore be delivered as part of the developed application;
the required JAR is delivered by another application.
In the last case, you must include a file path dependency. Note that in this scenario, the developed application can be deployed without the required Java Archive being available on the production environment.
●Roles为角色目录
●Rules为规则目录
●User Interfaces为用户界面文件目录,包括user interfaces 和 external user
interfaces
●Web content目录为HTM(L)页面文件、Javascript文件、CSS样式表、图片、图标等目录
文件。

这个目录要求定义一个Web Library Definition。

此目录中的文件将部署到Cordys Web Server 目录。

●XML Store content 所有有效的XML结构能够发布到CordysXML Store中。

典型地,它将用
于不会存储在数据库或在文件系统中的属性和设置文件
这个目录要求定义一个 XML Store Definition以使部署文档到Cordys XML Store
All documents having a valid XML structure can be published to the Cordys XML Store.
Typically, it will be used to store properties and settings that will not be stored in a database or on the file system. Not all documents with extension xml need to be published to the Cordys XML Store. For example, message bundles end at xml but needs to be part of some Java archive.
You need to define a XML Store Definition to deploy documents to the Cordys XML
Store. More explanation and detailed instructions you can find at this webinar.
●Web Services 开发的Web 服务目录
●Web WsAppServer Packages 目录为根据DB Metadata生成成的package目录
●XMLSchema Definitions为XMLSchema目录
3.3.3 CWS项目项目开发注意
如果项目按每租户每开发人员模式进行BOP4项目开发的话,提醒各位基于SVN的CWS开发人员,在修改代码前一定要先检出代码,修改后再提交到SVN 如果想将项目保存到自己的服务器Workspace下面使用
3.3.4 备份策略
3.3.5 方法集和命名空间
3.3.5.1 WS命名空间说明
JAVA代码命名定义格式:
http:// {公司域名} / {项目编号} / {模块名}
公司域名:
项目编号:bpm
模块名:见下表
模块名编号对应操作接口描述
流程执行ProcessExecute
1. 发起流程
2.
列举出所有流程执行类的操作
待办处理PendingOperate 1. 任务认领
2. 工作移交
3. 委派
列表出所有统一待办待阅、应
用待办待阅及Cordys平台任
务相关的处理操作
流程定义ProcessDefine 1. 查看流程
2. 获取流程环节
列举出涉及流程定义类的操
作,如获取当前用户下所有流
3. 获取流程执行人
4. 程名称,获取当前流程环节,获取当前环节的后续环节等等。

流程管理ProcessMgmt 1. 获取流程实例
2. 查看流程历史
流程管理相关的所有操作
组织管理OrgMgmt 1. 用户查询
2. 用户同步
涉及与4A相关的组织用户同
步及用户、角色、等组织信息
查询操作,通过封装4A提供
的REST服务接口,开发同步
WS来实现。

应用开户AppRegister 1. 建立租户
2. 建立系统资源(建
立SG、SC、
CLASSPATH)
3. 分配数据库资源
4. 分配用户
5.
涉及应用开户
流程模型BpmModel 1. 车辆(Vehicle)
2. 会议(Meeting)
3. 档案(Archive)
命名示例:
如【流程执行】模块下面的启动流程操作命名空间如下http:// /bpm / ProcessExecute
JAVA包命名方式:
com.cuc.bpm.processexecute
3.3.5.2 流程模型命名空间说明
流程模型NS定义格式:
http:// {公司域名} / {项目编号} / BpmModel/ {APPID}
公司域名:
项目编号:bpm
{APPID}:应用开发时EIP中申请的APPID。

3.3.5.3 JAR包命名规范
1、J AVA包命名
bpm-{模块名}-{版本号}.jar
2、提供给第三方REST接口SDK命名
bpm-{模块名}-interface-{版本号}.jar
3.3.5.4 REST接口URI命名说明
http://{EIP部署服务主机}:{端口}/bpm/rest/{模块名}/{服务操作}/{参数1}/{参数2} 示例:
http://10.0.0.99:8080/bpm/rest/ ProcessExecute
/workflowBackOne/{appId}/{appToken}/{controlUserId}/{processInstanceId}/{track_id}
3.3.6 方法
命名方式为
Get%BUSINESS_ENTITIY%Object (返回0-1个tuple)
Get%BUSINESS_ENTITIY%Objects (返回0-n个tuple)
Get%BUSINESS_ENTITIY%Object/ObjectsBy%PARAM1%[_and_%PARARM2%] (固定参数查询)
Get%BUSINESS_ENTITIY%ObjectsByDF (动态查询)
Get%BUSINESS_ENTITIY%Object/ObjectsBy%PARAM1%[_and_%PARARM2%][_and_DF] (固定参数+DF 查询)
参数较多时,可考虑在object后以功能进行命名。


GetChangeObjectsByDF
GetAnnualPlanObjectsByPlanID_and_PlanType
GetAnnualPlanObjectsFilter
method的命名基本上遵循两点
1.系统默认生成的规则: Object表示返回单个tuple,Objects表示返回多个tuple
2.自定义规则:By后面是条件,DF表示动态查询
这里PARAM之间之所以用下划线连接,是因为数据库字段有时候可能全部大写,无法断词。

3.3.7 JAVA类注释
1.方法注释:
项目中的方法注释按以下模板生成。

生成成后效果,如图所示:
配置方法:在Eclipse中按以下方式打开菜单:
windows -> preferences:
找到Java – Code Template
右侧“Configute generated code and comments”:区中点击“Metods”,然后Edit此模板,将下面内容
/**
* <b>Method Name</b>: ${enclosing_method}
* <br/><b>Description</b>: ${todo}
* @author ${user}
* ${tags} ${return_type}
* @throws
*/
粘贴后,如图示:
保存即可。

生成的模板注释后如下所示:
/**
*
* <b>Method Name</b>: startProcess
* <br/><b>Description</b>: 根据传递的流程特定消息来启动流程并返回流程实例ID * @author yuming
* @param type 类型 'definition'
* @param receiver 流程图名称(全路径)
* @param messages 流程流转消息(XML Node)
* @param source 可选参数
* @return String Instance_Id
* @throws
* IllegalArgumentException 参数错误
* @throws
* SOAPException 执行异常,流程启动失败
*/
2.
3.4 编程公共命名
进行面向对象的设计,考察方法本身是否为类的职责。

3.4.1 类命名
WS-AppServer依据后台数据库表对象或Object自动生成的Class,以系统默认命名为准;其他自定义类命名方式为
名词
名词中各个单词的第一个字母大写
如:
OaObject

动词+名词
动词第一个字母小写,名词中各个单词的第一个字母大写
getOaObject
3.5 Javascript命名
3.5.1 类成员变量命名
命名方式为
_名词[+名词]

_password
_userName
首字母小写,如包含多个名词后面名词首字母大写。

成员变量都应当被封装,不能被外部直接访问。

采用“_”前缀,同时提供getter/setter方法。

3.5.2 普通变量命名
非对象类型变量命名方式为
%TYPE%名词[+名词]

sType
iIndex
giIndex
%TYPE%为变量类型(虽然Javascript没有类型的概念,但是从代码可读性和校验方便性考虑还是应当添加),包括以下取值:
•i: int
•gi: gloable int variable
•s: String
对象类型变量命名方式为
名词[+名词]%OBJECT_TYPE%

employeeNode
orderArray
%OBJECT_TYPE%为对象类型,包括以下取值:
•Node
•Array
•其它
所有无类型前缀的变量都是“对象”,而后缀表示它是哪种“对象”。

有多个名词时采用Camel格式,也即各名词首字母大写。

3.5.3 类成员方法
命名方式为
function [_]动词+名词[+名词](参数列表也即普通变量列表)

function getUser(sCode)
需要考虑是否对外部公开
•公开则无“_”前缀
•不公开则有“_”前缀
实例方法通过prototype定义,静态方法直接定义。


Date.prototype.toCordysString=function()
Date.fromCordysString=function(sDateTime)
3.5.4 普通方法
与类成员方法的唯一区别是不需要考虑外部可见性。

3.6 Java命名
3.6.1 类成员变量与普通变量
命名方式为
名词[+名词]

PassWord
UserName
首字母小写,如包含多个名词后面名词首字母大写。

成员变量都应当被封装,不能被外部直接访问。

采用private修饰符,同时提供getter/setter方法。

3.6.2 类成员方法
命名方式为
%可见性% %返回类型% 动词+名词[+名词](参数列表也即普通变量列表)
动词第一个字母小写,名词中各个单词的第一个字母大写

private String generateReport(int employeeIndex){}
3.6.3 包命名
命名方式为
com.unicom. %MODULE%

com.unicom.bpmsi
注意保持WS-AppServer Repository中的package和java中的一致3.7 数据库命名
3.7.1表和字段命名
对于Oracle,、表名全部大写,根据应用的不同用下划线分隔

OA_***
HR_***
如果表明超长,测应用名称缩写
比如REPAIRREPORT_***缩写为RR_***
3.7.2主键命名
命名方式为
PK_表名

PK_EMPLOYEE
全部大写。

3.7.3外键命名
命名方式为
FK_表名_被引用表名

FK_EMPLOYEE_DETAIL_EMPLOYEE
全部大写。

3.7.4视图命名
命名方式为
VW_表名[_表名]

OA_VW_EMPLOYEE_USER_INFO
全部大写。

3.7.5序列命名
命名方式为
SEQ_表名

OA_SEQ_EMPLOYEE
全部大写。

3.7.6存储过程命名
命名方式为
S_动词_名词

OA_S_UPDATE_EMPLOYEE
全部大写。

3.7.7函数命名
命名方式为
F_动词_名词

OA_F_CALCULATE_USER_NUMBER
全部大写。

3.7.8触发器命名
命名方式为
DT_动词_名词

OA_DT_GENERATE_USER_ID
全部大写。

4技术实现
4.1 业务逻辑实现方案选择
本项目中的业务逻辑可以通过以下几种方式实现:Javascript in XForm, WS-AppServer, BPM, SQL in WS-AppServer Web Service (method), SAP Connector, Scheduler和Store Procedure。

一般的指导原则是:
•考虑企业内部原有和目标业务流程规范性、业务流程操作习惯和项目执行力度
•是否采用BPM进行技术实现取决于是否可以或需要增加业务的可见性
•尽量使用BPM进行较高层次的业务建模,而使用WS-AppServer构建细粒度的功能或事务逻辑•如果性能是业务逻辑的瓶颈,应尽量采用WS-AppServer实现
•尽量简化客户端(Javascript in Xform)的实现代码,而选择后面的几种方式把实现封装在SOAP method中(其实就是统一的后台调用接口)
•尽量少使用Store Procedure,因为它特定数据库的依赖性太强,而且无法实现标准的tuple old/new接口
•无论是不太涉及业务对象、简单轻量级的业务逻辑,比如拼接日期、格式化字符串或者进行数学运算等,还是较为复杂的业务逻辑,比如需要从数据库中获得相关业务对象信息进行比较复杂的组装,应使用WS-AppServer;对于和SAP系统的集成,使用SAP Connector
根据逻辑的复杂性和要实现的目标不同,分情况处理:
1.如果某项功能仅实现单个业务实体的增删改查(包括以一张表为主体,但涉及多表的关联查询),同时该实体的变化又不至于扩散(扩散的例子:删除订单还要同时修改对应计划的状态),那么就可以由SQL in WS-AppServer Method实现。

2.如果某项功能需要复杂的逻辑处理,这些处理可以由系统完成,或者对业务实体的增删改影响到了其他的实体(变化扩散),由WS-AppServer实现。

3.如果某项功能需要多个不同用户的合作才能完成,且某些角色的所要完成的业务工作是多样的,那么可以由BPM实现。

4.如果逻辑取决于用户的交互,还是前端判断比较合理。

(例如根据用户对控件A的选择结果确定控件B显示的内容
5.对于本项目需要较高性能要求的情况,采用详细设计中基于WS-AppServer的复合框架,进行请求封装
4.2 页面
页面实现有以下指导原则:
•页面脚本做结构化处理,考虑调试情况和异常处理,示例如下
var gDebug = false;// 调试标志
var gDebugBPM = false;// 调试BPM标志
var gParam; // 全局传入参数
var gType; // 是否新建报销单全局标识,默认新建
var gOpen=false; // 重入标志
var OPERATION_NEW = 0; // 新建
var OPERATION_DRAFT = 1; // 草稿
var OPERATION_PROCESS = 2; // 流程中
// 表单初始化
function Form_InitDone(eventObject)
{
try
{
// 重入检验
if(gOpen) // 已打开
{
CordysRoot.application.showError("请首先关闭已打开页面!", "系统错误", null, errorHandler);
return;
}
else
{
gOpen = true;
}
initGlobal();
initForm();
}
catch(e)
{
CordysRoot.application.showError("页面初始化发生错误,请重新尝试或联系系统管理员!\n"+e.message, "系统错误", null, errorHandler);
}
}
function errorHandler()
{
closeApplication();
}
// 初始化全局变量
function initGlobal()
{
// 获得传入参数
gParam = application.event.data;
// 流程中
if(isFromBPM())
{
gType = OPERATION_PROCESS;
if(!gDebugBPM) gID = id.getValue();
}
else
{
// 修改已有
if(gParam && gParam.operationType && gParam.operationType == OPERATION_DRAFT) {
gType = OPERATION_DRAFT;
}
// 新建
else
{
gType = OPERATION_NEW;
} }
}
function isFromBPM()
{
if(parent && typeof(mitForm) == "function")
{
return true;
}
if(gDebugBPM) return true;
return false;
}
// 设置表单默认值和可用性
function initForm()
{
initDefault();
hideHiddenFields();
if(XXXModel.soapFaultOccurred)
{
CordysRoot.application.showError("读取XXX信息失败", "系统错误", null, closeApplication);
return;
}
}
// 隐藏所有不可见字段
function hideHiddenFields()
{
grpHidden.hide();
}
// 设置默认值
function initDefault()
{
}
// 点击提交
function tbbCommit_Click(eventObject)
{
commit();
}
// 提交处理
function commit()
{
if(gType == OPERATION_DRAFT || gType == OPERATION_NEW) // 草稿
{
application.confirm("是否提交并启动流程?", false, confirmCommitHandler);
}
else // 流程中
{
application.confirm("是否提交并继续执行流程?", false, confirmCommitHandler); }
}
// 提交处理
function confirmCommitHandler(confirmReturnValue)
{
// 确定
if (confirmReturnValue == 1)
{
var result = validateForm();
if(!result) return;
if(gType == OPERATION_DRAFT || gType == OPERATION_NEW) // 草稿
{
var bStarted = startProcess();
if(!bStarted)
return false;
continueProcess();
}
else // 流程
{
continueProcess();
}
}
else
{
// 否(0)/取消
return;
}
closeApplication();
}
// 表单校验
function validateForm()
{
return true;
}
// 启动流程
function startProcess()
{
XXXModel.reset();
if(XXXModel.soapFaultOccurred)
{
CordysRoot.application.showError("流程启动失败", "系统错误", gbxBasic, closeApplication);
return false;
}
return true;
}
// 继续执行流程
function continueProcess()
{
if (mitForm)
{
mitForm();
CordysRoot.application.notify("已成功提交", "系统信息", null, closeApplication);
}
else
{
CordysRoot.application.notify("已成功提交并启动流程", "系统信息", null, closeApplication);
}
}
// 点击取消
function tbbCancel_Click(eventObject)
{
application.confirm("是否关闭当前页面?", false, closeApplication, true, "系统确认");
}
// 关闭当前页面
function closeApplication(confirmReturnValue)
{
if (confirmReturnValue == 1 || confirmReturnValue == null)
{
// 确定
application.container.close();
}
}
// 对应模型的异常处理
function XXXModel_OnSOAPFault(eventObject)
{
eventObject.showError = false;
}
•对于各页面通用的函数,放置在独立的js文件中并链接到XForm中
•检查XForm中的各个Model,如果不必要应去掉其“automatic”属性以增强性能
•各个XForm特别是非Zoom页面的实现考虑页面重入的问题(如通过菜单多次点击)并进行相应处理,也即在FormInitDone事件中判断当前页面是否已被打开过,如下所示:var gIsOpen = false;
function Form_InitDone(eventObject)
{
if (gIsOpen) // 已打开过,不做任何操作返回,应根据实际情况做相应调整
return;
gIsOpen = true;
……
}
•如果数据库表设计时,需要在前端展现的业务对象相关表中只存储了标识编码信息,而未冗余存储描述信息,则应通过适当的WS-AppServer方法将记录一次取出展现在前端,而不应对描述信息增加Model二次取出,以减少round trip提高性能
•虽然集中化的服务器端校验是实现表单字段有效性校验的理想方式,但是出于性能的考虑,一般情况下有效性校验应当在客户端进行;而对于以下几种情况,可以考虑在服务器端进行校验:
o保存操作:此时一般允许充足的时间进行服务器端校验,同时校验逻辑可能比较复杂
o出于较高安全性的考虑,在服务器端实现相同的校验逻辑
使用FreeFormData或Non-Transactional Model统一封装XForm的输入输出。

4.3 BPM
4.3.1 流程松耦合性
流程设计时应当尽量避免所有流程环节紧密耦合,而应当通过本地消息变量的方式尽量保证流程的松耦合性,以便于未来可能的业务变更,示例如下:
图17流程模型松耦合
可以看到,通过使用流程特定消息(Process Specific Message)MessageOP,虽然流程模型发生了变更,对MessageOP节点内属性EmployeeID赋值进行了调整(红色区域),但在
Notification环节(及其它任何可能环节)中的引用都可以保持不变
(bpm:MessageOP/bpm:EmployeID/text()),这可以有效降低活动间的耦合度。

4.3.2 流程事务性
对于短生命周期(Short Lived Process)的流程,在主流程中将各子流程组为同一事务,即可保证各子流程内部的各个自动环节在同一事务中,如下图所示:
图18流程事务性
注意:在一个Transaction Context中使用针对不同数据源的多个WS-AppServer类型方法,但是其中只能有一个方法(也即针对一个数据源的方法)可以具有事务性,不支持分布式数据库事务或两阶段提交。

4.3.3 流程建模复用组件配置及使用规范
请参见《中国联通云门户-流程服务项目-基础流程建模说明 V1.0.doc》文档中的相关内容。

4.4 消息映射
4.4.1 消息结构
应当保持消息结构的清晰,将不同类型的消息组织在不同的节点层次下,比如业务对象的消息应当与流程控制信息分开。

如:
Process Specific Messages
<InputMessage>
<BusinessData>
<ShopID/>
</BusinessData>
<ControlData>
<InstanceID/>
<ParentInstanceID/>
<RootID/>
<DefaultDuration/>
<DecisionAttribute/>
<NextActivityUserList/>
</ControlData>
<SAP>
<BatchNumber/>
</SAP>
</InputMessage>
4.4.2 消息删除
在流程中各个活动环节对应方法的Business Object(也即顶层元素)应尽量相互区分,如果使用Business Object同名的多个SOAP method作为流程环节,特别是Update方法时,必须要删除前一环节的消息映射,否则会将前一环节的tuple节点复制到后一环节。

其次,如果在流程中定义了某些XML结构,当后续环节不再使用该结构时,应当及时使用上面的方式删除该结构以节约内存。

4.4.3 本地变量
对于每个流程都可能用到的本地变量,应当统一定义在本地消息中并按照以下方式使用:
•在Starter环节的“Message map After”/ Message Map中对本地变量进行定义和初始化,BOP-4截图如下
图19流程本地变量定义
•使用某个方法作为活动环节获得后台数据等结果后,在该环节的“Message map after” / “Post Assignments”中将后续环节需要使用的结果赋值给本地变量
•对于需要使用本地变量作为输入参数的活动环节,按照活动对应方法的WSDL中输入参数的顺序,将本地变量赋值给输入参数
•如果流程中具有循环结构并需要使用循环计数器,应当在Loop结构的“Message map before”/ “Pre Assignments”中进行初始化,并在Loop结构内第一个活动环节的
“Message map before” / “Pre Assignments”中进行累加
4.4.4 子流程
在BOP-4 FP1中,在子流程内定义好输入输出消息,然后将子流程拖拽到主流程内,将自动生成Input Message,如下图
图20子流程消息定义
4.4.5 并行处理
4.4.
5.1 普通SOAP方法
对于普通的SOAP方法,当流程活动的执行需要较长时间时,而又需要并行执行不同的流程环节,应采用适当的方式进行流程建模,如下图所示。

相关文档
最新文档