Activiti界面元素的使用总结
一、图形设计中元素的使用
1、SequenceFlow:连接线,可以连接两个任务,来管理流程实例的流向
-----General
-----id:流程的id,用与程序内部识别
-----name流程的名字,用于用户显示识别
-----Main config
-----Label width:组件的大小,自动
-----Condition:执行该流程的条件,可以通过#{}或${}结合流程变量来 实现
-----Listeners:通过类来控制流程的执行,该来要实现TaskListener接 口,并重写notify()方法,把要传入的参数传进去。
2、UserTask:个人任务
----General:当前任务
----id:用于程序内部标示当前任务
-----name:任务名称:用于在视图上显示当前任务描述
----Main config
----Assignee:指定单个办理人(有三种方法)
方法一:直接指定,输入办理人即可
方法二:通过流程变量指定办理人(使用#{}或${}获取流程实例启动 时,通过
.startProcessInstanceByKey(processDefinitionKey,variables)
流程变量传入的值)
方法三:通过类来指定办理人(在该属性下不加任何指定,在Listeners 下指定相关的类,与连接线中的listeners相似)
delegateTask.setAssignee("指定办理人"
----Candidate user(comma separated):指定组任务(三种方式)
方法一:直接指定,如:小a,小b,小c,小d
可以在程序中通过
taskService.addCandidateUser("taskId","userId")添加组成员
.deleteCandidateUser("taskId","userId")删除组成员
.claim("taskId","userId");拾取任务,将组任务分配 给个人任务
.claim("taskId",null);将个人任务退回到组任务(之 前必须是组任务)
方法二:通过流程变量分配(同个人任务分配一样)
如:variables.put("userIDs","大大,中中,小小");
方法三:通过类来分配(同个人任务分配一样),只是在方法内部调 用的是:delegateTas.addCandidateUser()
或者.addCandidateUsers()方法
----Candidate groups(comma separated):指定组任务分配给角色
可以在流程发布时,设定相应的角色和用户
添加角色:identityService.saveGroup(new GroupEntity(groupId));
添加用户:identityService.saveUser(new UserEntity(userId));
添加两者间的关系:
identityService.createMembership(userId,groupId)
----Form
----Form key:表单id,用于程序内部识别(表单链接)
表单的三种方式:
方法一:(动态表单)
在Form属性中指定各个字段
方法二:(外置表单)
在Main config属性中的Form key字段中指定.form文件的路径
方法三:(普通表单)
在Main config属性中的Form key字段中指定存放表单的页面 (jsp,html,jsf等)
----Listeners:
----Task listeners:任务监听,在流程启动时,把流程变量,通过TaskListener接 口的实现类中的notify方式添加进去
----event :
-----create:创建任务,并设置所有属性后触发
----assignment:任务分配给办理人时触发,在create事件之前
----complete:任务完成,且尚未从数据库中删除时触发
----delete:只在任务删除之前触发。(正常完成时也会触发)
----Execution listeners:执行监听器,在任务执行时,调用ExecutionListener接 口的实现类中的notify方法
----event:对于连续:只能是take(因为连续只能触发take事件,默认该属 性会被忽略)
对于其他组件:(start 和end)
----start:事件开始前调用
----end:事件结束后调用
----Multi instance:
----Sequential:
-----yes:串行(多个人要按照list集合中的顺序依次完成任务)
----no:并行(多个人是同级关系,没有先后,可以同时完成各自的 任务)
----Loop cardinality:产生的实例个数(不能超过list集合的元素个数)
----Collection:#{users}接收任务的人员列表,可以在启动流程实例时进行初 始化流程变量users
例:String [] users={“大大”,”中中”,”小小”};
Map<String,Object> variables=new HashMap<String,Object>();
Variables.put(“users”,Arrays.asList(users));
.startProcessInstanceByKey(processDefintionKey,variables);
----Element variable:办理人的环境变量
例:如果在assignment:中指定为#{user},则该项应为user
----Completion condition:完成条件
可以根据以下三个变量进行设置
nrOfInstances:实例总数
nrOfActiveInstances:当前还没有完成的实例
nrOfCompleteInstances:已经完成的实例个数
3、ExclusiveGateway:排他网关
根据不同的条件执行不同的流程分支(每次只能执行一个流程分支)
----General:(id,name和其他组件意义相同)
----Default flow:默认执行的流程分支,值为默认流程连接线的id
4、ParallelGateway:并行网关
可以同时执行多个流程分支
InclusiveGateway:包含网关
可以同时分支出多个流程分支(与并行网关一样),和并行网关的区别就在于在分支流线上如果定义了条件,并行网关会忽略,而包含网关会进行相应的解析。
5、ReceiveTask:手动接收任务
执行到流程中的某个节点后就暂停执行,指定收到外部的信号后才会继续执行
通过调用runtimeService.signal(executionId);方法,使流程继续向下执行。
6、ScriptTask:脚本任务
可以执行一段脚本,可以在脚本中定义或修改变量,来控制流程的流转。
脚本中添加的变量可以再整个流程中使用。execution.setVariable(“变量名”,变量值)
7、ServiceTask:java服务任务
会调用外部的java类
指定调用的class类的三种方式:
第一种中方法:
----Main config
-----Type:java class -----Service class:选择外部实现了JavaDelegate或者ActivityBehavior 的java类;
第二种方法:
----Main config
----Type:Delegate expression
----Delegate expression:${“在spring中定义了的实现了JavaDelegate的bean”}
第三种方法
----Main config
----Type:Expression
----Expression:#{“在spring中配置的javabean的id.所调用的方法”}
在调用外部java类时,可以注入指段:(两种方式)
方法一:直接注入
----Main config
----Field:new时指定Field name和String value
方法二:使用表达式注入
----Main config
----=Field:new时,指定File name和Expression()
表达式中查找的是流程变量或者Spring定义的bean
----Result variable:会把上面指定的java类的指定方法的返回值赋给该变量,该 变量可以是一个流程变量,或者spring的bean
8、Execution listeners和Task Listeners 执行监听和任务监听
在流程执行期间执行外部的java代码
-----Event:start(事件开启前调用),end(事件结束后调用)
Type和Field和上面的一样
9、Email Task邮件任务:(需要在activiti.cfg.xml中配置邮件服务器)
----Mian config
----To:接受者
----From:发送者
----Subject:主题
----Cc:抄送
----Bcc:暗送
----Charset:字符集
----Html text:邮件内容
10、CallActiviti:调用外部其他流程
当流程运行的此时,启动新的流程实例
----General:
----Default flow:默认流程的流转
----Main config
----Called Element:被调用的流程的.bpmn文件中的id值
11、SubProcess:调用子流程(可以在SubProcess中配置新的流程,当流程运行到这里时会知 道启动子流程)
----id,name和上面的一样
12、timer:定时器(Main config中的数据格式均为:)
必选在activiti的配置文件中配置:<property name="jobExecutorActivate" value="true" />,否则定时任务无法正常启动。
Main config中的数据格式均为:ISO_8601格式:(P ,Y,M,W,D,T,.H,M,S)或 cron时间格式:
Iso_8601格式:
-----Time duration:延时多长时间后触发。例:P10D 表示10天以后触发
-----time date:什么时间触发。例:2011-03-12T12:12:23 表示在2011年03 月12日 12:12:23触发
---time cycle:循环规则:
R【循环次数】【/开始时间】/时间间隔【/结束时间】。
例:R3/PT10 表示重复3次,每次间隔10小时
从2004年5月6日北京时间下午1点起时间间隔半年零5天3小 时循环,且循环3次,可以表示为 R3/2004-05-06T130000+08/P0Y6M5DT3H0M0S。
以1年2个月为循环间隔,无限次循环,最后循环终止于2025年1 月1日,可表示为R/P1Y2M/2025-01-01
Cron 时间格式:seconds minutes hours day-of -mouth mouth,day-of-week year
其中*表示这个域上所有的合法值
例:0 * 17 * * ? 表示每天下午5点到5:59每分钟触发一次
?表示不指定该域上的值(只能用在日域或周域上,且不能同时在两 个域上使用,即假如在在其中的一个域上指定了值,必要再另一 个上放?)
,表示在某个域上指定一个值列表
例:0 10,44 14 ? 3 WEB 表示三月中每个星期三的下午2:10 和下午的2:44触发
- 表示在某个域上指定一个值范围
例:0 45 3-8 ? * * 表示上午3点到上午8点的45分时触发
m/n 表示某个域的值从m开始,按n递增
例:0/15 0/30 * * * ? 表示整点和半点时每15秒触发
L 表示某个域上允许的最后一个值(只能用在日域和周域上,用在 日域上时,表示当月的最后一天触发;用在周域上,表示周的最 后一天,即周六触发)
例:0 0 12 ? * 2L 表示每个月中的最后一个星期一的12:00触发
W 表示里指定日期最近的工作日(只用在日域上,其只能指定单天, 不能指定范围或列表)
例:在日域上指定15W,那么如果15号是工作日,就在15号 触发
如果15号是周六,就在14号触发
如果15号是周日,就在16号触发
# 表示月份中的第几周的哪一天(只用在周域上)
例:6#3 表示某个月的第三个星期五
二、开发流程
1、配置activiti.cfg.xml文件,里面可以配置要访问的数据库
<bean id=”processEngineConfiguration”
class=”org.activiti.engine.impl.cfg.StandaloneInMemprocessEngineConfiguration>
<property name=”databaseType” value=”mysql”/>
<property name=”jdbcUrl” value=”jdbc:mysql://localhost:3306/activiti”/> ......
<!--在进行过去流程引擎时会自动生成工作流需要的28张表-->
<property name=”databaseSchemaUpdate” value=”true”/>
</bean>
2、获取流程引擎(默认会按照类路径下的activiti.cfg.xml文件生成)
ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine();
3、部署流程定义
方法一:(从classpath下部署)
Deployment deployment=processEngine.getRepositoryService()
.createDeployment()
.name(“流程名称”)
.addClasspathResource(“diagrams/helloword.bpmn”)
.addClasspathResource(“diagrams/helloword.png”)
.deploy();
方法二:(从zip文件部署)
//将.bpmn和.png文件压缩到helloword.zip文件中
InputStream inputStream=this.getClass().getClaassLoader().
getResourceAsStream(“diagrams/helloword.zip”);
Deployment deployment=processEngine.getRepositoryService()
.createDeployment()
.name(“流程名称”)
.addZipInputStream(new ZipInputStream(inputStream))
.deploy();
方法三:(从当前路径下获取)
要在Build Pah-->configura Build Path--->Source---->某个包下的Included双击
--->Inclusion pathterns下清空,则会把该包下的所有文件进行编译
InpuStream inputStreamBpmn=this.getClass().
getResourceAsStream(“sequenceFlow.bpmn”);//从当前路径下获取
InpuStream inputStreamBpmn=this.getClass().
getResourceAsStream(“/sequenceFlow.bpmn”);//从类路径下获取
Deployment deployment=processEngine.getRepositoryService()
.createDeployment()
.name(“流程名称”)
.addInputStream(“sequenceFlow.bpmn”,inputStreamBpmn)
.addInputStream(“sequenceFlow.png”,inputStreamPng)
.deploy();
4、启动流程实例
ProcesssInstance processInstance=processEngine.getRuntiomService()
.startProcessInstanceByKey(“.bpmn文件中流程的id属性的值”)
5、任务查询
(1)个人任务查询(只有任务的Main config中的Assignee中指定了办理人才代 表个人任务,才可通过个人任务进行查询)
List<Task> list=processEngine.getTaskService()
.createTaskQuery()
.taskAssignee(“办理人”)//指定办理人
.list();
(2)查询组任务
List<Task> list=processEngine.getTaskService()
.createTaskQuery()
.taskCandidateUser(“组成员或者拥有角色的用户”)
.list();
a.如果是通过组任务的方式进行的任务分配,即在Mian config中的 Candidate Users中通过逗号分隔指定的一组办理人
b.如果是通过角色的方式进行的任务分配即在Main config中的
Candidate groups中指定任务的办理角色
6、完成任务
processEngine.getTaskService().complete(“任务id”);