activiti 的使用
来源:互联网 发布:淘宝网免单 编辑:程序博客网 时间:2024/05/21 11:06
一,Activiti简介。
Activiti项目是一项新的基于Apache许可的开源工作流引擎,它实现了BPMN 2.0规范,可以发布设计好的流程定义,并通过api进行流程调度。
二,BPMN2.0规范。
BPMN(Business ProcessModel and Notation)--业务流程模型与符号。
BPMN是一套流程建模的标准,主要目标是被所有业务用户容易理解的符号,支持从创建流程轮廓的业务分析到这些流程的最终实现,知道最终用户的管理监控。
通俗一点其实就是一套规范,画流程模型的规范。
流程模型包括:流程图、协作图、编排图、会话图。
三,demo(也可以当做Activiti控制台)
1,学习网站:http://www.mossle.com/docs/activiti/index.html#demo.setup.one.minute.version;
2,从Activiti网站下载ActivitiExplorer的WAR文件;点击这里可以下载
3,准备运行环境:jdk 1.6+ ,tomcat 6.0+;
4,将上面的war包放到tomcatwebapps文件夹下面;
5,启动tomcat,访问:http://localhost:8080/activiti-explorer,使用kermit/kermit登录;
6,登录后可以测试创建任务,提交申请,完成审批等操作。
7,点击流程设计工作区,可以自定义流程。
四,本地项目使用(简单测试)
1,这里以maven web 项目为基础,开发工具使用eclipse,要求jdk 1.6及以上版本。
2,如果不想使用上面提供的管理器定义流程图,也可以在自己本地下载eclipse插件:
Activiti BPMN 2.0 designer。
下载步骤:
打开eclipse,找到工具栏Help,选择Install New SoftWare,点击Add输入:
Activiti BPMN 2.0 designer
http://activiti.org/designer/update/
按照默认勾选,直到安装完成,重启eclipse生效。
3,新建maven web项目,添加依赖包,项目有使用Spring + Spring mvc 框架,这里省略配置。
<dependency> <groupId>org.activiti</groupId> <artifactId>activiti-engine</artifactId> <version>5.21.0</version> </dependency> <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-spring</artifactId> <version>5.21.0</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.10</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.1.2</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.1.2</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.38</version> </dependency>
4,设计流程图。
4.1,在项目中新建一个*.bpmn,如my-process.bpmn,上面已经安装了插件。
4.2,完成一个简单的流程图,这里新建了两个用户审批节点。
4.3,保存后会自动生成xml文档,切换查看方式为xml,可以看到源文件:
<?xml version="1.0" encoding="UTF-8"?><definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test"> <process id="my-process" isExecutable="true"> <startEvent id="startevent1" name="Start"></startEvent> <userTask id="usertask1" name="主管审批"></userTask> <sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow> <userTask id="usertask2" name="经理审批"></userTask> <sequenceFlow id="flow2" sourceRef="usertask1" targetRef="usertask2"></sequenceFlow> <endEvent id="endevent1" name="End"></endEvent> <sequenceFlow id="flow3" sourceRef="usertask2" targetRef="endevent1"></sequenceFlow> </process> <bpmndi:BPMNDiagram id="BPMNDiagram_my-process"> <bpmndi:BPMNPlane bpmnElement="my-process" id="BPMNPlane_my-process"> <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1"> <omgdc:Bounds height="35.0" width="35.0" x="50.0" y="140.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1"> <omgdc:Bounds height="55.0" width="105.0" x="130.0" y="130.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2"> <omgdc:Bounds height="55.0" width="105.0" x="280.0" y="130.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1"> <omgdc:Bounds height="35.0" width="35.0" x="430.0" y="140.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1"> <omgdi:waypoint x="85.0" y="157.0"></omgdi:waypoint> <omgdi:waypoint x="130.0" y="157.0"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2"> <omgdi:waypoint x="235.0" y="157.0"></omgdi:waypoint> <omgdi:waypoint x="280.0" y="157.0"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3"> <omgdi:waypoint x="385.0" y="157.0"></omgdi:waypoint> <omgdi:waypoint x="430.0" y="157.0"></omgdi:waypoint> </bpmndi:BPMNEdge> </bpmndi:BPMNPlane> </bpmndi:BPMNDiagram></definitions>
5,流程设计完成后,主要是在项目中如何集成使用。
5.1,添加配置文件,默认文件名activiti.cfg.xml,这里使用Spring管理,可以任意命名,需要在wen.xml中指定classpath。
配置关系图:
配置示例:
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- activiti 常规配置 --> <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration"> <!-- activiti需要用到有23张表,需要用到数据库,默认是h2内存数据库,这里需要更改为本地使用的库 --> <property name="dataSource" ref="dataSource"/> <!-- 事务 --> <property name="transactionManager" ref="transactionManager"/> <!-- 数据库类型 --> <property name="databaseType" value="mysql"/> <!-- 数据库脚本更新策略 --> <property name="databaseSchemaUpdate" value="true"/> <!-- JobExecutor是管理一系列线程的组件,可以触发定时器,如果不想在流程引擎启动后自动激活JobExecutor,可以设置为false--> <property name="jobExecutorActivate" value="true"/> <!-- 历史配置 --><!-- <property name="history" value="full"/> --> <!-- 限制流程定义缓存 --> <property name="processDefinitionCacheLimit" value="10"/> <!-- 禁用身份模块 --> <property name="dbIdentityUsed" value="false"/> <!-- 资源自动部署 --><!-- <property name="deploymentResources" value="classpath*:/bpmn/*.bpmn20.xml" /> --> </bean><!-- activiti工作的核心。负责生成流程运行时的各种实例及数据、监控和管理流程的运行。 --> <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean"> <property name="processEngineConfiguration" ref="processEngineConfiguration"/> </bean> <!-- activiti api接口 --> <!-- 负责静态信息 --> <bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService"/> <!-- 负责启动一个流程定义的新实例 --> <bean id="runtimeService" factory-bean="processEngine" factory-method="getRuntimeService"/> <!-- 可选服务,提供了启动表单和任务表单两个概念。 启动表单会在流程实例启动之前展示给用户, 任务表单会在用户完成任务时展示 --> <bean id="formService" factory-bean="processEngine" factory-method="getFormService"/> <!-- 可以管理(创建,更新,删除,查询...)群组和用户 --> <bean id="identityService" factory-bean="processEngine" factory-method="getIdentityService"/> <!-- 可以从这个类中获取任务的信息 --> <bean id="taskService" factory-bean="processEngine" factory-method="getTaskService"/> <!-- 提供了Activiti引擎手机的所有历史数据 --> <bean id="historyService" factory-bean="processEngine" factory-method="getHistoryService"/> <!-- 可以查询数据库的表和表的元数据 --> <bean id="managementService" factory-bean="processEngine" factory-method="getManagementService"/></beans>
上面配置中的activiti api接口也可以不配置,在项目中使用就使用processEngine调用上面配置的factory-method方法获取。
5.2,启动项目,查看日志,activiti会自动创建所需要的数据表。
2017-07-20 14:11:06.017 [localhost-startStop-1] DEBUG o.a.e.i.interceptor.LogInterceptor - --- starting SchemaOperationsProcessEngineBuild --------------------------------------------------------2017-07-20 14:11:06.023 [localhost-startStop-1] DEBUG o.a.s.SpringTransactionInterceptor - Running command with propagation NOT_SUPPORTED2017-07-20 14:11:06.078 [localhost-startStop-1] DEBUG o.a.i.t.managed.ManagedTransaction - Opening JDBC Connection2017-07-20 14:11:06.111 [localhost-startStop-1] DEBUG o.s.jdbc.datasource.DataSourceUtils - Fetching JDBC Connection from DataSource2017-07-20 14:11:06.675 [localhost-startStop-1] DEBUG o.s.jdbc.datasource.DataSourceUtils - Registering transaction synchronization for JDBC Connection2017-07-20 14:11:06.690 [localhost-startStop-1] INFO o.a.engine.impl.db.DbSqlSession - performing create on engine with resource org/activiti/db/create/activiti.mysql.create.engine.sql2017-07-20 14:11:06.690 [localhost-startStop-1] INFO o.a.engine.impl.db.DbSqlSession - Found MySQL: majorVersion=5 minorVersion=72017-07-20 14:11:06.692 [localhost-startStop-1] DEBUG o.a.engine.impl.db.DbSqlSession - SQL: create table ACT_GE_PROPERTY ( NAME_ varchar(64), VALUE_ varchar(300), REV_ integer, primary key (NAME_) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin2017-07-20 14:11:07.229 [localhost-startStop-1] DEBUG o.a.engine.impl.db.DbSqlSession - SQL: insert into ACT_GE_PROPERTY values ('schema.version', '5.18.0.1', 1)2017-07-20 14:11:07.274 [localhost-startStop-1] DEBUG o.a.engine.impl.db.DbSqlSession - SQL: insert into ACT_GE_PROPERTY values ('schema.history', 'create(5.18.0.1)', 1)2017-07-20 14:11:07.318 [localhost-startStop-1] DEBUG o.a.engine.impl.db.DbSqlSession - SQL: insert into ACT_GE_PROPERTY values ('next.dbid', '1', 1)2017-07-20 14:11:07.407 [localhost-startStop-1] DEBUG o.a.engine.impl.db.DbSqlSession - SQL: create table ACT_GE_BYTEARRAY ( ID_ varchar(64), REV_ integer, NAME_ varchar(255), DEPLOYMENT_ID_ varchar(64), BYTES_ LONGBLOB, GENERATED_ TINYINT, primary key (ID_) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin2017-07-20 14:11:08.383 [localhost-startStop-1] DEBUG o.a.engine.impl.db.DbSqlSession - SQL: create table ACT_RE_DEPLOYMENT ( ID_ varchar(64), NAME_ varchar(255), CATEGORY_ varchar(255), TENANT_ID_ varchar(255) default '', DEPLOY_TIME_ timestamp(3), primary key (ID_) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin2017-07-20 14:11:09.338 [localhost-startStop-1] DEBUG o.a.engine.impl.db.DbSqlSession - SQL: create table ACT_RE_MODEL ( ID_ varchar(64) not null, REV_ integer, NAME_ varchar(255), KEY_ varchar(255), CATEGORY_ varchar(255), CREATE_TIME_ timestamp(3) null, LAST_UPDATE_TIME_ timestamp(3) null, VERSION_ integer, META_INFO_ varchar(4000), DEPLOYMENT_ID_ varchar(64), EDITOR_SOURCE_VALUE_ID_ varchar(64), EDITOR_SOURCE_EXTRA_VALUE_ID_ varchar(64), TENANT_ID_ varchar(255) default '', primary key (ID_) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin
6,使用java api 执行流程。
先贴出代码:
package com.maven.web.controller;import java.io.File;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import org.activiti.engine.HistoryService;import org.activiti.engine.IdentityService;import org.activiti.engine.ManagementService;import org.activiti.engine.ProcessEngine;import org.activiti.engine.ProcessEngineConfiguration;import org.activiti.engine.RepositoryService;import org.activiti.engine.RuntimeService;import org.activiti.engine.TaskService;import org.activiti.engine.repository.ProcessDefinition;import org.activiti.engine.runtime.ProcessInstance;import org.activiti.engine.task.Task;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.ResponseBody;import org.springframework.web.bind.annotation.RestController;import com.maven.web.common.ErrorCode;import com.maven.web.common.ListResult;import com.maven.web.common.Result;import com.maven.web.util.Constant;@RestControllerpublic class ActivitiController {public static final Logger logger = LoggerFactory.getLogger(ActivitiController.class);@Autowiredprivate ProcessEngineConfiguration processEngineConfiguration;@Autowiredprivate ProcessEngine processEngine;@Autowiredprivate RepositoryService repositoryService;@Autowiredprivate RuntimeService runtimeService;@Autowiredprivate TaskService taskService;@Autowiredprivate HistoryService historyService;@Autowiredprivate ManagementService managementService;@Autowiredprivate IdentityService identityService;/** * 流程发布 * 可以发布多次,会取最新版本的流程 * @param flowName 需要发布的流程名称 * @return 状态码 */@RequestMapping(value="/process/release",method=RequestMethod.GET)public Result release(String flowName){logger.info("-> 开始发布流程:{}。",flowName);repositoryService.createDeployment() .addClasspathResource(Constant.DIAGRAMS.concat(File.separator).concat(flowName).concat(Constant.BPMN)) .deploy();logger.info("-> 流程:{}已成功发布。",flowName);Result r = new Result(ErrorCode.SUCCESS);return r;}/** * 查看所有已发布流程(不管流程是否已启动) * @return 已发布流程集合 */@RequestMapping(value="/process/release/list",method=RequestMethod.GET)public ListResult<Map<String,Object>> releaseList(){logger.info("-> 查询所有已发布的流程。");List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().list();List<Map<String,Object>> maps = new ArrayList<Map<String,Object>>();for (ProcessDefinition pd : list) {Map<String,Object> map = new HashMap<String,Object>();map.put("id", pd.getId());map.put("key", pd.getKey());maps.add(map);}logger.info("-> 查询结果:{}。",list);ListResult<Map<String,Object>> r = new ListResult<Map<String,Object>>();r.setCode(ErrorCode.SUCCESS);r.setData(maps);return r;}/** * 流程启动,单个流程可以启动多个流程实例 * @param flowName 需要启动的流程名称 * @return 状态码 */@RequestMapping(value="/process/start",method=RequestMethod.GET)public Result start(String flowName){logger.info("-> 开始启动流程:{}。",flowName);/* * 还可以传递参数,很多时候某个流程节点并没有写定具体的参数, * 比如员工提交审批申请时才手动勾选需要审批的人员。 */runtimeService.startProcessInstanceByKey(flowName);logger.info("-> 流程:{}已成功启动。",flowName);Result r = new Result(ErrorCode.SUCCESS);return r;}/** * 查看所有已启动的流程实例 * @return 流程实例集合 */@RequestMapping(value="/process/start/list",method=RequestMethod.GET)public ListResult<Map<String,Object>> startList(){logger.info("-> 开始查询所有已启动的流程实例。");/* * 还可以传递参数,很多时候某个流程节点并没有写定具体的参数, * 比如员工提交审批申请时才手动勾选需要审批的人员。 */List<ProcessInstance> list = runtimeService.createProcessInstanceQuery().list();List<Map<String,Object>> maps = new ArrayList<Map<String,Object>>();for (ProcessInstance pi : list) {Map<String,Object> map = new HashMap<String,Object>();map.put("id", pi.getId());maps.add(map);}logger.info("-> 查询结果:{}。",list);ListResult<Map<String,Object>> r = new ListResult<Map<String,Object>>();r.setCode(ErrorCode.SUCCESS);r.setData(maps);return r;}/** * 查看个人待完成的任务 * @param 用户名 * @return 用户待完成任务集合 */@RequestMapping(value="/user/task/undo",method=RequestMethod.GET)@ResponseBodypublic ListResult<Map<String,Object>> userTaskUndo(String userName){logger.info("-> 开始查询用户:{}待完成的任务。",userName);// 还可以查看用户已提交的任务,已完成的任务等等。List<Task> list = taskService.createTaskQuery().taskDefinitionKey(userName).list();List<Map<String,Object>> maps = new ArrayList<Map<String,Object>>();for (Task task : list) {Map<String,Object> map = new HashMap<String,Object>();map.put("id", task.getId());map.put("name", task.getName());maps.add(map);}logger.info("-> 查询结果:{}。",list);ListResult<Map<String,Object>> r = new ListResult<Map<String,Object>>();r.setCode(ErrorCode.SUCCESS);r.setData(maps);return r;}/** * 任务完成 * @param 任务ID * @return 状态码 */@RequestMapping(value="/task/complete",method=RequestMethod.GET)public Result taskComplete(String taskId){logger.info("-> 任务:{}审批完成。",taskId);taskService.complete(taskId);logger.info("-> 操作成功。");Result r = new Result(ErrorCode.SUCCESS);return r;}}
下面具体来看各个接口实现:
6.1,上面建好了任务流程,需要发布到activiti引擎中。发布意味着引擎会把BPMN2.0 xml解析成可以执行的东西,“发布包”中的所有流程定义都会添加到数据库中。
http://localhost:8088/spring-web/process/release?flowName=my-process
发布成功后数据库对应表act_re_procdef会添加一条数据:
6.2,发布流程到activiti引擎后,可以启动流程。单个流程可以启动多个实例(也就是可以提出多次同样的申请)。
http://localhost:8088/spring-web/process/start?flowName=my-process
这里执行两次,可以查看数据act_ru_task,主管审批任务就有两条:
6.3,流程启动后第一个节点就是主管审批,主管用户可以查看自己需要完成的任务。
http://localhost:8088/spring-web/user/task/undo?userName=usertask1
6.4,完成任务。
http://localhost:8088/spring-web/task/complete?taskId=12
再次查看任务数据表act_ru_task:
任务流程已经到了下一个节点,经理审批。
6.5,实际上各个节点的审批人可以动态设置,允许使用表达式 ,具体可以查看官网提供的api 文档:activiti api使用
7,测试过程中遇到的问题。
(1) 开始使用版本5.19.0,在执行查询操作时会报sql语句错误,默认会有排序,语句重复:
【order by order by ** asc】,更换版本为5.22.0后查询正常。
(2) 调用activiti api 查询数据直接返回会抛异常,无法正常解析成Json数据。
这是因为返回的结果,例如List<ProcessInstance>,其中的ProcessInstance是一个接口,需要在返回结果中调用get方法获取属性值封装后返回。
- activiti bpmnModel的使用
- activiti的使用注意事项
- activiti工作流的使用
- activiti 的使用
- Activiti 监听器的配置使用
- Activiti工作流引擎的使用
- Activiti工作流引擎使用(Activiti的乱码问题)
- activiti 使用
- activiti使用
- activiti的使用以及简单的操作
- activiti:initiator的作用及其使用
- activiti 网页流程设计器 的使用
- 流程引擎activiti的使用心得
- Activiti 工作流引擎的初步使用
- Activiti工作流框架学习(二)——使用Activiti提供的API完成流程操作
- Activiti工作流框架学习(二)——使用Activiti提供的API完成流程操作
- Activiti工作流框架学习(二)——使用Activiti提供的API完成流程操作
- Activiti工作流框架学习(二)——使用Activiti提供的API完成流程操作
- poj3253Fence Repair(哈夫曼树)
- spark Job执行流程
- php表单处理基本方法
- elementary os中WPS Office的安装方法
- 真·板子
- activiti 的使用
- 数据结构
- 关于python的计算方式
- Nexus3搭建Maven私有库(一)
- 13读书笔记之研究碎片
- 怎样让你的网页更快的被搜索到
- 699 - The Falling Leaves
- map and pair (1)
- Android高效加载大图、多图解决方案,有效避免程序OOM