工作流
1)概念:多个人一起完成某件事情的过程,把这个过程变成计算机识别的形式就是工作流;
2)常见的工作流框架:Activiti、JBPM
3)Activiti的优点:
提高系统柔性,适应业务流程的变化;
实现更好的业务控制过程、提高服务质量
降低维护成本和系统开发人力
4)Activiti核心对象介绍
- 1)工作流引擎ProcessEngine Activiti的核心对象,它负责生成流程时需要的各种实例的数据、监控时维护;
- 2)Activiti流程定义语言BPMN(XML)
- 3)Activiti数据库持久化
- ACT_RE_*: 'RE'表示repository,这个表开头的是包含了定义流程和静态资源(图片、规则) ACT_RU_*:
- 'RU'表示runtime,运行时的流程实例相关的信息,开启流程后到结束所有的实例数据都存储在这里; ACT_ID_*:
- 'ID'表示identity,身份相关信息 ACT_HI_*:
- 'HI'表示history,这些表包含历史数据,比如历史流程实例、具体的活动历史流程实例; ACT_GE_*: 通用数据,
用于不同场景下。(上传的流程图保存在里面)
5)使用Activiti
a、准备eclipse的Activiti插件压缩包
百度云资源:https://pan.baidu.com/s/1oZX8_rZZmXGAbWqn_amRog
b、把压缩包中的内容(Activiti)放入eclipse根目录的dropins文件夹下
c、创建web项目,并导入包(全部)
百度云资源全部jar: https://pan.baidu.com/s/1xxGn9K1PIVs_gbLibwHqzw
选择下面的就可以了,差啥导啥
d、得到工作流的核心对象ProcessEngine(三种方式)
编码方式
// 创建ProcessEngine引擎对象:就会自动创建数据和25张表
@Test
public void createProcessEngine1() {
//是一个接口:我们需要去连接数据库,肯定需要很多连接信息,就是配置信息
//所以先做配置对象,再通过配置对象构建引擎
// ProcessEngine 创建引擎的配置对象
ProcessEngineConfiguration configuration=
ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration();
//做引擎配置对象的配置
configuration.setJdbcUrl("jdbc:mysql:///activiti?
createDatabaseIfNotExist=true");
configuration.setJdbcDriver("com.mysql.jdbc.Driver");
configuration.setJdbcUsername("root");
configuration.setJdbcPassword("000000");
//设置创建数据库表的策略:true:创建
configuration.setDatabaseSchemaUpdate
(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
//通过引擎配置对象构建引擎
ProcessEngine pe = configuration.buildProcessEngine();
// org.activiti.engine.impl.ProcessEngineImpl@3c947bc5
System.out.println(pe);
}
配置方式(resource下的activiti.cfg.xml)
@Test
public void createProcessEngine2() throws Exception {
/**
* 让创建的配置对象 加载配置文件创建引擎对象
*/
try {
ProcessEngineConfiguration configuration =
ProcessEngineConfiguration.
createProcessEngineConfigurationFromResource("activiti.cfg.xml");
ProcessEngine processEngine = configuration.buildProcessEngine();
//org.activiti.engine.impl.ProcessEngineImpl@36b4091c
System.out.println(processEngine);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
最佳实践方式(推荐)
/**
* 配置文件都是按照一定规则来的:activiti.cfg.xml有统一的命名规范,,放在resource下
* 使用框架提供的默认方法创建
* @throws Exception
*/
@Test
public void creatProcessEngine3() throws Exception {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//org.activiti.engine.impl.ProcessEngineImpl@1583741e
System.out.println(processEngine);
}
6)学习导读
6.1)使用Activiti绘图,会产生两个文件:bpmn(流程定义文件),png(流程图)
右键创建资源文件
6.2)部署流程的核心对象ProcessDefinition
6.2.1)部署流程
/**
* @throws Exception
*流程定义(规则)管理--核心(ProcessDefinition)
* 1、部署流程
* 2、流程定义列表查询
* 3、删除流程(删除部署,流程的挂起和激活)
* 4、查看规则流程图 (没有修改,删除了重新部署!!)
* 涉及的数据库三张表:
* 1)act_re_deployment 部署信息表:部署一次就有一条记录
* 2)act_re_procdef 流程定义数据表:部署一次,就产生一个流程,有一个流程定义数据
* 3)act_ge_bytearray二进制数据表:一个流程定义会有有两个2机制数据:.bpmn和png的数据
*/
@Test
public void processDefinitionTest() throws Exception {
// 1 拿到核心对象 首先获得默认的流程引擎,在创建时会自动加载classpath下得activiti.cfg.xml
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 2 通过核心对象拿到服务实例 仓库服务类:bpmn文件和流程图片
RepositoryService repositoryService = processEngine.getRepositoryService();
// 3 通过仓库服务对象部署一个builder 用来封装部署环境的相关配置
DeploymentBuilder builder = repositoryService.createDeployment();
// 部署两个资源文件bpmn和png图片
builder.addClasspathResource("LeaveProcess.bpmn")
.addClasspathResource("LeaveProcess.png").name("员工离职_verson1");
// 4 使用服务的方法做事情
Deployment deployment = builder.deploy();
System.out.println(deployment);
}
启动部署后创建的数据表
6.2.2)流程定义列表查询
// 查看定义的流程列表信息
@Test
public void processDefinitedList() throws Exception {
// 1 获取核心对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 2 通过核心对象,获取服务对象 流程定义的信息存放在仓库中,所以应该获取RepositoryService
RepositoryService repositoryService = processEngine.getRepositoryService();
// 3 使用服务做事情 查询
// 创建查询对象
ProcessDefinitionQuery definitionQuery = repositoryService.createProcessDefinitionQuery();
// 设置查询条件
// deploymentQuery.processDefinitionKey("myProcess");
// definitionQuery.processDefinitionKey(processDefinitionKey)
// definitionQuery.processDefinitionKeyLike(processDefinitionKeyLike)
// definitionQuery.processDefinitionName(processDefinitionName)
// definitionQuery.processDefinitionNameLike(processDefinitionNameLike)
// 执行查询
// System.out.println(definitionQuery.count());
// definitionQuery.count();//查询总的条数
// definitionQuery.list();//查询所有的流程定义
// definitionQuery.singleResult();//查询唯一记录
// definitionQuery.listPage(firstResult, maxResults);//分页查询
// 查询全部
List<ProcessDefinition> list = definitionQuery.list();
// 循环查询结果
for (ProcessDefinition pD : list) {
System.out.println("id=" + pD.getId());
System.out.println("name=" + pD.getName());
System.out.println("category=" + pD.getCategory());
System.out.println("resourceName=" + pD.getResourceName());
System.out.println("DeployementId=" + pD.getDeploymentId());
System.out.println("key用户定义不同的流程" + pD.getKey());
}
}
6.2.3)删除流程(删除部署,流程的挂起和激活)
/**
* 删除流程定义(删除部署,就删除了流程定义) --> 使用流程挂起和激活来实现流程的删除.物理删除也许失败 因为有外键
*/
@Test
public void delProcess() throws Exception {
try {
// 1 获取核心引擎对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 2 拿到服务对象实例
RepositoryService repositoryService = processEngine.getRepositoryService();
String deploymentId = "5001";
// 3 调用服务对象的方法
// 使用服务的方法做事情:删除一个部署,就删除一个流程定义
repositoryService.deleteDeployment(deploymentId);//物理删除
//String processDefinitionKey="myProcess";//定义流程的key值
//逻辑删除:挂起 suspend,其实是修改某个字段的状态suspension_state 1激活 2挂起
//repositoryService.suspendProcessDefinitionByKey(processDefinitionKey);
//激活
//String processDefinitionKey="myProcess";
//repositoryService.activateProcessDefinitionByKey(processDefinitionKey);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}}
6.2.4)查看规则流程图(没有修改,删除了重新部署!!)
// 查看规则流程图 查询出流程定义文档。主要查的是图片,用于显示流程用
@Test
public void viewProcessDiagram() throws Exception {
try {
// 获取核心对象
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
// 分析需求,通过核心对象获取对应的"服务实例"
RepositoryService repositoryService = engine.getRepositoryService();
// 使用服务方法做事情
String deploymentId = "5001";//deploymentId为流程部署ID
String resourceName = "Myprocess.png";//act_ge_bytearray表中NAME_列的值
// 通过流的方式获取,以后在做项目的时候直接复制到response中就可以输出了
InputStream resourceAsStream =
repositoryService.getResourceAsStream(deploymentId, resourceName);
// 输出到本地
IOUtils.copy(resourceAsStream, new FileOutputStream(new
File("d://9.png")));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
7)流程运行时管理核心对象ProcessInstance
7.1)启动流程
// act_ru_execution:存储流程的相关信息
// act_ru_identifylink 执行介绍 该表数据消失
// act_ru_task 如果该表是有人参与的流程节点 那么是对execution的补充
@Test
public void startProcessInstance() throws Exception {
// 拿到大管家
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 拿到相应的服务对象 启动实例,启动后就运行了,使用运行服务
RuntimeService runtimeService = processEngine.getRuntimeService();
// 调用服务对象的方法做事情
String processDefinitionKey = "leaveProcess";// 定义流程的key
// 启动流程实例
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey);
System.out.println("instanceId:" + processInstance.getId());
System.out.println("instanceIName:" + processInstance.getName());
// 操作数据库的act_ru_execution表,如果是用户任务节点,同时也会在act_ru_task添加一条记录
}
7.2)查看任务
私有任务
// 查看有人参与的节点 的//私有任务
@Test
public void viewPersonTask() throws Exception {
// 拿到核心对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 拿到服务对象实例 启动实例
TaskService taskService = processEngine.getTaskService();
// 调用服务对象的方法做事情
// 查询得先创建一个查询对象
TaskQuery taskQuery = taskService.createTaskQuery();
String assignee = "yang";
// 设置yang的任务 查询条件
taskQuery.taskAssignee(assignee); // taskAssignee指定任务的候选者
// 执行查询操作
List<Task> list = taskQuery.list();
for (Task task : list) {
// Task[id=2504, name=????]
System.out.println(task);
}
}
![在这里插入图片描述](https://img-blog.csdnimg.cn/20181111180303562.png)
公共任务
// 查看任务:公共任务
@Test
public void commandTask() throws Exception {
try {
// 1 拿到核心对象
ProcessEngine processEngine =
ProcessEngines.getDefaultProcessEngine();
// 2 拿到服务对象
TaskService taskService = processEngine.getTaskService();
// 3 调用服务对象的方法
// 拿到查询对象
TaskQuery taskQuery = taskService.createTaskQuery();
// 4 执行查询
taskQuery.taskCandidateUser("tang");
List<Task> list = taskQuery.list();
for (Task task : list) {
System.out.println(task);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
7.3)认领任务
/**
* 任务认领:对于公有任务,可以认领。一旦认领后,自己就不再有这个任务
*/
@Test
public void claimTask() throws Exception {
ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine();
TaskService taskService = processEngine.getTaskService();
String taskId="2505";
String userId="liu";
//确定被认领的任务ID和认领人ID
taskService.claim(taskId, userId);
}
7.4)完成任务
// 指定任务ID,完成该任务。
// 办理任务
@Test
public void completeProcess() {
try {
// 流程执行
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 流程启动后,办理是人在办理,使用taskService
TaskService taskService = processEngine.getTaskService();
// 表:act_ru_task
taskService.complete("2504");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
7.5)查看流程实例历史状态
// 查看用户按照某个流程规则执行了多少次流程
@Test
public void processDefinitionHistoryTest() throws Exception {
// 1 获取核心镀锡
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 2 拿到历史服务对象实例
HistoryService historyService = processEngine.getHistoryService();
// 3 通过服务对象方法做事情
// 创建历史实例查询对象
HistoricProcessInstanceQuery historicProcessInstanceQuery =
historyService.createHistoricProcessInstanceQuery();
historicProcessInstanceQuery.processInstanceBusinessKey("leaveProcess");
// 执行查询
List<HistoricProcessInstance> list = historicProcessInstanceQuery.list();
for (HistoricProcessInstance historicProcessInstance : list) {
System.out.println(historicProcessInstance);
}
}
7.6)查看活动流程实例历史状态
// 查看某次流程的执行执行经历具体的。
@Test
public void activityInstanceTest() throws Exception {
// 1 获取核心对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 2 拿到历史服务对象实例
HistoryService historyService = processEngine.getHistoryService();
// 3 拿到查询对象
HistoricActivityInstanceQuery activityInstanceQuery = historyService.createHistoricActivityInstanceQuery();
//4 设置查询条件 执行查询
List<HistoricActivityInstance> list = activityInstanceQuery.processInstanceId("2505").list();
for (HistoricActivityInstance historicActivityInstance : list) {
System.out.println(historicActivityInstance);
}
}
7.7)查看是否流程结束
/**
* 查询流程状态是否结束
*/
@Test
public void checkProceeEnd() throws Exception {
ProcessEngine engine=ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = engine.getRuntimeService();
//创建流程查询对象
ProcessInstanceQuery query = runtimeService.createProcessInstanceQuery();
//查询条件
ProcessInstanceQuery processInstanceId = query.processInstanceId("2504");
ProcessInstance result = query.singleResult();
if(result==null){
System.out.println("processInstanceId="+processInstanceId+"流程已经结束");
}else{
System.out.println("processInstanceId="+processInstanceId+"流程还在运行中");
}
}
8)核心API
1. ProcessEngine: 在Activiti中最核心的类,其他的类都是由他而来,它管理着7个服务类对象
各个Service的作用:
1. RepositoryService 管理流程规则相关。流程定义
仓库服务类主要是管理bpmn文件和流程图片,可以通过核心对象获取,和流程定义相关的操作都使用这个类型的对象实现部署流程,流程定义列表的查询,查看规则流程图,删除流程(删除部署,流程的挂起和激活)
2. RuntimeService 执行管理,包括启动、推进、删除流程实例等操作
运行时服务对象流程实例相关的操作都使用这个类型的对象实现可以启动流程,查看流程状态;
3. TaskService 任务管理,比如任务的查看、办理等
任务服务类对象任务相关的操作要使用该对象来查看私有任务、公共任务和认领任务、完成任务
4. HistoryService 历史管理(执行完的数据的管理)
历史相关的操作(主要用于查看流程操作的历史过程)
5. IdentityService Activiti的组织机构管理
6. FormService 一个可选服务,任务表单管理
7. ManagerService 管理定时任务
8. RepositoryService:规则类,是Activiti的仓库服务类
9. ProcessDefinition:定义流程对象,可以获取到资源文件
10. ProcessInstance:流程实例对象,每个部署就是一个流程实例
11. Execution :执行对象
一个流程中,执行对象可以存在多个,但是流程实例只能有一个。
当流程按照规则只执行一次的时候,那么流程实例就是执行对象。