activiti 与业务结合流程怎么和业务结合

Activiti的流程如何与外部业务进行数据交互
我的图书馆
Activiti的流程如何与外部业务进行数据交互
如何通过流程审批与外部表单实现对接
在流程的审批过程中,我们有很多业务是需要进行流程的审批的,但实际上这些业务在大部分处理上跟流程上是无关的,他们只是有部分业务的数据需要参与审批的动作而已,如:
销 售采购合同,制订采购合同是需要走审批流程,一旦审批完成后,这个采购合同后续的执行是则是由采购合同模块本身的处理来完成,后续跟审批操作没有多太关 系。在系统设计上,我们需要开发一个单独的模块进行采购合同的处理,但我们又希望他们有些信息是需要参与审批,并且在审批完成后,能完成对采购合同进行修 改。
为了更形象说明这个整合开发原理,我们举一个简单的例子:如供应商入库,前期的供应商信息我们是需要审批的,一旦审批通过后,我们后续 的其他业务模块就可以使用供应商的信息。为此我们基于activiti进行了了灵活的处理,本文先介绍其中一方便快捷的方法,本文的前提就是供应商管理模块已经存在。我们 需要在供应商表中加一个字段 act_inst_id_,用于存储Activiti的流程实例Id,用于后续追踪供应商的审批过程。
根据供应商的信息制作在线表单,如:
编写供应商的数据处理接口
1.通过审批表单的数据来创建供应商
实现流程在启动时创建时调用供应商的创建接口,实现接口ProcessStartAfterHandler即可。
2.通过审批表单更新供应商的数据
实现TaskAfterHandler接口即可
3.通过审批表单的审批触发供应商数据的审批状态
实现ProcessEndHandler即可。
以下是我们把以上三个实现均放在CrmProviderManager中来实现,代码如下所示:
Java代码 &@Service&&public&class&CrmProviderManager&extends&BaseManager&CrmProvider&&implements&&ProcessStartAfterHandler,TaskAfterHandler,ProcessEndHandler{&&&&&&&&&&/**&&&*&通过Json数据创建供应商&&&*&@param&json&&&*&@param&bpmInstId&&&*&@return&&&*/&&public&CrmProvider&createFromJson(String&json,String&actInstId){&&&&CrmProvider&crmProvider=JSON.parseObject(json,&CrmProvider.class);&&&//关联流程实例ID&&&crmProvider.setActInstId(actInstId);&&&&crmProviderDao.create(crmProvider);&&&return&crmP&&}&&/**&&&*&通过Json更新供应商的值&&&*&@param&json&&&*&@param&busKey&&&*/&&public&void&updateFromJson(String&json,String&busKey){&&&&CrmProvider&orgProvider=get(busKey);&&&if(orgProvider==null)&&&&&CrmProvider&newProvider=JSON.parseObject(json,CrmProvider.class);&&&try&{&&&&&BeanUtil.copyNotNullProperties(orgProvider,&newProvider);&&&}&catch&(Exception&e)&{&&&&&e.printStackTrace();&&&}&&&&crmProviderDao.update(orgProvider);&&}&&&&/**&&&*&1.通过流程实例创建完成后通过表单的数据创建供应商信息&&&*/&&@Override&&public&String&processStartAfterHandle(String&json,&String&actInstId)&{&&&&CrmProvider&crmProvider=createFromJson(json,actInstId);&&&&crmProvider.setStatus(MStatus.INIT.name());&&//返回业务主键给流程实例&&&return&crmProvider.getProId();&&}&&&&&&/**&&&*&2.任务审批完成时调用,用于更新供应商的数据&&&*/&&@Override&&public&void&taskAfterHandle(IExecutionCmd&cmd,&String&nodeId,&String&busKey)&{&&&&updateFromJson(cmd.getJsonData(),busKey);&&}&&/**&&&*&3.流程成功审批完成时,对供应商的审批状态进行更新&&&*/&&@Override&&public&void&endHandle(BpmInst&bpmInst)&{&&&&String&busKey=bpmInst.getBusKey();&&&&CrmProvider&crmProvider=crmProviderDao.get(busKey);&&&if(crmProvider!=null){&&&&&crmProvider.setStatus(MStatus.ENABLED.name());&&&&&crmProviderDao.update(crmProvider);&&&}&&}&&&&}&&
配置流程定义及流程解决方案,实现以下几点,特别是节点上的数据配置处理
关联审批表单
关联审批人员
在节点上配置调用供应商的数据处理接口
配置完成后,流程启动在审批过程中,就会调用对应的供应商接口实现数据的同步处理了。
若我们需要在供应商管理模块中,点添加的时候,就可以实现启动供应商审批流程,这时我们需要做一点配置。在全局的模块流程绑定模块中,配置供应商模块中的流程,同时在供应商添加管理模块中,调用这个配置处理。如下:
在供应商管理模块中增加以下调用,用来替换原来的添加处理即可,同时增加查看流程实例的信息调用:
&& //处理添加 &&&&&&&function _add(){ &&&&&&&&//检查是否存在流程配置,若没有,则启用本地的默认配置 &&&&&&&&_ModuleFlowWin({&&&&&&&&&&title:'供应商入库申请',&&&&&&&&&&moduleKey:'CRM_PROVIDER', &&&&&&&&&//failCall:add, &&&&&&&&&success:function(){&&&&&&&&&&&grid.load();
&&&&&&&&&} &&&&&&&&}); &&&&&&&}//查看流程审批实例信息function checkDetail(actInstId){&&&&&&&&&_OpenWindow({&&&&&&&&&&title:'审批明细',&&&&&&&&&&width:800,&&&&&&&&&&height:480,&&&&&&&&&&url:__rootPath+'/bpm/core/bpmInst/get.do?actInstId='+actInstId &&&&&&&&}); &&&&&&&}
这时我们在这个模块中添加供应商时,即可以显示供应商的填写流程申请入口。如下所示:
同时在供应商管理中可以看到流程审批的相关信息
最终的使用效果如下所示:
TA的最新馆藏
喜欢该文的人也喜欢activiti学习资料(5)
场景模拟(请假流程):
员工申请请假部门领导审批人事审批员工销假
本文用次例介绍在工作流中出现的几个对象及其之间的关系,以及在Activiti中各个对象是如何关联的。
在线演示实例:
在开始之前先看看下图,对整个对象结构有个了解,再结合下面的详细介绍理解。
图1 Activiti中几个对象之间的关系
1.ProcessInstance
员工开始申请请假流程,通过runtimeService.startProcessInstance()方法启动,引擎会创建一个流程实例(ProcessInstance)。
简单来说流程实例就是根据一次(一条)业务数据用流程驱动的入口,两者之间是一对一的关系。
擎会创建一条数据到ACT_RU_EXECUTION表,同时也会根据history的级别决定是否查询相同的历史数据到ACT_HI_PROCINST表。
启动完流程之后业务和流程已经建立了关联关系,第一步结束。
启动流程和业务关联区别:
对于自定义表单来说启动的时候会传入businessKey作为业务和流程的关联属性对于动态表单来说不需要使用businessKey关联,因为所有的数据都保存在引擎的表中对于外部表单来说businessKey是可选的,但是一般不会为空,和自定义表单类似
关于各种表单之间的区别请参考:
2.Execution
初学者最搞不懂的就是ProcessInstance与Execution之间的关系,要分两种情况说明。
Execution的含义就是一个流程实例(ProcessInstance)具体要执行的过程对象。
不过在说明之前先声明两者的对象映射关系:
ProcessInstance(1)---&Execution(N),其中N &= 1。
值相等的情况:
除了在流程中启动的子流程之外,流程启动之后在表ACT_RU_EXECUTION中的字段ID_和PROC_INST_ID_字段值是相同的。
图2 ID_和PROC_INST_ID_相等
值不相等的情况:
不相等的情况目前只会出现在子流程中(包含:嵌套、引入),例如一个购物流程中除了下单、出库节点之外可能还有一个付款子流程,在实际企业应用中付款流程通常是作为公用的,所以使用子流程作为主流程(购物流程)的一部分。
当任务到达子流程时引擎会自动创建一个付款流程,但是这个流程有一个特殊的地方,在数据库可以直观体现,如下图。
图3 ID_和PROC_INST_ID_不相等
上图中有两条数据,第二条数据(嵌入的子流程)的PARENT_ID_等于第一条数据的ID_和PROC_INST_ID_,并且两条数据的PROC_INST_ID_相同。
上图还有一点特殊的地方,字段IS_ACTIVE_的值一个是0一个是1,说明正在执行子流程主流程挂起。
刚刚说了ProcessInstance是和业务一对一关联的,和业务数据最亲密;Task是和用户最亲密的(UserTask),用户每天的待办事项就是一个个的Task对象。
从图1中看得出Execution和Task是一对多关系,Task可以是任何类型的Task实现,可以是用户任务(UserTask)、Java服务(ServiceTask)等,在实际流程运行中只不过面向对象不同,用户任务需要有人完成(complete),Java服务需要有系统自动执行(execution)。
图4 表ACT_RU_TASK
Task是在流程定义中看到的最大单位,每当一个task完成的(complete)时候会引擎把当前的任务移动到历史中,然后插入下一个任务插入到ACT_RU_TASK中。
从图4中可以看出
结合请假流程来说就是让用户点击“完成”按钮提交当前任务是的动作,引擎自动根据任务的顺序流或者排他分支判断走向。
4.Activity
Activity——活动。
图5 表ACT_HI_ACTINST
Activity包含了流程中所有的活动数据,例如开始事件(图5中的第1条)、各种分支(排他、并行等,图5中的第2条数据)、以及刚刚提到的Task执行记录(如图5中的第3、4条数据)。
有些人认为Activity和Task是多对一关系,其实不是,从上图中可以看出来根本没有Task相关的字段。
结合请假流程来说如Task中提到的当完成流程的时候所有下一步要执行的任务(包括各种分支)都会创建一个Activity记录到数据库,例如领导审核节点点击“同意”按钮就会流转到人事审批节点,如果“驳回”那就流转到调整请假内容节点,每一次操作的task背后实际记录更详细的活动。
知不知己,百战不殆——作为开发人员最好能知道当你做一个操作的时候引擎会怎么操作数据库。
此文就是给大家一个图形的对象结构,在脑海中有一个印象,读者结合自己的业务流程从头到尾每步跟踪引擎操作的数据库以便更好的理解,关于activiit打印sql日志请参考:中的7.开启Logger。
写的比较粗糙,有异议的地方希望一起讨论。
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:125384次
积分:1695
积分:1695
排名:千里之外
转载:205篇
(1)(4)(1)(6)(3)(3)(1)(11)(1)(6)(5)(4)(1)(4)(13)(9)(6)(4)(3)(3)(1)(2)(2)(2)(5)(4)(11)(1)(6)(2)(4)(3)(2)(3)(24)(24)(9)(1)(10)(2)(1)(1)工作流从流程定义到创建一个流程实例完成执行步骤
使用activi-designer创建一个流程定义(.bpmn结尾的文件)
将定义好的流程定义和生成的png图片通过RepositoryService(前面章节说过主要是用来处理流程定义的service)的api上传到数据库
通过RuntimeService(这个service主要是处理当前正在运行的流程实例的)启动一个流程实例
这个时候通过TaskService(主要处理当前运行的任务,一个流程实例下有多个任务)获取到上面的实例所对应的当前人任务
结束上面的任务task,流程实例会走向下一个task任务
重复4,5,完成一个流程实例的启动到结束
  上面就是一个最简单从上往下执行的流程的执行步骤,本章节都是以代码做示例,代码不多,但是都执行一遍,你会对整个activiti的流程有个大概的了解
  1,首先第一步要做的就是通过eclipse插件activiti-designer绘制一张最简单的流程图出来(在这里我们只用到了startEvent,endEvent,UserTask三个组件所以是比较简单的)
  绘制的流程图如下
  当我们点击创建采购单的时候,为这个节点定义一个id和名称(下面几个节点也是同样的道理)
  -------------------------------------------------------------------------------------------------------------------
  点击左侧的mainConfig在Assingee输入一个名字,设置该流程这个步骤的处理人(当然在实际程序中会采用另外的动态获取的方式,这样只是方便理解一个整体过程)
  接下来同样的道理依次为每个节点设置处理人
  -------------------------------------------------------------------------------------------------------------------
  最后点击空白处,设置整个流程的id和名称
&  到这里点击保存后,会在相同的目录下生成purchasingflow.png,到这里简单的流程就绘制完成了
  2,利用activiti的api将上面定义好的工作流bpmn文件和png文件上传到activiti的数据库
* 获取流程引擎对象,下面的方法会默认查找classpath目录下的名称为activi.cfg.xml
* 里面bean的id为processEngineConfiguration的ProcessEngineConfiguration引擎配置对象来获取ProcessEngine对象
private ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
//部署一个流程
public void deployProcessDefinition(){
<span style="color: #
//根据引擎获取资源service
<span style="color: #
RepositoryService repositoryService =
engine.getRepositoryService();
<span style="color: #
//部署bpmn文件
<span style="color: #
String bpmnName="purchasingflow.bpmn";
<span style="color: #
InputStream bpmnIn = this.getClass().getClassLoader().getResourceAsStream("diagram/purchasingflow.bpmn");
<span style="color: #
//部署bpmn生成的图片
<span style="color: #
String pngName="purchasingflow.png";
<span style="color: #
InputStream pngIn = this.getClass().getClassLoader().getResourceAsStream("diagram/purchasingflow.png");
<span style="color: #
//添加这两个文件进行部署
<span style="color: #
Deployment deployment = repositoryService.createDeployment()
<span style="color: #
.addInputStream(bpmnName, bpmnIn)
<span style="color: #
.addInputStream(pngName, pngIn)
<span style="color: #
.deploy();
<span style="color: #
<span style="color: #
System.out.println("部署id:"+deployment.getId());
<span style="color: #
System.out.println("部署的name:"+deployment.getDeploymentTime());
<span style="color: #
<span style="color: #
  上面的简单的api就将采购流程的流程定义部署到我们的activiti的数据库,打开数据库act_re_procdef可以查询到我们刚才上传的流程定义
  3,在启动一个流程实例之前我们再重复上传上面的流程定义,接着我们根据流程定义的id(purchasingflow)来查询这个流程定义看看会发生什么情况 
1 //查询流程定义
public void queryProcessDefinition(){
RepositoryService repositoryService =
engine.getRepositoryService();
//创建流程定义查询对象
ProcessDefinitionQuery definitionQuery = repositoryService.createProcessDefinitionQuery();
String processDefinitionKey = "purchasingflow";
<span style="color: #
//设置流程定义的key的查询条件
<span style="color: #
definitionQuery.processDefinitionKey(processDefinitionKey);
<span style="color: #
//查询所有的流程定义
<span style="color: #
List&ProcessDefinition& processDefinitionList = definitionQuery.list();
<span style="color: #
for(ProcessDefinition definition:processDefinitionList){
<span style="color: #
System.out.println("-------------------------");
<span style="color: #
System.out.println("流程定义id:"+definition.getId());
<span style="color: #
System.out.println("流程资源名:"+definition.getResourceName());
<span style="color: #
System.out.println("流程部署id:"+definition.getDeploymentId());
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: #
  上面的结果输出了三条流程定义,并且部署的id不同和流程定义的id都不相同,带着这个疑问,我们在下面启动一个流程实例并详细讲解下
  4,启动一个流程实例
1 //启动一个流程实例
public void startProcessInstance(){
RuntimeService runtimeService = engine.getRuntimeService();
String processDefinitionKey = "purchasingflow";
//根据流程定义的key启动一个流程实例
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey);
<span style="color: #
System.out.println("流程实例id:"+processInstance.getId());
<span style="color: #
System.out.println("流程定义id:"+processInstance.getProcessDefinitionId());
<span style="color: #
<span style="color: #
<span style="color: #
  我们发现上面打印的流程定义的id是我们最后一次上传的流程定义,所以我们得出结论,多次上传相同id的流程定义,根据流程定义启动流程实例,会取版本最新的流程定义
   5,查询当前处理人的任务,我们之前在流程定义的时候写死第一个节点(也就是创建采购单这一步的处理人是zhangsan)
1 //查询当前用户的代办任务
public void queryProcessInstance(){
//查询任务使用的service
TaskService taskService = engine.getTaskService();
//获取任务查询对象
TaskQuery taskQuery = taskService.createTaskQuery();
taskQuery.taskAssignee("zhangsan");
<span style="color: #
//查询该条件下的所有的任务
<span style="color: #
List&Task& tasks =taskQuery.list();
<span style="color: #
for(Task task:tasks){
<span style="color: #
System.out.println("当前任务id:"+task.getId());
<span style="color: #
System.out.println("当前任务所属流程定义id:"+task.getProcessDefinitionId());
<span style="color: #
System.out.println("当前任务的key:"+task.getTaskDefinitionKey());
<span style="color: #
<span style="color: #
<span style="color: #
  我们通过zhangsan查询到当前任务的id和所属流程定义id,大家会发现如果填写的不是zhangsan而是别的就会查询不到,因为我们指定的任务处理人是zhangsan
  6,处理一个任务,到这里我们的zhangsan获取到这个任务后,需要处理完它
1 //完成一个流程
public void completeProcessInstance(){
//任务的id,后期整合后会通过当前登录人身份查询到该用户的任务,然后获取到该id
String taskId="402";
TaskService taskService = engine.getTaskService();
//根据任务id完成该任务
plete(taskId);
<span style="color: #
<span style="color: #
  7,我们在通过lisi,也就是下一节点的处理人查询当前任务会发现查询到了一个任务,然后重复5,6,直到任务结束
&原文链接:
阅读排行榜关于工作流中业务和流程及表单的两个初学者问题 - ITeye问答
我是activiti初学者,询问工作流中业务和流程及表单的两个初学者问题,
其实这个和具体的引擎关系不大了。
1 如何根据流程实例找到对应的业务表?
&&& 多个流程的话,如果统一的待办,已办入口,要通过流程实例ID去找具体是哪个业务实体表吧?
&& 比如请假,报销两个流程,在系统中要有唯一的一个”待办,已办“入口,
用户点待办,看到的只是待办的流程名称,这个我已经实现了,但用户需要先看到待办的流程,然后点进去,再看这个到底是什么流程,是请假呢,还是报销?
这个需要通过流程实例id去找业务表。
&& 我的做法是在每个业务实体表,比如请假表,加了一个流程实例id的字段,
在流程启动的时候,写入这个ID,这个大家都应该知道。
&&& 而为了适应在多个流程(多个业务表了)中,通过流程实例ID找到
业务表,我再增加了一个表:
&&&
&& 流程定义&&&&&& 对应业务表名称&&&&&&&&&&&&& 业务表主键名称
&& 请假流程定义id&&& qjdtable(数据库中的物理表名)&&&& qjdId
& 我的想法是:假如要看某个待办流程的具体情况,可以通过
&& 1) 流程实例id得出流程定义id
&& 2) 在这个表中,根据流程定义id,知道要到qjdtable这个业务表中,通过qjdId去找对应的实体记录。
&&& 不知道我的这个方法是否可行?
2) 我设计了一个统一的流程审批意见总表:
id& 业务实体表& 业务表主键&& 流程实例id& 审批意见子表名&&
1&& qjdtable&&&& qjid&&&&&&&&&&&& 1001&&&&&&&& qingjiaapprov&&&&
2&& baoxiaotable&&&&&& baoxiaoid&&&&& 1002&&&&&& baoxiaoapprov
&& 就是说,比如用户申请提交了一个请假单,同时要在这个主表中保留一个记录(唯一的),并且设定审批意见子表的表名(有多少个审批流程,就有多少个审批意见子表)
&& 好了,假设现在到部门经理审批这个请假单了,那么在 qingjiaapprov 这个表中,记录如下
&
& 自动递增id&&& 审批意见主表id& 审批人& 审批时间 审批意见& 流程实例id
&& 12&&&&&&&&&&&&&& 1&&&&&&&&&& 部门经理..............&&&&&&& 1001
&& 13&&&&&&&&&&&&&& 1&&&&&&&&&&& 总经理&&&&&&&&&&&&&&&&&&&&&& 1001
&& 14&&&&&&&&&&&&&& 2&&&&&&&&&& 部门经理&&&&&&&&&&&&&&&&&&&&& 1002
这样的设计,不知道大家觉得如何?有无什么问题?
3) 之所以要分开审批意见主表和审批意见子表,是因为有的时候有的流程中,某些节点,审批者不单是”同意,不同意,审批意见“,有的时候可能要填写复杂的业务表单!但这些业务表单的字段,如何保存好呢?所以我才在每个流程的业务审批子表中,设计不同的这些备用的字段去保存!当然,
这个方法我觉得也麻烦,表单一改,数据库字段要改,不知道大家有什么好的办法?
&&
用K-V形式的String去存审批意见,不用子表
已解决问题
未解决问题该项目主页:
本分类【】其它开源项目
&&相关的文档 ->
&Activiti源码分析?java工作流Activiti源码架构Activiti是业界很流行的java工作流引擎,Activiti从架构角度看是比较优秀的,是很面向对象的。Activiti的基础编程框架Activiti基于Spring,ibatis等开源中间件作为软件平台,在此之上构建了非常清晰的开...&数据库表的命名Acitiviti数据库中表的命名都是以ACT_开头的。第二部分是一个两个字符用例表的标识。此用例大体与服务API是匹配的。 &数据库表的命名Acitiviti数据库中表的命名都是以ACT_开头的。第二部分是一个两个字符用例表的标识。此用例大体与服务API是匹配的。 &优秀的轻量级BPMN2.0规范流程引擎——Activiti,由jBPM创始人——Tom Baeyens发起。Activiti是一个针对企业用户、开发人员、系统管理员轻量级工作流业务管理平台。其核心是使用Java开发的快速、稳定BPMN 2.0流程引擎。Activiti 是在 Apache V2 许可...&我们都知道Alfresco 4.0以后采用了Activiti BPMN2.0 引擎(关于Activiti, 是一个open source 项目。 Alfresco从jBPM公司挖出了jBPM的创建人和若干核心人员,意欲创建一个基于Apache License的,并且遵循BPMN 2.0工作流标准的开...
&&相关的经验 ->
ActivitiDesigner 是开源工作流 Activiti 的设计器。
Activiti 作为一个遵从 Apache 许可的工作流和业务流程管理开源平台,其核心是基于 Java 的超快速、超稳定的 BPMN 2.0 流程引擎,强调流程服务的可嵌入性和可扩展性,同时更加强调面向业务... ...Activiti是一个业务流程管理(BPM)和工作流系统,适用于开发人员和系统管理员。其核心是超快速,稳定的BPMN2流程引擎。它易于与 Spring集成使用。
官方网站:http://www./lib/view/home/5 ...自jBPM创始人Tom离开之后,jBPM和Activiti就开始大相径庭,jBPM被迫使用新的LGPL协议,而Activiti则使用一种更为宽松的Apache License 2.0协议。不管使用jBPM还是Activiti,两者都遵循BPMN 2.0规范,都可满足项目的一般需求,相比于jBPM,A... ...Activiti 5 下载、安装和运行。快速体验 Activiti 这个开源的 Java 工作流引擎。 下载和安装
activiti下载:
本例子版本:activiti-5.16.4.zip
http://www.activiti.org/download.html
JDK 下载 JDK 6... ...一、 什么是工作流
以请假为例,现在大多数公司的请假流程是这样的
员工打电话(或网聊)向上级提出请假申请——上级口头同意——上级将请假记录下来——月底将请假记录上交公司——公司将请假录入电脑
采用工作流技术的公司的请假流程是这样的
员工使用账户登录系统——点击请假——上级登录系统点击... ...
&&相关资讯 ->
&&相关代码 ->}

我要回帖

更多关于 activiti工作流业务表 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信