Activiti工作流详解完整教程
- 格式:doc
- 大小:1.12 MB
- 文档页数:47
Activiti⼯作流框架学习笔记(⼆)之springboot2.0整合⼯作流Activi。
以前在⼯作当中做过不少与⼯作流Activiti有关的⼯作,当时都是spring集成activiti5.22的项⽬,现在回过头去看,其实版本已经稍微⽼了,因此,基于先前的⼯作经验,决定⽤较新版本的技术来重新梳理下以前接触过的技术。
决定⽤springboot2.0+Activiti6.0来做实践总结。
第⼀步,在springboot项⽬pom.xml⽂件引⼊相关依赖:1<!--Activiti ⼯作流-->2<dependency>3<groupId>mysql</groupId>4<artifactId>mysql-connector-java</artifactId>5<scope>5.1.35</scope>6</dependency>78<dependency>9<groupId>org.activiti</groupId>10<artifactId>activiti-spring</artifactId>11<version>6.0.0</version>12</dependency>1314<dependency>15<groupId>com.fasterxml.jackson.core</groupId>16<artifactId>jackson-core</artifactId>17<version>2.9.5</version>18</dependency>第⼆步,建⽴Activiti的配置类1 @Configuration2 public class Activiticonfig {34 /**5 * 流程实例类,启动流程时创建6 * @return7 */8 @Bean9 public ProcessEngine processEngine(){10 ProcessEngineConfiguration pro=ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration();11 pro.setJdbcDriver("com.mysql.jdbc.Driver");12 pro.setJdbcUrl("jdbc:mysql://localhost:3306/example?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=UTC&nullCatalogMeansCurrent=true");13 pro.setJdbcUsername("root");14 pro.setJdbcPassword("root");15 //避免发布的图⽚和xml中⽂出现乱码16 pro.setActivityFontName("宋体");17 pro.setLabelFontName("宋体");18 pro.setAnnotationFontName("宋体");19 pro.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);20 return pro.buildProcessEngine();21 }222324 /**25 * 仓库服务类,⽤于管理bpmn⽂件与流程图⽚26 * @return27 */28 @Bean29 public RepositoryService repositoryService(){30 return processEngine().getRepositoryService();31 }3233 /**34 * 流程运⾏服务类,⽤于获取流程执⾏相关信息35 * @return36 */37 @Bean38 public RuntimeService runtimeService(){39 return processEngine().getRuntimeService();40 }4142 /**43 * 任务服务类,⽤户获取任务信息44 * @return45 */46 @Bean47 public TaskService taskService(){48 return processEngine().getTaskService();49 }505152 /**53 * 获取正在运⾏或已经完成的流程实例历史信息54 * @return55 */56 @Bean57 public HistoryService historyService(){58 return processEngine().getHistoryService();59 }6061 /**62 * 流程引擎的管理与维护63 * @return64 */65 @Bean66 public ManagementService managementService(){67 return processEngine().getManagementService();68 }6970 /**71 * 创建、更新、删除,查询群组和⽤户72 * @return73 */74 @Bean75 public IdentityService identityService(){76 return processEngine().getIdentityService();77 }7879 }在springboot⼯程⾥简单加完这些配置后,启动项⽬,原以为可以正常⽣成Activi6.0⼯作流⾃带的28张表,但这时出现了⼀堆错误:### Error querying database. Cause: java.sql.SQLSyntaxErrorException: Table 'example.act_ge_property' doesn't exist ### The error may exist in org/activiti/db/mapping/entity/Property.xml### The error may involve org.activiti.engine.impl.persistence.entity.PropertyEntityImpl.selectProperty-Inline### The error occurred while setting parameters### SQL: select * from ACT_GE_PROPERTY where NAME_ = ?### Cause: java.sql.SQLSyntaxErrorException: Table 'example.act_ge_property' doesn't exist出现这种问题主要是因为MySql的版本问题,在连接mysql的url后边加⼀个&nullCatalogMeansCurrent=true即可解决。
activiti工作流引擎的原理
Activiti工作流引擎是一个开源的业务流程引擎,它是基于Java的BPMN 2.0规范来实现的。
在工作流引擎实施的过程中,可以实现业务流程的定义、执行、协作以及监控。
Activiti工作流引擎的原理很简单,一般分为以下几个步骤:(1)设计和开发工作流:将业务流程抽象成工作流设计,编写XML描述工作流的XML文件,例如:用户创建一个新的工作流,并定义工作流流程的细节;
(2)创建工作流实例:在Activiti工作流引擎中,可以根据设计的工作流,创建一个新的工作流实例。
在创建新实例时,可以设置实例的参数,指定每一步由谁审批或执行,以及审批人之间的关系;
(3)执行工作流:在工作流实例创建完成之后,可以使用Activiti工作流引擎执行工作流,包括开始工作流实例,按照设计的流程执行各个节点,以及处理异常和结束实例等;
(4)监控工作流:Activiti工作流引擎可以监控工作流执行情况,例如,当前处于哪个步骤,执行者接收到任务,有哪些未被处理的任务等;
(5)管理工作流:Activiti工作流引擎提供了一些管理工作流实例的功能,例如,可以暂停工作流实例,可以激活工作流实例,可以更新工作流实例的参数,可以重新执行工作流实例;
(6)报表:Activiti工作流引擎可以根据实例执行情况,生成各类报表,例如,可以生成实例的执行轨迹,可以列出实例每一步的
执行者,未处理的任务,执行者之间的耗时和完成的实例等。
activiti工作流原理Activiti是一个基于Java的开源工作流引擎,旨在提供一种简单易用的方式来构建和管理工作流程。
其核心原理包括流程定义、流程实例和流程任务。
流程定义指的是以BPMN(Business Process Model and Notation)标准为基础,定义流程的各个环节、参与者、活动和交互。
这个过程涉及到流程的设计、建模和配置,可以使用Activiti提供的可视化工具或者使用代码进行定义。
流程定义中包含了流程的起始节点、流程变量、路由条件等信息。
流程实例是流程定义的具体执行过程。
当一个流程被启动时,会生成一个对应的流程实例。
流程实例会根据流程定义中的逻辑进行流转,经过不同的节点和活动,直到流程结束。
一个流程实例通常与一个业务实例相关联,用于描述该业务实例的状态和进程。
流程任务是流程实例中的可执行操作。
在流程执行过程中,会根据流程定义中的设置,生成相应的任务并分配给相关参与者。
任务包含了需要执行的具体工作内容和操作,可以是人工任务或者自动任务。
流程任务通常包括审批、申请、审核等功能,可以通过Activiti提供的任务管理接口进行操作。
Activiti通过引擎管理流程定义、流程实例和流程任务。
引擎负责解析流程定义文件,根据定义生成流程实例,并监听实例执行过程中的各种事件。
引擎还负责任务的分配和调度,以及流程的监控和控制。
通过Activiti的API和服务接口,可以方便地与引擎进行交互,并实现对工作流的管理和操作。
总之,Activiti工作流的原理包括流程定义、流程实例和流程任务的管理与执行。
通过定义流程的各个环节和参与者,以及任务的分配和调度,实现了工作流程的自动化和可控化。
这为企业提供了一种高效、灵活的方式来管理和优化业务流程。
activity工作流详解# Activity工作流在学生社团活动组织中的详解。
一、啥是Activity工作流呀?Activity工作流就像是一个活动的“指挥棒”,它能帮咱们把一个复杂的活动安排得明明白白,让每一步都有条不紊地进行。
比如说咱们社团要举办一场校园音乐节,从前期的策划、场地预订、宣传推广,到活动当天的现场布置、节目表演,再到活动结束后的总结反馈,这一系列的事儿就可以通过Activity工作流来管理。
它能清楚地告诉咱们每一步该做啥,谁来做,啥时候做,就像给活动画了一张清晰的“路线图”。
二、Activity工作流有啥好处呢?# (一)提高效率。
以前咱们组织活动,可能会出现手忙脚乱的情况,一会儿忘了这个事儿,一会儿又耽误了那个事儿。
有了Activity工作流,就像有个小助手在旁边提醒,每个环节都按计划推进,效率自然就提高啦。
就拿校园音乐节来说,宣传组按照工作流的安排,准时把海报贴出去,把宣传信息发出去,就不会出现活动都快开始了,还有很多同学不知道这回事儿的尴尬情况。
# (二)明确分工。
在活动组织中,大家的分工很重要。
Activity工作流能把每个任务分配得清清楚楚,让每个人都知道自己该干啥。
比如在音乐节筹备中,有的同学负责联系演出嘉宾,有的同学负责准备音响设备,大家各司其职,就不会出现互相扯皮或者都不管的情况啦。
# (三)便于跟踪和调整。
活动过程中,有时候会出现一些意外情况。
Activity工作流可以让咱们随时了解活动的进展,看看哪个环节出了问题,然后及时调整。
比如说音乐节当天突然下雨了,咱们可以根据工作流快速安排人员去搭建雨棚,调整活动流程,让活动能继续顺利进行。
三、Activity工作流一般都有哪些环节呢?# (一)活动策划。
这是活动的第一步,就像盖房子要先画图纸一样。
咱们得确定活动的主题、目标、时间、地点、参与人员等等。
比如说校园音乐节,咱们要确定是流行音乐为主还是古典音乐为主,是面向全校学生还是特定的几个学院,活动是在周末还是工作日,在学校的哪个场地举办等等。
activiti流程开发指南•一、BPMN•二、activiti主要接口•三、如何实现一个业务流程•四、如何管理所有流程与实例•五、开发流程•六、api一、BPMN1. 什么是BPMN首先BPMN规范是由标准组织BPMI发布的.BPMN 1.0规范发布于2004年5月。
此规范展示了BPMI组织两年多的努力成果。
BPMN的主要目标就是要提供被所有业务用户理解的一套标记语言,包括业务分析者、软件开发者以及业务管理者与监察者。
BPMN还将支持生成可执行的BPEL4WS语言。
所以,BPMN在业务流程设计与流程实现之间搭建了一条标准化的桥梁。
BPMN定义了业务流程图,其基于流程图技术,同时为创建业务流程操作的图形化模型进行了裁减。
业务流程的模型就是图形化对象的网图,包括活动(也可以说工作)和定义操作顺序的流控制。
2. BPMN基础业务流程图由一系列的图形化元素组成。
这些元素简化了模型的开发,且业务分析者看上去非常熟悉。
这些元素每个都有各自的特性,且与大多数的建模器类似。
比如,活动是矩形,条件是菱形。
应该强调的是:开发BPMN的动力就是为了在创建业务流程模型时提供一个简单的机制,同时又能够处理来自业务流程的复杂性。
要处理这两个矛盾的需求的方法就是将标记的图形化方面组织分类为特定的类别。
这里提供标记类别中的一小部分,以便业务流程图的读者可以简单地识别出元素的基本类型从而理解图形。
以下是四种基本的类型:1)流对象2)连接对象3)泳道4)人工信息BPMN2.0概要:/workclass/201206272.asp二、activiti主要接口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();ProcessEngines.getDefaultProcessEngine()会在第一次调用时初始化并创建一个流程引擎,以后再调用就会返回相同的流程引擎。
《Activiti6.0⼯作流引擎深度解析与实战》笔记1.1 课程导学--- 什么是⼯作流引擎?是⽤来驱动业务按照流程图逐步流转的核⼼框架。
--- 为什么学习⼯作流引擎?早期:企业OA、CRM、流程审批现在:电商购物、⾦融出⾏、中台⽀撑--- Activiti6.0流程引擎配置--- 核⼼API--- 数据模型设计--- BPMN2.0规范--- BPMN2.0元素2.1 本章概述⼯作流⼊门:⼯作流介绍、⼯作流技术选型、Activiti6.0快速体验。
2.2 ⼯作流介绍⼯作流是什么?为什么学习⼯作流?如何去学习⼯作流?1、审批业务场景(如请假,有⼀系列步骤)2、审批流程模型化(抽象出⼀系列流程图模型)“开始节点”(开始StartEvent)->填写审批信息的“⽤户节点”->通过“流程判断”(排他⽹关Exclusive Gateway)可以流转到“主管审批”(任务UserTask)->...->“结束节点”(结束EndEvent)3、常见的⽹上购物流程4、购物⼯作流程模型化有3个参与者,“电商购物流程”是泳池Pool,“仓储物流”等是泳道Line,“检验库存”是服务任务ServiceTask(服务任务是指不是由⼈⼯操作,⽽是由系统⾃动完成实现的逻辑)。
5、⼯作流是什么6、为什么需要⼯作流2.3 ⼯作流引擎技术选型2.4 Activiti6.0快速体验--部署环境介绍默认的⽤户名和密码是:admin和test2.5 Activiti6.0快速体验--部署环境实操win10下打开Cygwin,进⾏如下操作:1、curl -s "http://get.sdkman.io" | bash报错:Looking for a previous installation of SDKMAN...Looking for unzip...Looking for zip...Not found.Please install zip on your system using your favourite package manager.参考:https:///IOIO_/article/details/84946257解决⽅法是重新点击cygwin的安装包,把zip的package安装⼀遍,重启cygwin,再输⼊⼀遍这个命令即可。
activity 工作流详细介绍在软件开发中,很多应用需要处理一批活动,如订单的处理、审批流程、工作流等。
这时候,activity 工作流就成为了一个有效的工具。
它可以协调并管理大规模复杂的业务流程,能够帮助我们更快、更高效地处理各种业务。
本文将详细介绍 activity 工作流的工作原理和实现步骤。
步骤 1:创建 activity 工作流创建 activity 工作流需要借助 eclipse 等开发工具。
首先需要选择 activity 工作流项目的类型,然后创建 activity 文件。
接下来,需要添加 activity 的命令并进行流程控制的定义。
步骤 2:定义活动活动定义是工作流程设计的基本构建块,决定了最初的流程实现。
活动定义包括:名称、类型和相关事件。
在定义活动时,需要明确该活动的任务类型,例如:人工任务、服务任务和自动任务。
同时,还需要指定是否是并行的活动,以及是否会有分支和合并情况的出现。
步骤 3:定义事件在 activity 工作流中,事件是触发活动执行的关键。
事件定义包括:开始、中止、异常、结束等。
要使 activity 工作流更清晰、可维护,必须准确定义这些事件。
步骤 4:定义流程变量流程变量是 activity 工作流中的一个重要元素。
通过流程变量的设置,可以在活动定义阶段确定流程的方向,以及在后续的流程中激活相关的活动。
流程变量可以定义为整型、字符型、日期型等多种数据类型,使活动之间能够插入适当的逻辑和自定义规则。
步骤 5:定义流程流转流程流转是 activity 工作流的核心,也是设计工作中最具挑战性的部分。
在定义流程流转过程中,需要考虑各个活动的关联关系、优先级、策略等。
通过流程流转的设计,可以使整个工作流程更加完善,能够更有效地支持业务过程。
步骤 6:测试工作流工作流的开发完毕后,需要进行测试,以验证流程的行为和逻辑是否符合预期。
在测试过程中,需要进行全面的测试,覆盖各种场景和异常情况,确保 activity 工作流的可用性和可靠性。
activiti用法Activiti是一个基于Java的开源工作流引擎,它提供了完整的工作流程概念和一套完善的管理工具,包括典型的BPMN 2.0图形建模,在业务处理和应用开发中有着广泛的应用。
以下是使用Activiti的详细步骤:1.安装和配置Activiti首先,需要将Activiti工作流引擎下载并且解压缩,然后在应用程序中添加相关依赖。
在Spring框架中集成Activiti,只需要在Spring配置文件中添加Activiti相应的XML配置即可。
2.设计和部署应用程序在Activiti中,首先需要设计和构建工作流流程,通过Activiti Designer可以轻松地进行BPMN 2.0流程图的设计。
设计好后,将其导出为XML文件并部署到Activiti Engine中。
在Activiti中可以通过REST API来部署工作流程。
另外,也可以在命令行中执行相关的命令来部署工作流程。
3.使用Activiti API开发可以在应用程序中通过Activiti API来访问Activiti Engine提供的相关操作。
首先,需要创建流程引擎,之后可以使用它来访问Activiti工作流引擎。
然后,可以使用Activiti的API来启动流程实例、查询任务、完成任务等操作,在具体实现中,需要使用Activiti提供的Java代码段来完成相应的工作。
4.监控和管理在Activiti中,可以使用Activiti Explorer或者Activiti Admin应用程序来监控和管理工作流流程。
可以使用Activiti Explorer来查看/管理实例、任务、用户、组等信息,也可以在Activiti Admin中进行高级的调优和监控操作。
5.测试和优化在完成Activiti的开发之后,需要进行全面的测试和优化。
可以使用Junit来进行单元测试,使用性能测试工具来检测系统在高负载条件下的性能表现等。
可以通过具体的优化方案来提高Activiti系统的性能和稳定性,例如使用缓存、对数据库进行优化等方法。
Activiti⼯作流框架中的任务调度!⼯作流框架中的任务流程元素详解,使⽤监听器监听任务执⾏任务⽤户任务描述⽤户任务⽤来设置必须由⼈员完成的⼯作当流程执⾏到⽤户任务,会创建⼀个新任务,并把这个新任务加⼊到分配⼈或群组的任务列表中图形标记⽤户任务显⽰成⼀个普通任务(圆⾓矩形),左上⾓有⼀个⼩⽤户图标XML内容XML中的⽤户任务定义:id属性是必须的,name属性是可选的:<userTask id="theTask" name="Important task" />⽤户任务可以设置描述,添加documentation元素可以定义描述:<userTask id="theTask" name="Schedule meeting" ><documentation>Schedule an engineering meeting for next week with the new hire.</documentation>描述⽂本可以通过标准的java⽅法来获取:task.getDescription()持续时间任务可以⽤⼀个字段来描述任务的持续时间可以使⽤查询API来对持续时间进⾏搜索,根据在时间之前或之后进⾏搜索Activiti提供了⼀个节点扩展,在任务定义中设置⼀个表达式,这样在任务创建时就可以设置初始持续时间表达式应该是:java.util.Datejava.util.String(ISO8601格式),ISO8601持续时间(⽐如PT50M)null在流程中使⽤上述格式输⼊⽇期,或在前⼀个服务任务中计算⼀个时间.这⾥使⽤了持续时间,持续时间会基于当前时间进⾏计算,再通过给定的时间段累加: 使⽤"PT30M"作为持续时间,任务就会从现在开始持续30分钟<userTask id="theTask" name="Important task" activiti:dueDate="${dateVariable}"/>任务的持续时间也可以通过TaskService修改,或在TaskListener中通过传⼊的DelegateTask参数修改⽤户分配⽤户任务可以直接分配给⼀个⽤户,通过humanPerformer元素定义humanPerformer定义需要⼀个resourceAssignmentExpression来实际定义⽤户.⽬前只⽀持formalExpressions<process ... >...<userTask id='theTask' name='important task' ><humanPerformer><resourceAssignmentExpression><formalExpression>kermit</formalExpression></resourceAssignmentExpression></humanPerformer></userTask>只有⼀个⽤户可以作为任务的执⾏者分配⽤户在activiti中,⽤户叫做执⾏者拥有执⾏者的⽤户不会出现在其他⼈的任务列表中,只能出现执⾏者的个⼈任务列表中直接分配给⽤户的任务可以通过TaskService获取:List<Task> tasks = taskService.createTaskQuery().taskAssignee("kermit").list();任务也可以加⼊到⼈员的候选任务列表中.需要使⽤potentialOwner元素⽤法和humanPerformer元素类似,需要指定表达式中的每个项⽬是⼈员还是群组<process ... >...<userTask id='theTask' name='important task' ><potentialOwner><resourceAssignmentExpression><formalExpression>user(kermit), group(management)</formalExpression></resourceAssignmentExpression></potentialOwner></userTask>使⽤potentialOwner元素定义的任务可以通过TaskService获取:List<Task> tasks = taskService.createTaskQuery().taskCandidateUser("kermit");这会获取所有kermit为候选⼈的任务,表达式中包含user(kermit).这也会获得所有分配包含kermit这个成员的群组(⽐如,group(management),前提是kermit是这个组的成员,并且使⽤了activiti的账号组件).⽤户所在的群组是在运⾏阶段获取的, 它们可以通过IdentityService进⾏管理如果没有显式指定设置的是⽤户还是群组,引擎会默认当做群组处理下⾯的设置与使⽤group(accountancy)⼀样:<formalExpression>accountancy</formalExpression>Activiti对任务分配的扩展当分配不复杂时,⽤户和组的设置⾮常⿇烦.为避免复杂性,可以使⽤⽤户任务的⾃定义扩展assignee属性: 直接把⽤户任务分配给指定⽤户(和使⽤humanPerformer 效果完全⼀样)<userTask id="theTask" name="my task" activiti:assignee="kermit" />candidateUsers属性: 为任务设置候选⼈(和使⽤potentialOwner效果完全⼀样,不需要像使⽤potentialOwner通过user(kermit)声明,这个属性只能⽤于⼈员)<userTask id="theTask" name="my task" activiti:candidateUsers="kermit, gonzo" />candidateGroups属性: 为任务设置候选组(和使⽤potentialOwner效果完全⼀样,不需要像使⽤potentialOwner通过group(management)声明,这个属性只能⽤于群组)<userTask id="theTask" name="my task" activiti:candidateGroups="management, accountancy" />candidateUsers和candidateGroups可以同时设置在同⼀个⽤户任务中Activiti中虽然有账号管理组件和IdentityService ,账号组件不会检测设置的⽤户是否存在. Activiti允许与其他已存的账户管理⽅案集成使⽤创建事件的任务监听器来实现⾃定义的分配逻辑:<userTask id="task1" name="My task" ><extensionElements><activiti:taskListener event="create" class="org.activiti.MyAssignmentHandler" /></extensionElements></userTask>DelegateTask会传递给TaskListener的实现,通过它可以设置执⾏⼈,候选⼈和候选组public class MyAssignmentHandler implements TaskListener {public void notify(DelegateTask delegateTask) {// Execute custom identity lookups here// and then for example call following methods:delegateTask.setAssignee("kermit");delegateTask.addCandidateUser("fozzie");delegateTask.addCandidateGroup("management");...}}使⽤spring时,使⽤表达式把任务监听器设置为spring代理的bean,让这个监听器监听任务的创建事件⽰例:执⾏者会通过调⽤ldapService这个spring bean的findManagerOfEmployee⽅法获得.流程变量emp会作为参数传递给bean<userTask id="task" name="My Task" activiti:assignee="${ldapService.findManagerForEmployee(emp)}"/>可以⽤来设置候选⼈和候选组:<userTask id="task" name="My Task" activiti:candidateUsers="${ldapService.findAllSales()}"/>⽅法返回类型只能为String(候选⼈) 或Collection < String >(候选组):public class FakeLdapService {public String findManagerForEmployee(String employee) {return "Kermit The Frog";}public List<String> findAllSales() {return Arrays.asList("kermit", "gonzo", "fozzie");}}脚本任务描述脚本任务是⼀个⾃动节点当流程到达脚本任务,会执⾏对应的脚本图形标记脚本任务显⽰为标准BPMN 2.0任务(圆⾓矩形),左上⾓有⼀个脚本⼩图标XML内容脚本任务定义需要指定script和scriptFormat<scriptTask id="theScriptTask" name="Execute script" scriptFormat="groovy"><script>sum = 0for ( i in inputArray ) {sum += i}</script></scriptTask>scriptFormat的值必须兼容JSR-223(java平台的脚本语⾔).默认Javascript会包含在JDK中,不需要额外的依赖.如果要使⽤其他的脚本引擎,必须要是JSR-223引擎兼容的.还需要把对应的jar添加到classpath下, 并使⽤合适的名称:activiti单元测试经常使⽤groovygroovy脚本引擎放在groovy-all.jar中,在2.0版本之前,脚本引擎是groovy jar的⼀部分.使⽤需要添加依赖:<dependency><groupId>org.codehaus.groovy</groupId><artifactId>groovy-all</artifactId><version>2.x.x<version></dependency>脚本变量到达脚本任务的流程可以访问的所有流程变量,都可以在脚本中使⽤<script>sum = 0for ( i in inputArray ) {sum += i}</script>也可以在脚本中设置流程变量,直接调⽤execution.setVariable("variableName", variableValue) 默认,不会⾃动保存变量(activiti 5.12之前) 可以在脚本中⾃动保存任何变量,只要把scriptTask的autoStoreVariables属性设置为true 最佳实践是不要使⽤,⽽是显式调⽤execution.setVariable()<scriptTask id="script" scriptFormat="JavaScript" activiti:autoStoreVariables="false">参数默认为false: 如果没有为脚本任务定义设置参数,所有声明的变量将只存在于脚本执⾏的阶段在脚本中设置变量: 这些命名已经被占⽤,不能⽤作变量名- out, out:print, lang:import, context, elcontext.<script>def scriptVar = "test123"execution.setVariable("myVar", scriptVar)</script>脚本结果脚本任务的返回值可以通过制定流程变量的名称,分配给已存在或者⼀个新流程变量,需要使⽤脚本任务定义的'activiti:resultVariable'属性任何已存在的流程变量都会被脚本执⾏的结果覆盖如果没有指定返回的变量名,脚本的返回值会被忽略<scriptTask id="theScriptTask" name="Execute script" scriptFormat="juel" activiti:resultVariable="myVar"><script>#{echo}</script></scriptTask>脚本的结果-表达式 #{echo} 的值会在脚本完成后,设置到myVar变量中Java服务任务描述Java服务任务⽤来调⽤外部Java类图形标记Java服务任务显⽰为圆⾓矩形,左上⾓有⼀个齿轮⼩图标XML内容声明Java调⽤逻辑有四种⽅式:实现JavaDelegate或者ActivityBehavior执⾏解析代理对象的表达式调⽤⼀个⽅法表达式调⽤⼀个值表达式执⾏⼀个在流程执⾏中调⽤的类,需要在activiti:class属性中设置全类名:<serviceTask id="javaService"name="My Java Service Task"activiti:class="org.activiti.MyJavaDelegate" />使⽤表达式调⽤⼀个对象,对象必须遵循⼀些规则,并使⽤activiti:delegateExpression属性进⾏创建:<serviceTask id="serviceTask" activiti:delegateExpression="${delegateExpressionBean}" />delegateExpressionBean是⼀个实现了JavaDelegate接⼝的bean,定义在实例的spring容器中要执⾏指定的UEL⽅法表达式, 需要使⽤activiti:expression:<serviceTask id="javaService"name="My Java Service Task"activiti:expression="#{printer.printMessage()}" />⽅法printMessage()会调⽤名为printer对象的⽅法为表达式中的⽅法传递参数:<serviceTask id="javaService"name="My Java Service Task"activiti:expression="#{printer.printMessage(execution, myVar)}" />调⽤名为printer对象上的⽅法printMessage.第⼀个参数是DelegateExecution, 在表达式环境中默认名称为execution. 第⼆个参数传递的是当前流程的名为myVar的变量要执⾏指定的UEL⽅法表达式, 需要使⽤activiti:expression:<serviceTask id="javaService"name="My Java Service Task"activiti:expression="#{split.ready}" />ready属性的getter⽅法:getReady() 会作⽤于名为split的bean上.这个对象会被解析为流程对象和spring环境中的对象实现要在流程执⾏中实现⼀个调⽤的类,这个类需要实现org.activiti.engine.delegate.JavaDelegate接⼝,并在execute⽅法中提供对应的业务逻辑.当流程执⾏到特定阶段,会指定⽅法中定义好的业务逻辑,并按照默认BPMN 2.0中的⽅式离开节点⽰例: 创建⼀个java类的例⼦,对流程变量中字符串转换为⼤写这个类需要实现org.activiti.engine.delegate.JavaDelegate接⼝,要求实现execute(DelegateExecution) ⽅法,包含的业务逻辑会被引擎调⽤流程实例信息:流程变量和其他信息,可以通过DelegateExecution接⼝访问和操作public class ToUppercase implements JavaDelegate {public void execute(DelegateExecution execution) throws Exception {String var = (String) execution.getVariable("input");var = var.toUpperCase();execution.setVariable("input", var);}}serviceTask定义的class只会创建⼀个java类的实例所有流程实例都会共享相同的类实例,并调⽤execute(DelegateExecution) 类不能使⽤任何成员变量,必须是线程安全的,必须能模拟在不同线程中执⾏.影响着属性注⼊的处理⽅式流程定义中引⽤的类(activiti:class)不会在部署时实例化只有当流程第⼀次执⾏到使⽤类的时候,类的实例才会被创建如果找不到类,会抛出⼀个ActivitiException这个原因是部署环境(更确切是的classpath)和真实环境往往是不同的:当使⽤ant或业务归档上传到Activiti Explorer来发布流程,classpath没有包含引⽤的类内部实现类也可以提供实现org.activiti.engine.impl.pvm.delegate.ActivityBehavior接⼝的类实现可以访问更强⼤的ActivityExecution,它可以影响流程的流向注意: 这应该尽量避免.只有在⾼级情况下并且确切知道要做什么的情况下,再使⽤ActivityBehavior接⼝属性注⼊为代理类的属性注⼊数据. ⽀持如下类型的注⼊: 固定的字符串表达式如果有效的话,数值会通过代理类的setter⽅法注⼊,遵循java bean的命名规范(⽐如fistName属性对应setFirstName(Xxx)⽅法)如果属性没有对应的setter⽅法,数值会直接注⼊到私有属性中⼀些环境的SecurityManager不允许修改私有属性,要把想注⼊的属性暴露出对应的setter⽅法来⽆论流程定义中的数据是什么类型,注⼊⽬标的属性类型都应该是 org.activiti.engine.delegate.Expression⽰例: 把⼀个常量注⼊到属性中属性注⼊可以使⽤class属性在声明实际的属性注⼊之前,需要定义⼀个extensionElements的XML元素<serviceTask id="javaService"name="Java service invocation"activiti:class="org.activiti.examples.bpmn.servicetask.ToUpperCaseFieldInjected"><extensionElements><activiti:field name="text" stringValue="Hello World" /></extensionElements></serviceTask>ToUpperCaseFieldInjected类有⼀个text属性,类型是org.activiti.engine.delegate.Expression. 调⽤text.getValue(execution) 时,会返回定义的字符串Hello World可以使⽤长⽂字(⽐如,内嵌的email),使⽤activiti:string⼦元素:<serviceTask id="javaService"name="Java service invocation"activiti:class="org.activiti.examples.bpmn.servicetask.ToUpperCaseFieldInjected"><extensionElements><activiti:field name="text"><activiti:string>Hello World</activiti:string></activiti:field></extensionElements></serviceTask>可以使⽤表达式,实现在运⾏期动态解析注⼊的值这些表达式可以使⽤流程变量或spring定义的bean.服务任务中的java类实例会在所有流程实例中共享:为了动态注⼊属性的值,可以在org.activiti.engine.delegate.Expression中使⽤值和⽅法表达式会使⽤传递给execute⽅法的DelegateExecution参数进⾏解析<serviceTask id="javaService" name="Java service invocation"activiti:class="org.activiti.examples.bpmn.servicetask.ReverseStringsFieldInjected"><extensionElements><activiti:field name="text1"><activiti:expression>${genderBean.getGenderString(gender)}</activiti:expression></activiti:field><activiti:field name="text2"><activiti:expression>Hello ${gender == 'male' ? 'Mr.' : 'Mrs.'} ${name}</activiti:expression></activiti:field></ extensionElements></ serviceTask>⽰例: 注⼊表达式,并使⽤在当前传⼊的DelegateExecution解析:public class ReverseStringsFieldInjected implements JavaDelegate {private Expression text1;private Expression text2;public void execute(DelegateExecution execution) {String value1 = (String) text1.getValue(execution);execution.setVariable("var1", new StringBuffer(value1).reverse().toString());String value2 = (String) text2.getValue(execution);execution.setVariable("var2", new StringBuffer(value2).reverse().toString());}}可以把表达式设置成⼀个属性,⽽不是⼦元素:因为java类实例会被重⽤,注⼊只会发⽣⼀次,当服务任务调⽤第⼀次的时候发⽣注⼊当代码中的属性改变了,值也不会重新注⼊,把它们看作是不变的,不⽤修改它们服务任务结果服务流程返回的结果(使⽤表达式的服务任务)可以分配给已经存在的或新的流程变量通过指定服务任务定义的activiti:resultVariable属性来实现指定的流程变量会被服务流程的返回结果覆盖如果没有指定返回变量名,就会忽略返回结果<serviceTask id="aMethodExpressionServiceTask"activiti:expression="#{myService.doSomething()}"activiti:resultVariable="myVar" />服务流程的返回值(在myService上调⽤doSomething() ⽅法的返回值,myService可能是流程变量,也可能是spring的bean),在服务执⾏完成之后,会设置到名为myVar的流程变量⾥处理异常执⾏⾃定义逻辑时,常常需要捕获对应的业务异常,在流程内部进⾏处理抛出BPMN Errors: 在服务任务或脚本任务的代码⾥抛出BPMN error: 要从JavaDelegate,脚本,表达式和代理表达式中抛出名为BpmnError的特殊ActivitiExeption 引擎会捕获这个异常,把它转发到对应的错误处理中:边界错误事件或错误事件⼦流程public class ThrowBpmnErrorDelegate implements JavaDelegate {public void execute(DelegateExecution execution) throws Exception {try {executeBusinessLogic();} catch (BusinessException e) {throw new BpmnError("BusinessExceptionOccured");}}}构造参数是错误代码,会被⽤来决定哪个错误处理器会来响应这个错误这个机制只⽤于业务失败,应该被流程定义中设置的边界错误事件或错误事件⼦流程处理. 技术上的错误应该使⽤其他异常类型,通常不会在流程⾥处理异常顺序流: 内部实现类在⼀些异常发⽣时,让流程进⼊其他路径<serviceTask id="javaService"name="Java service invocation"activiti:class="org.activiti.ThrowsExceptionBehavior"></serviceTask><sequenceFlow id="no-exception" sourceRef="javaService" targetRef="theEnd" /><sequenceFlow id="exception" sourceRef="javaService" targetRef="fixException" />这⾥的服务任务有两个外出顺序流:分别叫exception和no-exception. 异常出现时会使⽤顺序流的ID来决定流向public class ThrowsExceptionBehavior implements ActivityBehavior {public void execute(ActivityExecution execution) throws Exception {String var = (String) execution.getVariable("var");PvmTransition transition = null;try {executeLogic(var);transition = execution.getActivity().findOutgoingTransition("no-exception");} catch (Exception e) {transition = execution.getActivity().findOutgoingTransition("exception");}execution.take(transition);}}JavaDelegate使⽤Activiti服务需要在Java服务任务中使⽤Activiti服务的场景: ⽐如,通过RuntimeService启动流程实例,⽽callActivity不满⾜需求org.activiti.engine.delegate.DelegateExecution允许通过 org.activiti.engine.EngineServices接⼝直接获得这些服务:public class StartProcessInstanceTestDelegate implements JavaDelegate {public void execute(DelegateExecution execution) throws Exception {RuntimeService runtimeService = execution.getEngineServices().getRuntimeService();runtimeService.startProcessInstanceByKey("myProcess");}}所有activiti服务的API都可以通过这个接⼝获得使⽤这些API调⽤出现的所有数据改变,都是在当前事务中在例如spring和CDI这样的依赖注⼊环境也会起作⽤,⽆论是否启⽤了JTA数据源⽰例: 下⾯的代码功能与上⾯的代码⼀致,这是RuntimeService是通过依赖注⼊获得,⽽不是通过org.activiti.engine.EngineServices接⼝@Component("startProcessInstanceDelegate")public class StartProcessInstanceTestDelegateWithInjection {@Autowiredprivate RuntimeService runtimeService;public void startProcess() {runtimeService.startProcessInstanceByKey("oneTaskProcess");}}因为服务调⽤是在当前事务⾥,数据的产⽣或改变,在服务任务执⾏完之前,还没有提交到数据库.所以API对于数据库数据的操作,意味着未提交的操作在服务任务的API调⽤中都是不可见的WebService任务描述WebService任务可以⽤来同步调⽤⼀个外部的WebService图形标记WebService任务与Java服务任务显⽰效果⼀样(圆⾓矩形,左上⾓有⼀个齿轮⼩图标)XML内容要使⽤WebService需要导⼊操作和类型,可以使⽤import标签来指定WebService的WSDL<import importType="/wsdl/"location="http://localhost:63081/counter?wsdl"namespace="/" />声明告诉activiti导⼊WSDL定义,但没有创建itemDefinition和message假设想调⽤⼀个名为prettyPrint的⽅法,必须创建为请求和响应信息对应的message和itemDefinition <message id="prettyPrintCountRequestMessage" itemRef="tns:prettyPrintCountRequestItem" /><message id="prettyPrintCountResponseMessage" itemRef="tns:prettyPrintCountResponseItem" /><itemDefinition id="prettyPrintCountRequestItem" structureRef="counter:prettyPrintCount" /><itemDefinition id="prettyPrintCountResponseItem" structureRef="counter:prettyPrintCountResponse" />在申请服务任务之前,必须定义实际引⽤WebService的BPMN接⼝和操作基本上,定义接⼝和必要的操作.对每个操作都会重⽤上⾯定义的信息作为输⼊和输出⽰例: 定义了counter接⼝和prettyPrintCountOperation操作:<interface name="Counter Interface" implementationRef="counter:Counter"><operation id="prettyPrintCountOperation" name="prettyPrintCount Operation"implementationRef="counter:prettyPrintCount"><inMessageRef>tns:prettyPrintCountRequestMessage</inMessageRef><outMessageRef>tns:prettyPrintCountResponseMessage</outMessageRef></operation></interface>然后定义WebService任务,使⽤WebService实现,并引⽤WebService操作<serviceTask id="webService"name="Web service invocation"implementation="##WebService"operationRef="tns:prettyPrintCountOperation">WebService任务IO规范每个WebService任务可以定义任务的输⼊输出IO规范<ioSpecification><dataInput itemSubjectRef="tns:prettyPrintCountRequestItem" id="dataInputOfServiceTask" /><dataOutput itemSubjectRef="tns:prettyPrintCountResponseItem" id="dataOutputOfServiceTask" /><inputSet><dataInputRefs>dataInputOfServiceTask</dataInputRefs></inputSet><outputSet><dataOutputRefs>dataOutputOfServiceTask</dataOutputRefs></outputSet></ioSpecification>WebService任务数据输⼊关联指定数据输⼊关联有两种⽅式:使⽤表达式使⽤简化⽅式使⽤表达式指定数据输⼊关联: 需要定义来源和⽬的item,并指定每个item属性之间的对应关系:<dataInputAssociation><sourceRef>dataInputOfProcess</sourceRef><targetRef>dataInputOfServiceTask</targetRef><assignment><from>${dataInputOfProcess.prefix}</from><to>${dataInputOfServiceTask.prefix}</to></assignment><assignment><from>${dataInputOfProcess.suffix}</from><to>${dataInputOfServiceTask.suffix}</to></assignment></dataInputAssociation>分配item的前缀和后缀使⽤简化⽅式指定数据输⼊关联: sourceRef元素是activiti的变量名,targetRef元素是item定义的⼀个属性:<dataInputAssociation><sourceRef>PrefixVariable</sourceRef><targetRef>prefix</targetRef></dataInputAssociation><dataInputAssociation><sourceRef>SuffixVariable</sourceRef><targetRef>suffix</targetRef></dataInputAssociation>PrefixVariable变量的值分配给prefix属性,把SuffixVariable变量的值分配给suffix属性WebService任务数据输出关联指定数据输出关联有两种⽅式:使⽤表达式使⽤简化⽅式使⽤表达式指定数据输出关联: 需要定义⽬的变量和来源表达式<dataOutputAssociation><targetRef>dataOutputOfProcess</targetRef><transformation>${dataOutputOfServiceTask.prettyPrint}</transformation></dataOutputAssociation>⽅法和数据输⼊关联完全⼀样使⽤简化⽅式指定数据输出关联: sourceRef元素是item定义的⼀个属性,targetRef元素是activiti的变量名<dataOutputAssociation><sourceRef>prettyPrint</sourceRef><targetRef>OutputVariable</targetRef></dataOutputAssociation>⽅法和数据输⼊关联完全⼀样业务规则任务描述业务规则任务⽤来同步执⾏⼀个或多个规则Activiti使⽤drools规则引擎执⾏业务规则: 包含业务规则的.drl⽂件必须和流程定义⼀起发布流程定义⾥包含了执⾏这些规则的业务规则任务流程使⽤的所有.drl⽂件都必须打包在流程BAR⽂件⾥如果想要⾃定义规则任务的实现: 想⽤不同⽅式使⽤drools,或者使⽤完全不同的规则引擎.你可以使⽤BusinessRuleTask上的class或表达式属性图形标记业务规则任务是⼀个圆⾓矩形,左上⾓使⽤⼀个表格⼩图标进⾏显⽰XML内容要执⾏部署流程定义的BAR⽂件中的⼀个或多个业务规则,需要定义输⼊和输出变量:对于输⼊变量定义,可以使⽤逗号分隔的⼀些流程变量输出变量定义只包含⼀个变量名,会把执⾏业务规则后返回的对象保存到对应的流程变量中注意: 结果变量会包含⼀个对象列表,如果没有指定输出变量名称,默认会使⽤ org.activiti.engine.rules.OUTPUT<process id="simpleBusinessRuleProcess"><startEvent id="theStart" /><sequenceFlow sourceRef="theStart" targetRef="businessRuleTask" /><businessRuleTask id="businessRuleTask" activiti:ruleVariablesInput="${order}"activiti:resultVariable="rulesOutput" /><sequenceFlow sourceRef="businessRuleTask" targetRef="theEnd" /><endEvent id="theEnd" /></process>业务规则任务也可以配置成只执⾏部署的.drl⽂件中的⼀些规则.这时要设置逗号分隔的规则名,只会执⾏rule1和rule2:<businessRuleTask id="businessRuleTask" activiti:ruleVariablesInput="${order}"activiti:rules="rule1, rule2" />定义哪些规则不⽤执⾏:除了rule1和rule2以外,所有部署到流程定义同⼀个BAR⽂件中的规则都会执⾏:<businessRuleTask id="businessRuleTask" activiti:ruleVariablesInput="${order}"activiti:rules="rule1, rule2" exclude="true" />可以⽤⼀个选项修改BusinessRuleTask的实现:<businessRuleTask id="businessRuleTask" activiti:class="${MyRuleServiceDelegate}" />BusinessRuleTask的功能和ServiceTask⼀样,但是使⽤BusinessRuleTask的图标来表⽰在这⾥要执⾏业务规则邮件任务Activiti强化了业务流程,⽀持⾃动邮件任务: 可以发送邮件给⼀个或多个参与者,包括⽀持cc,bcc,HTML内容等等邮件任务不是BPMN 2.0规范定义的官⽅任务,Activiti中邮件任务是⽤专门的服务任务实现的邮件服务器配置Activiti引擎要通过⽀持SMTP功能的外部邮件服务器发送邮件为了实际发送邮件,引擎穾知道如何访问邮件服务器.下⾯的配置可以设置到activiti.cfg.xml配置⽂件中:属性是否必须描述mailServerHost否邮件服务器的主机名(⽐如:).默认为localhostmailServerPort 是如果没有使⽤默认端⼝邮件服务器上的SMTP传输端⼝.默认为25mailServerDefaultFrom否如果⽤户没有指定发送邮件的邮件地址,默认设置的发送者的邮件地址。
为了更好地理解和使用Activiti工作流引擎,我们有必要对其源码进行深入的解读和学习。
在本文中,我们将针对Activiti工作流引擎的源码进行解读,并添加中文注释,以便读者可以更好地理解其原理和实现。
一、Activiti工作流引擎概述1.1 概述Activiti是一个轻量级的工作流引擎,它实现了BPMN 2.0规范,并提供了丰富的API和工具,方便开发人员进行流程设计、部署和执行。
1.2 应用场景Activiti广泛应用于企业中的各种业务流程,如审批流程、请假流程、报销流程等,通过Activiti可以实现流程的自动化和规范化,提高工作效率和质量。
1.3 核心特性Activiti工作流引擎具有以下核心特性:- 支持BPMN 2.0规范,可以对复杂的业务流程进行建模和执行;- 提供了丰富的API和工具,方便开发人员进行流程管理和监控;- 支持分布式部署,可以满足高并发、高可用的业务需求。
二、Activiti源码解读2.1 模块解析Activiti源码主要包括以下几个模块:- activiti-engine:工作流引擎的核心实现,包括流程定义、流程实例、任务管理等;- activiti-bpmn-converter:BPMN 2.0规范的解析和转换;- activiti-rest:RESTful API的实现;- activiti-spring:与Spring框架的集成;- ...2.2 核心类解析Activiti工作流引擎的核心类包括ProcessEngine、RepositoryService、RuntimeService、TaskService等,这些类负责流程定义、流程执行、任务管理等核心功能的实现。
2.3 核心流程解析Activiti工作流引擎的核心流程包括流程定义、流程部署、流程执行等,这些流程通过一系列的核心类和接口进行协同工作,并最终实现业务流程的自动化和规范化。
2.4 核心算法解析Activiti工作流引擎的核心算法包括流程的解析、执行和监控,这些算法通过一系列的数据结构和设计模式进行实现,保证了工作流引擎的高性能和可靠性。
Activiti工作流详解完整教程 Activiti教程详解完整教程 1. Activiti介绍
Activiti是由Alfresco软件在2010年5月17日发布的业务流程管理(BPM)框架,它是覆盖了业务流程管理,工作流,服务协作等领域的一个开源,灵活的,易扩展的可执行流程语言框架。 Activiti基于Apache许可的开源BPM平台,创始人Tom Baeyens是JBoss JBPM的项目架构师,它的特色是提供了eclipse插件,开发人员可以通过插件直接绘画出业务流程图。 1.1 工作流引擎 ProcessEngine对象,这是Activiti工作的核心。负责生成流程运行时的各种实例及数据,监控和管理流程的运行。
1.2 BPMN 业务流程建模与标注(Business Process Model and Notation,BPMN),描述流程的基本符号,包括这些图元如何组合成一个业务流程图(Business Process Diagram)
2. 准备环境 2.1 Activiti软件环境 1) JDK1.6或者更高版本 2) 支持的数据库有:h2,mysql,oracle,mysql,db2等 3) 支持Activiti运行的jar包,可以通过maven依赖引入 4) 开发环境为Eclipse3.7或者以上版本, myeclipse为8.6版本 2.2安装流程设计器(eclipse插件) 1)打开Help Install New Software Add 输入 Name: Activiti Designer Location: http://Activiti.org/designer/update/ 输入完成后,单击OK按钮等待下载完成后安装。 安装完成后在菜单选项中会出现Activiti的目录选项 2.3 设置eclipse activit插件的画流程图 选项 打开菜单Windows --> Preferences --> Activiti -->Save 下流程图片的生成方式
勾选上Create process definition image when saving the diagram操作,勾选上这个操作后在画流程图后保存eclipse会自动生成对应的流程图片。
2.4 准备开发环境 2.4.1 创建maven web项目,在maven中添加Activiti依赖
在eclipse左边工作栏右键New选择创建Maven Project项目,创建一个名为ActivitiTest的项目 点击Finish完成。 右键项目选择Properties,选择Project Facets 勾选上图中的选项,点击Apply,再点击OK
然后将项目转换成web项目,右键项目选择Properties,在Project Facets中做如下勾选,然后点击Appy应用和OK确定 然后右键项目Properties ,选择Deployment Assembly,将test相关目录Remove掉之保留main下面需要发布的内容,如下图 然后点击Appply和OK 然后在pom.xml文件中添加以下依赖 org.Activiti Activiti-engine 5.21.0 org.Activiti Activiti-spring 5.21.0 org.codehaus.groovy groovy-all 2.4.3
org.slf4j slf4j-api 1.7.6 org.slf4j slf4j-jdk14 1.7.6 junit junit 3.8.1 test
mysql mysql-connector-java 5.1.38
然后在命令行下mvn compile 编译当前项目,
将需要的包下载到本地仓库
2.4.2 初始化数据库 1)src/main/resource目录下创建Activiti.cfg.xml
文件,内容如下
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
class="org.Activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration"> /> value="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8" />
jdbcUrl为你电脑数据库的url jdbcUsername为数据库用户名 jdbcPassword为数据库密码
2)在main/java目录下创建任意目录和类 编写创建Activiti数据表方法 public class CreateTable { /**** * 创建流程表 * */ @Test public void createTable() { ProcessEngine processEngine =