activity初探(基于kft-activiti-demo的一个小例子)

最近老板心血来潮要搞基于activiti的工作流,没办法,只能现学,看了两周,一个小总结。 前提准备:
- eclipse安装acidity-designer插件
- 了解bpmn2.0基本知识
- 下载activiti,跑一跑其中demo
- 下载咖啡兔中的kft-activiti-demo


基于kft-activiti-demo 中的leave-formkey改造,主要是为了学习bpmn流程图表制作,发布流程,对应的api,相关数据库表,顺便复习下springmvc。

  1. Bpmn流程图表制作

前提熟悉基本的bpmn2.0规范,熟悉eclipse插件acitviti-desinger使用。画出流程如下:
activity初探(基于kft-activiti-demo的一个小例子)

对应图表和每个控件属性如下:(task控件中的general选项主要定义id和name,可随意填写,故没有展示)

图表:
activity初探(基于kft-activiti-demo的一个小例子)
注意id取值,这里的id就是在启动流程时根据该id获取实例,如下:

repositoryService.createProcessDefinitionQuery().processDefinitionKey("leave-formkey")。

此id可以重复使用。因为后面要将该实例部署到kft-activiti-demo的外置表单流程中,而kft-activiti-demo中外置表单流程里一些调用sql是写死的,所以为了方便,这里直接用该id就行

Start:
activity初探(基于kft-activiti-demo的一个小例子)

注意initiator:
其作用设置一个变量名称,可以是任意的字符串,变量applyUserId保存申请用户的ID
在需要设置申请用户才能办理的任务上设置activiti:initiator
对应用户手册上两个关键函数

identityService.setAuthenticatedUserId("kafeitu")//设置当前的用户ID,而且这行代码需和activiti:initiator配合使用
runtimeService.startProcessInstanceByKey("leave")//启动流程,判断有没有activiti:initiator属性,如果有把属性activiti:initiator的值作为一个变量添加到流程实例中

班主任审批:
activity初探(基于kft-activiti-demo的一个小例子)

书记审批:
activity初探(基于kft-activiti-demo的一个小例子)

上面两个task中都定义了一个外置表单,实际上就是一个html文件,在流程流转到当前task时引擎会自动加载对应的外置表单。因为业务逻辑一样,所以这里直接copy了kft-activiti-demo 中的leave-formkey activiti diagram中的申请、审核表单。

两个task分别定义了一个candidate group name,实际上就是角色身份,就是说只要用户身份中包含teacher,schoolmaster就能签收办理该task。对应初始化sql:

insert into ACT_ID_GROUP values ('teacher', 1, '老师', 'assignment');
insert into ACT_ID_GROUP values ('schoolmaster', 1, '书记', 'assignment');

此外,还需要给用户分配group,为了方便,这里将当前用户公用一个身份,对应sql:

insert into ACT_ID_MEMBERSHIP values ('leaderuser', 'teacher');
insert into ACT_ID_MEMBERSHIP values ('leaderuser', 'schoolmaster');

上面的ACT_ID_GROUP和ACT_ID_MEMBERSHIP都是activiti自带的表,分别表示group定义和用户所属group的关系。这个在后面的数据库表中将详细介绍。

至于怎么执行sql,这里就不详细说了,kft-activiti-demo中sql目录下有h2,mysql,oracle对应的数据初始化脚本,可以把上面的数据插入其中,在首次初始化时执行,也可通过命令行或者其他工具一条条插入。

顺序流:
这里只有两条标准顺序流
同意:
activity初探(基于kft-activiti-demo的一个小例子)

注意其中的deptLeaderPass,这是在上一个班主任审批外置form中定义的一个是否同意的变量。

不同意:
activity初探(基于kft-activiti-demo的一个小例子)

End:
缺省值
activity初探(基于kft-activiti-demo的一个小例子)

最后项目生成文件:
activity初探(基于kft-activiti-demo的一个小例子)

2. 打包&部署

打包:
将上面5个文件,即bpmn文件和对应的png及相关form打包成zip,直接用eclipse自带的打包:
Export->archive file->选择保存路径->(注意option中选择save in zip format)
部署:项目启动后:
activity初探(基于kft-activiti-demo的一个小例子)

右上角点击部署流程:
activity初探(基于kft-activiti-demo的一个小例子)
选中打包的zip,点击submit

3.后台跟踪及相关数据库表

为了方便了解后台的流程,这里将每一步调用的文件及方法列出,并列出涉及的表:

3. 1.部署

/
*
部署函数
*/
me.kafeitu.demo.activiti.web.workflow.ActivitiController.java
public String deploy()
其中两个重要方法:
Deployment deployment = repositoryService.createDeployment().addZipInputStream(zip).deploy();
 List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).list();

其实就是部署和列取部署的流程定义,具体函数定义可参见,下载activiti安装包中说明:
activiti-5.18.0/activiti-5.18.0/docs/javadocs/index.html
涉及表:
ACT_RE_PROCDEF(流程定义表)
ACT_RE_DEPLOYMENT(部署信息表)

3. 2.列出流程(外置表单类型)
activity初探(基于kft-activiti-demo的一个小例子)

/*
列出所有外置表单
*/
Me.kafeitu.demo.activiti.web.form.formkey.FormKeyController.java //方法所在路径
public ModelAndView processDefinitionList()
关键方法:
 ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery().processDefinitionKey("leave-formkey").active().orderByDeploymentId().desc();

涉及表:
ACT_RE_PROCDEF(流程定义表)

3. 3.启动具体流程


/*
启动实例,读取启动环节的外置表单
*/
Me.kafeitu.demo.activiti.web.form.formkey.FormKeyController.java
public Object findStartForm()
关键函数:
Object startForm = formService.getRenderedStartForm(processDefinitionId);
//根据实例id获取表单

此时弹出渲染的表单:
activity初探(基于kft-activiti-demo的一个小例子)

填写内容后,点击“启动流程”

/**
     * 读取启动流程的表单字段
     */
Me.kafeitu.demo.activiti.web.form.formkey.FormKeyController.java
 public String submitStartFormAndStartProcessInstance()

相关表:
ACT_RU_EXECUTION(执行中流程执行)
ACT_RU_VARIABLE(实时变量)
ACT_HI_VARINST(历史变量信息)
ACT_RU_IDENTITYLINK(身份联系)
ACT_HI_IDENTITYLINK(历史身份信息)
ACT_HI_PROCINST(历史流程实例信息)核心表
ACT_HI_ACTINST(活动实例信息)
ACT_HI_DETAIL(历史详细信息)

以上是该步骤涉及的重要表,还有一些表未列出,可以在程序执行的debug信息中了解到更为详尽的细节,包括sql语句,后面为了节省页面时间,也不再将列出想关表。每张表结构及信息可自行百度之。

3. 4.查看当前任务

   /**
     * task列表
     *
     * @param model
     * @return
     */
Me.kafeitu.demo.activiti.web.form.formkey.FormKeyController.java
public ModelAndView taskList()
关键函数:
根据定义的签收人或者候选group中获取满足当前用户的当前任务
 NativeTaskQuery query = taskService.createNativeTaskQuery().sql(sql)
                .parameter("processDefinitionKey", "leave-formkey").parameter("suspensionState", SuspensionState.ACTIVE.getStateCode())
                .parameter("userId", user.getId());

这里可以在函数中看看sql的具体写法。

3. 5.任务签收

 /**
     * 签收任务
     */
Me.kafeitu.demo.activiti.web.form.formkey.FormKeyController.java
public String claim()
关键函数:
taskService.claim(taskId, userId);//用户签收任务,言简意赅

3. 6.任务办理

  /**
     * 读取Task的表单
     */
Me.kafeitu.demo.activiti.web.form.formkey.FormKeyController.java
public Object findTaskForm()
关键函数:
Object renderedTaskForm = formService.getRenderedTaskForm(taskId);//读取当前task的外置表单

此时弹出渲染的表单:

activity初探(基于kft-activiti-demo的一个小例子)
执行完毕后:
activity初探(基于kft-activiti-demo的一个小例子)
activity初探(基于kft-activiti-demo的一个小例子)

当前任务变成了书记审批,因为当前用户兼顾“老师”,“书记”身份。
此后的签收办理环节同前面“班主任审核”环节类似。

3. 7.结束环节

/**
     * 办理任务,提交task的并保存form
     */
Me.kafeitu.demo.activiti.web.form.formkey.FormKeyController.java
public String completeTask()
关键函数:
identityService.setAuthenticatedUserId(user.getId());//最后环节将任务交给提交任务的用户
formService.submitTaskFormData(taskId, formProperties);
上一篇:实现类似美团的下拉分级式菜单


下一篇:NSArray,NSMutableArray的KVO操作