BOS项目笔记第10天
内容:
1、历史数据查询(历史流程实例数据、历史任务数据、历史活动数据)
2、流程变量
3、组任务(候选人、候选组)
4、监听器(执行、任务)
5、网关(排他、并行)
6、spring整合activiti
1. 历史数据查询
历史是一个组件,它可以捕获发生在进程执行中的信息并永久的保存,与运行时数据不同的是,当流程实例运行完成之后它还会存在于数据库中。
在流程引擎配置对象中可以设置历史记录规则:

1.1 查询历史流程实例数据
表中内容包含已经完成的流程和正在进行的流程
//查询历史流程实例数据 @Test public void test4(){ //历史流程实例查询对象,查询表:act_hi_procinst HistoricProcessInstanceQuery query = pe.getHistoryService().createHistoricProcessInstanceQuery(); List<HistoricProcessInstance> list = query.list(); for (HistoricProcessInstance pi : list) { System.out.println(pi.getId() + " " + pi.getStartTime() + " " + pi.getEndTime()); } }
1.2 历史任务数据
表中内容包含已经完成的任务和正在进行的任务
//查询历史任务数据 @Test public void test5(){ //历史任务实例查询对象,查询表:act_hi_taskinst HistoricTaskInstanceQuery query = pe.getHistoryService().createHistoricTaskInstanceQuery(); query.orderByProcessInstanceId(); query.orderByHistoricTaskInstanceStartTime().asc(); List<HistoricTaskInstance> list = query.list(); for (HistoricTaskInstance task : list) { System.out.println(task.getProcessInstanceId() + " " + task.getName()); } }
1.3 历史活动数据
包含一个活动(流程上的节点)的执行信息
//查询历史活动数据 @Test public void test6(){ //历史活动实例查询对象,查询表:act_hi_actinst HistoricActivityInstanceQuery query = pe.getHistoryService().createHistoricActivityInstanceQuery(); query.orderByProcessInstanceId(); query.orderByHistoricActivityInstanceStartTime().asc(); List<HistoricActivityInstance> list = query.list(); for (HistoricActivityInstance ai : list) { System.out.println(ai.getProcessInstanceId() + " " + ai.getActivityName()); } }
2. 流程变量
流程变量的作用域范围是流程实例。也就是说各个流程实例的流程变量是不相互影响的
2.1 设置流程变量
方式一:启动流程实例时设置流程变量
// 设置流程变量方式一:启动流程实例时设置 @Test public void test2() { String processDefinitionKey = "qjlc"; Map<String, Object> variables = new HashMap<String, Object>(); variables.put("k1", "v1"); variables.put("k2", 200); variables.put("username", "小明");//从session中动态获取当前登录用户的用户名 ProcessInstance processInstance = pe.getRuntimeService() .startProcessInstanceByKey(processDefinitionKey, variables); System.out.println(processInstance.getId()); }
方式二:办理任务时设置流程变量
// 设置流程变量方式二:办理任务时设置 @Test public void test3() { // pe.getTaskService().createTaskQuery().taskAssignee("张三").list(); String taskId = "1502"; Map<String, Object> variables = new HashMap<>(); variables.put("qjts", 5); variables.put("qjyy", "不想上班"); pe.getTaskService().complete(taskId, variables); }
方式三:使用RuntimeService的set方法设置流程变量
// 设置流程变量方式三:RuntimeService的Set方法设置 @Test public void test4() { String executionId = "801";// 流程实例ID String variableName = "k3";// 流程变量的key Object value = "v3";// 流程变量的value // 设置一个流程变量 // pe.getRuntimeService().setVariable(executionId, variableName, value); Map<String, Object> variables = new HashMap<String, Object>(); variables.put("k4", "v4"); variables.put("k4", "v5"); variables.put("user", new User(10, "abc", 20)); // 设置多个流程变量 pe.getRuntimeService().setVariables(executionId, variables); }
方式四:使用TaskService的set方法设置流程变量
// 设置流程变量方式四:TaskService的Set方法设置 @Test public void test5() { String taskId = "1004";// 任务ID // 设置一个流程变量 pe.getTaskService().setVariable(taskId, "k5", "v5"); // 设置多个流程变量 // pe.getTaskService().setVariables(taskId, variables); }
注:自定义类如果需要设置流程变量,必须实现Serializable序列化接口。
2.2 获取流程变量
流程变量是从act_ru_variable这个表中读出来的
使用RuntimeService的get方法获取
// 获取流程变量方式一:使用RuntimeService的get方法获取 @Test public void test6() { String executionId = "801"; // 获取一个流程变量 Object v = pe.getRuntimeService().getVariable(executionId, "k1"); System.out.println(v); // 获取多个流程变量 Map<String, Object> variables = pe.getRuntimeService().getVariables( executionId); Set<String> keySet = variables.keySet(); for (String key : keySet) { Object value = variables.get(key); System.out.println(key + " = " + value); } }
使用TaskService的get方法获取
与runtimeService结果一样
注:存储的对象参数,再获取的时候必须与存储时对象结构一样(也可以添加固定序列化id),如果发生改变会抛异常,无法反序列化
// 获取流程变量方式二:使用TaskService的get方法获取 @Test public void test7() { String taskId = "1004"; // 获取一个流程变量 User user = (User) pe.getTaskService().getVariable(taskId , "user"); System.out.println(user); // 获取当前任务所在流程实例(801)范围内所有的流程变量 Map<String, Object> variables = pe.getTaskService().getVariables(taskId); Set<String> keySet = variables.keySet(); for (String key : keySet) { Object value = variables.get(key); System.out.println(key + " = " + value); } }
使用框架提供的表达式获取
3. 组任务操作
个人任务(私人任务):由某一个人负责办理的任务为个人任务
组任务(公共任务):多个人作为候选人,都可以办理的任务
3.1 候选人
所有组(公共)任务的assignee属性为空
查询组任务
// 查询组任务 @Test public void test5() { TaskQuery query = pe.getTaskService().createTaskQuery(); // 组任务查询 query.taskCandidateUser("user1"); List<Task> list = query.list(); for (Task task : list) { System.out.println(task.getId() + " " + task.getName()); } }
拾取组任务(将组任务变为个人任务)
// 拾取组任务 @Test public void test6() { String taskId = "2302"; String userId = "user1"; pe.getTaskService().claim(taskId, userId); }
退回组任务(,将个人任务变为组任务)
// 退回组任务 @Test public void test7() { String taskId = "2302"; pe.getTaskService().setAssignee(taskId, null); }
3.2 候选组(重点)
创建组
与项目中的角色表保持一致
// 创建组,操作的表:act_id_group @Test public void test2() { // 实际项目中group表中的数据和系统表角色表保持一致 Group group = new GroupEntity(); group.setId("财务人员组"); group.setName("财务人员组"); pe.getIdentityService().saveGroup(group); }
创建用户
与项目中的用户表保持一致
import org.activiti.engine.identity.User;
// 创建用户,操作的表:act_id_user @Test public void test3() { // 实际项目中act_id_user表中的数据和系统表用户表(t_user)保持一致 User user = new UserEntity(); user.setId("002"); user.setFirstName("小王"); pe.getIdentityService().saveUser(user); }
将用户加入到组中
// 将用户加入到组中 @Test public void test4() { pe.getIdentityService().createMembership("002", "财务人员组"); }
查询任务使用候选人(既候选人id)进行过滤
//查询组任务 @Test public void test8(){ TaskQuery query = pe.getTaskService().createTaskQuery(); //组任务查询 //query.taskCandidateGroup("财务人员组"); query.taskCandidateUser("001");//使用候选人进行过滤 List<Task> list = query.list(); for (Task task : list) { System.out.println(task.getId() + " " + task.getName()); } } //拾取组任务 @Test public void test9(){ String taskId = "3002"; String userId = "001"; pe.getTaskService().claim(taskId, userId); }
4. 监听器
在流程中我们有时会对整个流程或者一个节点的某种状态做出相应的处理。这时就会用到监听器。
在Activiti中流程的监听主要分为两大类,执行监听器和任务监听器。
4.1 执行监听器
监听流程实例的开始事件和结束事件
执行监听器可以执行外部java代码或执行表达式,当流程定义中发生了某个事件。
可以捕获的事件有:
流程实例的启动和结束。
选中一条连线。
节点的开始和结束。
网关的开始和结束。
中间事件的开始和结束。
开始事件结束或结束事件开始。
按照框架的要求编写一个监听器类,必须实现org.activiti.engine.delegate.ExecutionListener接口
/** * 自定义一个监听器类 * */ public class MyExecutionListener1 implements ExecutionListener { public void notify(DelegateExecution execution) throws Exception { String processInstanceId = execution.getProcessInstanceId(); String eventName = execution.getEventName(); Set<String> variableNames = execution.getVariableNames(); Map<String, Object> variables = execution.getVariables(); String processDefinitionId = execution.getProcessDefinitionId(); System.out.println("自定义的监听器执行了,监听器到事件:" + eventName); } }
注册监听器
执行监听器支持以下属性:
event(必选):任务监听器会被调用的任务类型。 可能的类型为:
start:流程节点创建后触发。
end:当任务完成,并尚未从运行数据中删除时触发。
take:任务完成后,流程流出时触发(监听一条连线的执行,配置在sequenceFlow节点的内部,只有task一种事件)
使用图形界面注册监听器

4.2 任务监听器
*监听任务相关的事件,如任务的创建事件,任务的办理事件
*任务监听器可以在发生对应的任务相关事件时执行自定义java逻辑 或表达式。
*任务监听器只能添加到流程定义中的用户任务中
按照框架的要求编写监听器类,实现TaskListener接口
/** * 自定义任务监听器 * */ public class MyTaskListener1 implements TaskListener{ public void notify(DelegateTask task) { String id = task.getId(); String name = task.getName(); String assignee = task.getAssignee(); Date createTime = task.getCreateTime(); String eventName = task.getEventName(); String processInstanceId = task.getProcessInstanceId(); Map<String, Object> variables = task.getVariables(); System.out.println("自定义任务监听器执行了,任务:[" + name + "] 被创建了,负责人为:" + assignee); } }
注册监听器
任务监听器支持以下属性:
event(必选):任务监听器会被调用的任务类型。 可能的类型为:
create:任务创建并设置所有属性后触发。
assignment:任务分配给一些人时触发。 当流程到达userTask,assignment事件 会在create事件之前发生。 这样的顺序似乎不自然,但是原因很简单:当获得create时间时, 我们想获得任务的所有属性,包括执行人。
complete:当任务完成,并尚未从运行数据中删除时触发。
5. 网关
*网关用来控制流程的流向。
*网关显示成菱形图形,内部有有一个小图标。 图标表示网关的类型。
5.1 排他网关
特点:只能有一个分支执行。
1.一个排他网关对应一个以上的顺序流
2.由排他网关流出的顺序流都有个conditionExpression元素,在内部维护返回boolean类型的决策结果。
3.决策网关只会返回一条结果。当流程执行到排他网关时,流程引擎会自动检索网关出口,
从上到下检索如果发现第一条决策结果为true或者没有设置条件的(默认为成立),则流出。
5.2 并行网关
网关也可以表示流程中的并行情况。
最简单的并行网关是parallelGateWay,它允许将流程 分成多条分支,也可以把多条分支 汇聚到一起。
图形标记
并行网关显示成一个普通网关(菱形)内部是一个“加号”图标, 表示“与(AND)”语义。
特点:多个分支同时执行。
1.并行网关的功能是基于进入和外出的顺序流的:
分支(fork): 并行后的所有外出顺序流,为每个顺序流都创建一个并发分支。
汇聚(join): 所有到达并行网关,在此等待的进入分支,直到所有进入顺序流的分支都到达以后, 流程就会通过汇聚网关。
2.并行网关的进入和外出都是使用相同节点标示
3.如果同一个并行网关有多个进入和多个外出顺序流,它就同时具有分支和汇聚功能。 这时,网关会先汇聚所有进入的顺序流,然后再切分成多个并行分支。
4.并行网关不会解析条件。即使顺序流中定义了条件,也会被忽略。
5.并行网关不需要是“平衡的”(比如,对应并行网关的进入和外出节点数目相等)

表中数据(流程实例表):
表中数据(任务表):
6. spring整合activiti框架
和Spring的集成主要就是把Activiti的主要对象交给Spring容器管理。
第一步:提供spring配置文件,配置数据源、事务管理器、spring提供的流程引擎配置对象、流程引擎工厂bean
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> <!-- 数据源信息 --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql:///activiti_day2"></property> <property name="username" value="root"></property> <property name="password" value="root"></property> </bean> <!-- 事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <!-- 配置流程引擎配置对象 --> <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration"> <!-- 注入数据源 --> <property name="dataSource" ref="dataSource"></property> <!-- 注入事务管理器 --> <property name="transactionManager" ref="transactionManager"></property> <!-- 注入自动建表设置 --> <property name="databaseSchemaUpdate" value="true"></property> </bean> <!-- 提供工厂bean,创建流程引擎对象 --> <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean"> <property name="processEngineConfiguration" ref="processEngineConfiguration"></property> </bean> <!-- 配置Service --> <bean id="repService" factory-bean="processEngine" factory-method="getRepositoryService"></bean> </beans>
第二步测试:读取spring配置文件,创建spring工厂,从spring工厂中获取一个流程引擎对象
public class SpringActivitiTest { public static void main(String[] args) { // 创建spring工厂,从spring工厂中获取一个流程引擎对象 ApplicationContext ctx = new ClassPathXmlApplicationContext( "com/itheima/activiti/spring/applicationContext.xml"); /*ProcessEngine processEngine = (ProcessEngine) ctx .getBean("processEngine"); List<ProcessDefinition> list = processEngine.getRepositoryService() .createProcessDefinitionQuery().list(); for (ProcessDefinition processDefinition : list) { System.out.println(processDefinition.getName()); }*/ RepositoryService service = (RepositoryService) ctx.getBean("repService"); List<ProcessDefinition> list = service.createProcessDefinitionQuery().list(); for (ProcessDefinition processDefinition : list) { System.out.println(processDefinition.getName()); } } }
将activiti加入进bos项目
jar包:去掉重复的spring等 jar包
把配置中引擎对象 工厂bean 和service 复制进bos spring配置文件即可
测试:配置正确启动项目会生成23张表
- 顶
- 0
- 踩
- 0