一。activiti简介
Activiti项目是一项新的基于Apache许可的开源BPM平台,从基础开始构建,旨在提供支持新的BPMN 2.0标准,包括支持对象管理组(OMG),面对新技术的机遇,诸如互操作性和云架构,提供技术实现。
创始人Tom Baeyens是JBoss jBPM的项目架构师,以及另一位架构师Joram Barrez,一起加入到创建Alfresco这项首次实现Apache开源许可的BPMN 2.0引擎开发中来。
Activiti是一个独立运作和经营的开源项目品牌,并将独立于Alfresco开源ECM系统运行。 Activiti将是一种轻量级,可嵌入的BPM引擎,而且还设计适用于可扩展的云架构。 Activiti将提供宽松的Apache许可2.0,以便这个项目可以广泛被使用,同时促进Activiti BPM引擎和BPMN 2.0的匹配,该项目现正由OMG通过标准审定。 加入Alfresco Activiti项目的是VMware的SpringSource分支,Alfresco的计划把该项目提交给Apache基础架构,希望吸引更多方面的BPM专家和促进BPM的创新。
Activiti框架用于定义业务逻辑相关的流程 ,开启相关流程实例,流程变量控制流程走向,用户及组完成流程任务
Activiti流程定义使用bpmn2.0标准 该标准通过xml定义了所有业务流程相关的节点 比如 开始 结束 用户任务 排他路由 并行路由等 由于编写xml比较困难 activiti提供了eclipse相关插件 通过绘图方式来生成xml
相关网站:官网:https://www.activiti.org/
用户向导:https://www.activiti.org/userguide
中文用户向导:http://www.mossle.com/docs/activiti/index.html
eclipse插件安装(参考用户向导https://www.activiti.org/userguide/#activitiDesigner)
eclipse点击菜单 Help → Install New Software
输入以下信息:
Name:Activiti BPMN 2.0 designer
Location:http://activiti.org/designer/update/
点击ok 后选择同意协议后安装完成即可 新建任意项目 新建diagram文件 操作如下gif动态图
相关概念解释
- 流程引擎:流程定义和流程实例相关的入口api 流程引擎可以生成数据库的存储表 通过产生不同的service来操作不同的流程
- repositoryService 用于发布流程定义
- taskService用于操作任务 (任务查询,任务完成,设置流程变量)
- runtimeService可以用于操作流程实例 (运行流程,设置流程变量)
- historyService可以查看历史流程
- IdentityService 操作用户和组信息
以下代码就是流程引擎以及各服务的相关代码
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); RuntimeService runtimeService = processEngine.getRuntimeService(); RepositoryService repositoryService = processEngine.getRepositoryService(); TaskService taskService = processEngine.getTaskService(); ManagementService managementService = processEngine.getManagementService(); IdentityService identityService = processEngine.getIdentityService(); HistoryService historyService = processEngine.getHistoryService(); FormService formService = processEngine.getFormService(); DynamicBpmnService dynamicBpmnService = processEngine.getDynamicBpmnService();
- 流程定义:将bpmn相关的文件和图片发布到流程数据库中 生成对应的流程信息 流程经过哪些任务 指派给哪个用户完成任务
- 流程实例 : 每个定义都可以产生多个流程实例 流程实例所有的任务需要指派的用户去完成后才能走向下一个节点,存在多个分支的用户节点需要通过流程变量值来判断流程走向
开始节点 所有的流程图都需要有个开始节点
结束节点 所有流程图都必须有个结束节点
任务节点 需要用户处理的任务 比如审批就是需要人工去完成的一个任务 就需要定义任务节点 该节点被普遍
使用
顺序线 上一个节点完成后 需要走到的下一个节点可以通过 顺序线连接
排他节点 流程需要分支需要通过排他节点 进行判断 如果有多个分支 最后流程只会走向其中一个分支
比如请假 天数<3天 走组长审批 3-5天 走项目经理审批 5天以上boss审批 最后请假了多少天 只会是某个人审批
具有排他性
并行节点 比如有两个分支 有可能两个分支流程都需要走 可以使用并行节点
流程变量和脚本在流程运行过程中可以定义流程变量 分为全局变量和临时变量 全局变量在整个流程中可用 局部变量在当前节点定义只能在当前节点中使用 一般比如请假 提交请假的天数 请假的时间 可以在请假任务完成后 添加全局变量 还比如如果有个排他节点 可以
通过请假的天数判断走哪个审批流程
所有定义的变量可以是普通的数据类型也可以是对象 在流程定义时可以使用uel表达式来获取流程变量的值
比如 ${userDay} 可以获取天数 ,判断 ${userDay<3} 也可以调用对象方法 比如 ${user.getUserDay()}
表达式可以参考 https://www.activiti.org/userguide/#apiExpressions
流程变量参考 https://www.activiti.org/userguide/#apiVariables
比如官网图 定义排他节点(input==1走上面流程 input==2走中间流程 input==3走下面流程) 流程开始时只需要添加一个键值对的流程变量 input=某个值 就能决定走哪条线路
二。activiti配置
ProcessEngines.getDefaultProcessEngine()会在第一次调用时 初始化并创建一个流程引擎,以后再调用就会返回相同的流程引擎。 使用对应的方法可以创建和关闭所有流程引擎:ProcessEngines.init() 和 ProcessEngines.destroy()。
ProcessEngines会扫描所有activiti.cfg.xml 和 activiti-context.xml 文件。 对于activiti.cfg.xml文件,流程引擎会使用Activiti的经典方式构建: ProcessEngineConfiguration.createProcessEngineConfigurationFromInputStream(inputStream).buildProcessEngine(). 对于activiti-context.xml文件,流程引擎会使用Spring方法构建:先创建一个Spring的环境, 然后通过环境获得流程引擎。
所有流程相关的数据都保存在数据库中 需要先通过流程引擎配置生成数据库的表 具体的实现参考官方用户向导
(https://www.activiti.org/userguide/#_configuration)
类路径下添加 activiti.cfg.xml
<beans xmlns="http://www.springframework.org/schema/beans" 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"> <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration"> <property name="jdbcUrl" value="jdbc:oracle:thin:@localhost:1521:orcl" /> <property name="jdbcDriver" value="oracle.jdbc.driver.OracleDriver" /> <property name="jdbcUsername" value="ac" /> <property name="jdbcPassword" value="ac" /> <property name="databaseSchemaUpdate" value="true" /> </bean> </beans>添加maven依赖
<dependencies> <!-- https://mvnrepository.com/artifact/org.activiti/activiti-engine --> <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-engine</artifactId> <version>5.22.0</version> </dependency> <!-- https://mvnrepository.com/artifact/com.hynnet/oracle-driver-ojdbc --> <dependency> <groupId>com.hynnet</groupId> <artifactId>oracle-driver-ojdbc</artifactId> <version>12.1.0.2</version> </dependency> </dependencies>
获取流程实例 自动创建表
package activiti; import org.activiti.engine.ProcessEngine; import org.activiti.engine.ProcessEngines; public class TestCreateDb { public static void main(String[] args) { ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); } }
运行main方法 查看数据库 发现产生了25张表
Activiti的表都以ACT_开头。 第二部分是表示表的用途的两个字母标识。 用途也和服务的API对应。
- ACT_RE_*: 'RE'表示repository。 这个前缀的表包含了流程定义和流程静态资源 (图片,规则,等等)。
- ACT_RU_*: 'RU'表示runtime。 这些运行时的表,包含流程实例,任务,变量,异步任务,等运行中的数据。 Activiti只在流程实例执行过程中保存这些数据, 在流程结束时就会删除这些记录。 这样运行时表可以一直很小速度很快。
- ACT_ID_*: 'ID'表示identity。 这些表包含身份信息,比如用户,组等等。
- ACT_HI_*: 'HI'表示history。 这些表包含历史数据,比如历史流程实例, 变量,任务等等。
- ACT_GE_*: 通用数据, 用于不同场景下。
三。activiti 实例,bpmn及常用api操作
以下通过一个流程实例显示 activiti的所有相关api操作
模拟实例 比如威客网站中某个雇主发布了一个单人悬赏的任务 此时不同的威客都可以发起投稿投标的流程 流程图如下
威客开启一个流程定义流程变量(威客用户id)威客交稿的任务当前威客通过威客id可以查询到任务 威客交稿任务
开始 用户需要传递投稿的任务编号 雇主信息 稿件信息 完成任务后 雇主选稿 选稿任务完成 需要进入排他路由 选中
和未选中通过一个流程变量来控制 如果未选中 直接发送落选邮件到威客账号 选中继续后 使用并行路由 同时开启两个流程
(发送通知邮件 ,威客提交终稿)是同时执行 互不影响 只演示前半部分 后面部分相似
bpmn的源码
<?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="inviteProcess" name="inviteProcess" isExecutable="true"> <startEvent id="startevent1" name="Start"></startEvent> <userTask id="wkInvite" name="威客交稿" activiti:assignee="${userWk}"></userTask> <sequenceFlow id="flow1" sourceRef="startevent1" targetRef="wkInvite"></sequenceFlow> <exclusiveGateway id="exclusivegateway1" name="Exclusive Gateway"></exclusiveGateway> <serviceTask id="mailtask1" name="发送落选邮件" activiti:type="mail"> <extensionElements> <activiti:field name="to"> <activiti:expression><![CDATA[${email_to}]]></activiti:expression> </activiti:field> <activiti:field name="from"> <activiti:expression><![CDATA[${email_from}]]></activiti:expression> </activiti:field> <activiti:field name="subject"> <activiti:expression><![CDATA[${email_title}]]></activiti:expression> </activiti:field> <activiti:field name="html"> <activiti:expression><![CDATA[${email_content}]]></activiti:expression> </activiti:field> <activiti:field name="charset"> <activiti:string><![CDATA[utf-8]]></activiti:string> </activiti:field> </extensionElements> </serviceTask> <endEvent id="endevent1" name="End"></endEvent> <sequenceFlow id="flow4" sourceRef="exclusivegateway1" targetRef="mailtask1"> <conditionExpression xsi:type="tFormalExpression"><![CDATA[${shortlist==0}]]></conditionExpression> </sequenceFlow> <sequenceFlow id="flow5" sourceRef="mailtask1" targetRef="endevent1"></sequenceFlow> <parallelGateway id="parallelgateway1" name="Parallel Gateway"></parallelGateway> <serviceTask id="mailtask2" name="发送中标邮件" activiti:type="mail"> <extensionElements> <activiti:field name="to"> <activiti:expression><![CDATA[${email_to}]]></activiti:expression> </activiti:field> <activiti:field name="from"> <activiti:expression><![CDATA[${email_from}]]></activiti:expression> </activiti:field> <activiti:field name="subject"> <activiti:expression><![CDATA[${email_title}]]></activiti:expression> </activiti:field> <activiti:field name="html"> <activiti:expression><![CDATA[${email_content}]]></activiti:expression> </activiti:field> <activiti:field name="charset"> <activiti:string><![CDATA[utf-8]]></activiti:string> </activiti:field> </extensionElements> </serviceTask> <sequenceFlow id="flow6" sourceRef="exclusivegateway1" targetRef="parallelgateway1"> <conditionExpression xsi:type="tFormalExpression"><![CDATA[${shortlist==1}]]></conditionExpression> </sequenceFlow> <userTask id="usertask1" name="提交最终稿件" activiti:assignee="${userWk}"></userTask> <sequenceFlow id="flow7" sourceRef="parallelgateway1" targetRef="mailtask2"></sequenceFlow> <sequenceFlow id="flow8" sourceRef="parallelgateway1" targetRef="usertask1"></sequenceFlow> <userTask id="usertask2" name="雇主确认" activiti:assignee="${employer}"></userTask> <exclusiveGateway id="exclusivegateway2" name="Exclusive Gateway"></exclusiveGateway> <sequenceFlow id="flow9" sourceRef="exclusivegateway2" targetRef="usertask1"> <conditionExpression xsi:type="tFormalExpression"><![CDATA[${ifaccept==0}]]></conditionExpression> </sequenceFlow> <sequenceFlow id="flow10" sourceRef="usertask2" targetRef="exclusivegateway2"></sequenceFlow> <sequenceFlow id="flow11" sourceRef="usertask1" targetRef="usertask2"></sequenceFlow> <userTask id="usertask3" name="威客收款" activiti:assignee="${userWk}"></userTask> <sequenceFlow id="flow12" sourceRef="exclusivegateway2" targetRef="usertask3"> <conditionExpression xsi:type="tFormalExpression"><![CDATA[${ifaccept==1}]]></conditionExpression> </sequenceFlow> <endEvent id="endevent2" name="End"></endEvent> <sequenceFlow id="flow13" sourceRef="usertask3" targetRef="endevent2"></sequenceFlow> <endEvent id="endevent3" name="End"></endEvent> <sequenceFlow id="flow14" sourceRef="mailtask2" targetRef="endevent3"></sequenceFlow> <userTask id="usertask4" name="雇主选稿" activiti:assignee="${employer}"></userTask> <sequenceFlow id="flow15" sourceRef="wkInvite" targetRef="usertask4"></sequenceFlow> <sequenceFlow id="flow16" sourceRef="usertask4" targetRef="exclusivegateway1"></sequenceFlow> </process> <bpmndi:BPMNDiagram id="BPMNDiagram_inviteProcess"> <bpmndi:BPMNPlane bpmnElement="inviteProcess" id="BPMNPlane_inviteProcess"> <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1"> <omgdc:Bounds height="35.0" width="35.0" x="0.0" y="172.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="wkInvite" id="BPMNShape_wkInvite"> <omgdc:Bounds height="55.0" width="105.0" x="60.0" y="162.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="exclusivegateway1" id="BPMNShape_exclusivegateway1"> <omgdc:Bounds height="40.0" width="40.0" x="300.0" y="169.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="mailtask1" id="BPMNShape_mailtask1"> <omgdc:Bounds height="55.0" width="105.0" x="380.0" y="216.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1"> <omgdc:Bounds height="35.0" width="35.0" x="415.0" y="380.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="parallelgateway1" id="BPMNShape_parallelgateway1"> <omgdc:Bounds height="40.0" width="40.0" x="380.0" y="110.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="mailtask2" id="BPMNShape_mailtask2"> <omgdc:Bounds height="55.0" width="105.0" x="470.0" y="56.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1"> <omgdc:Bounds height="55.0" width="105.0" x="470.0" y="135.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2"> <omgdc:Bounds height="55.0" width="105.0" x="640.0" y="135.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="exclusivegateway2" id="BPMNShape_exclusivegateway2"> <omgdc:Bounds height="40.0" width="40.0" x="672.0" y="223.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="usertask3" id="BPMNShape_usertask3"> <omgdc:Bounds height="55.0" width="105.0" x="640.0" y="300.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="endevent2" id="BPMNShape_endevent2"> <omgdc:Bounds height="35.0" width="35.0" x="675.0" y="414.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="endevent3" id="BPMNShape_endevent3"> <omgdc:Bounds height="35.0" width="35.0" x="670.0" y="66.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="usertask4" id="BPMNShape_usertask4"> <omgdc:Bounds height="55.0" width="105.0" x="180.0" y="164.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1"> <omgdi:waypoint x="35.0" y="189.0"></omgdi:waypoint> <omgdi:waypoint x="60.0" y="189.0"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4"> <omgdi:waypoint x="320.0" y="209.0"></omgdi:waypoint> <omgdi:waypoint x="320.0" y="243.0"></omgdi:waypoint> <omgdi:waypoint x="380.0" y="243.0"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="flow5" id="BPMNEdge_flow5"> <omgdi:waypoint x="432.0" y="271.0"></omgdi:waypoint> <omgdi:waypoint x="432.0" y="380.0"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="flow6" id="BPMNEdge_flow6"> <omgdi:waypoint x="320.0" y="169.0"></omgdi:waypoint> <omgdi:waypoint x="320.0" y="138.0"></omgdi:waypoint> <omgdi:waypoint x="353.0" y="138.0"></omgdi:waypoint> <omgdi:waypoint x="388.0" y="138.0"></omgdi:waypoint> <omgdi:waypoint x="388.0" y="138.0"></omgdi:waypoint> <omgdi:waypoint x="420.0" y="130.0"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="flow7" id="BPMNEdge_flow7"> <omgdi:waypoint x="400.0" y="110.0"></omgdi:waypoint> <omgdi:waypoint x="400.0" y="83.0"></omgdi:waypoint> <omgdi:waypoint x="470.0" y="83.0"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="flow8" id="BPMNEdge_flow8"> <omgdi:waypoint x="400.0" y="150.0"></omgdi:waypoint> <omgdi:waypoint x="400.0" y="162.0"></omgdi:waypoint> <omgdi:waypoint x="470.0" y="162.0"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="flow9" id="BPMNEdge_flow9"> <omgdi:waypoint x="692.0" y="223.0"></omgdi:waypoint> <omgdi:waypoint x="522.0" y="190.0"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="flow10" id="BPMNEdge_flow10"> <omgdi:waypoint x="692.0" y="190.0"></omgdi:waypoint> <omgdi:waypoint x="692.0" y="223.0"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="flow11" id="BPMNEdge_flow11"> <omgdi:waypoint x="575.0" y="162.0"></omgdi:waypoint> <omgdi:waypoint x="640.0" y="162.0"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="flow12" id="BPMNEdge_flow12"> <omgdi:waypoint x="692.0" y="263.0"></omgdi:waypoint> <omgdi:waypoint x="692.0" y="300.0"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="flow13" id="BPMNEdge_flow13"> <omgdi:waypoint x="692.0" y="355.0"></omgdi:waypoint> <omgdi:waypoint x="692.0" y="414.0"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="flow14" id="BPMNEdge_flow14"> <omgdi:waypoint x="575.0" y="83.0"></omgdi:waypoint> <omgdi:waypoint x="670.0" y="83.0"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="flow15" id="BPMNEdge_flow15"> <omgdi:waypoint x="165.0" y="189.0"></omgdi:waypoint> <omgdi:waypoint x="180.0" y="191.0"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="flow16" id="BPMNEdge_flow16"> <omgdi:waypoint x="285.0" y="191.0"></omgdi:waypoint> <omgdi:waypoint x="300.0" y="189.0"></omgdi:waypoint> </bpmndi:BPMNEdge> </bpmndi:BPMNPlane> </bpmndi:BPMNDiagram> </definitions>演示代码如下
假定流程引擎对象已经如下定义
//创建流程引擎对象 private ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
步骤1 发布流程定义
/** * 发布流程 添加发布bpmn和图片 也可以打包成 zip发布 * */ @Test public void deployProcess() { //用于发布流程资源 以及流程定义 RepositoryService repositoryService = processEngine.getRepositoryService(); Deployment deploy = repositoryService.createDeployment() .addClasspathResource("diagrams/MyProcess.bpmn") .addClasspathResource("diagrams/MyProcess.png") //.addZipInputStream(zipInputStream) 可以添加压缩包 web定义流程就可以使用这个方法上传 .name("威客单人投标流程") .deploy(); //资源文件在act_ge_bytearray表中 //流程定义在act_re_procdef表中 System.out.println("流程定义id:"+deploy.getId()); System.out.println("流程定义名称:"+deploy.getName()); System.out.println("流程定义发布时间:"+deploy.getDeploymentTime().toGMTString()); //查看发布的流程信息 查看发布的流程总和 long count = repositoryService.createDeploymentQuery().count(); System.out.println("总流程定义数:"+count); }步骤2 zs查看自己的任务编号 完成投稿任务
查看任务
/** * 运行流程 * 相同的流程被发布(id不同 _key相同)多, 每发布 一次 ACT_RE_PROCDEF 多一条数据, Version都会加1, * 根据key来启动 会启动最新版本号的流程定义 * 如果想执行旧的流程定义就可以使用id来启动 * 模拟场景 某个威客 开始向某个任务投稿 任务就开始了 */ @Test public void startProcess() { //运行流程使用runtimesErvice RuntimeService runtimeService = processEngine.getRuntimeService(); //流程变量 传入是谁启动的流程 Map map=new HashMap(); map.put("userWk", "zs"); //key就是流程图的 id (注意不是数据库里面的id 数据库里面的key是流程里开始定义的id) //流程实例数据在 ACT_RU_EXECUTION表中 //流程变量 在 ACT_RU_VARIABLE中 //用户任务在 ACT_RU_TASK中 ProcessInstance instance= runtimeService.startProcessInstanceByKey("inviteProcess",map); System.out.println("用户"+map.get("userWk")+"开启了一个投稿流程"); System.out.println("流程实例编号是:"+instance.getProcessInstanceId()); long count = runtimeService.createExecutionQuery().count(); System.out.println("总流程实例数:"+count); }
完成任务
/** * 张三完成任务 就需要交稿 定义流程变量 */ @Test public void submitTask() { //用户任务的完成 使用TaskService TaskService taskService = processEngine.getTaskService(); String taskId="20005"; Map map=new HashMap(); /** * 张三交稿数据 * **/ map.put("employer", "ls");//设置任务的雇主 map.put("taskNo", "雇主任务编号"); map.put("taskContent", "用字符串模拟"); taskService.complete(taskId, map); }
步骤3 雇主ls查看自己的任务编号 完成选稿稿任务 这里模拟shortlist==0表示没选中 进入发送邮件结束流程的步骤
需要配置邮件的smtp和用户密码信息 修改activiti.cfg.xml 添加
<property name="mailServerHost" value="smtp.126.com" /> <property name="mailServerPort" value="25" /> <property name="mailServerUsername" value="lixin1112003@126.com"></property> <property name="mailServerPassword" value="XXXXXXXXXX您的邮箱密码"></property>未选中代码
/** * 李四完成任务 就需要选稿 */ @Test public void submitTask() { //用户任务的完成 使用TaskService TaskService taskService = processEngine.getTaskService(); String taskId="20005"; Map map=new HashMap(); map.put("shortlist", 0); map.put("email_to", "973465719@qq.com"); map.put("email_from", "lixin1112003@126.com"); map.put("email_title", "973465719@qq.com"); map.put("email_content", "您对雇主任务编号"+taskService.getVariable(taskId, "taskNo")+"的投稿稿件 已经落选。。"); taskService.complete(taskId, map); }选中代码
/** * 李四完成任务 就需要选稿 */ @Test public void submitTask() { //用户任务的完成 使用TaskService TaskService taskService = processEngine.getTaskService(); String taskId="20005"; Map map=new HashMap(); map.put("shortlist", 1); map.put("email_to", "973465719@qq.com"); map.put("email_from", "lixin1112003@126.com"); map.put("email_title", "973465719@qq.com"); map.put("email_content", "您对雇主任务编号"+taskService.getVariable(taskId, "taskNo")+"的投稿稿件 已经被选中 请完成终稿。。"); taskService.complete(taskId, map); }
其他代码就不演示 具体参考https://www.activiti.org/userguide/#chapterApi
四。springboot集成activiti
集成web参考 https://www.activiti.org/userguide/#springintegration