原始博文链接
什么是工作流
首先还是要把专业术语给搬出来:工作流(Workflow),就是“业务过程的局部或整体在计算机应用环境下的自动化”,它次要解决的是“使在多个参与者之间依照某种预约义的规定传递文档、信息或工作的过程主动进行,从而实现某个预期的业务指标,或者促使此指标的实现”。说的艰深一点就是通过计算机利用帮忙咱们“走流程”,各种证件的办理、资格的审批在生活中无处不在,工作流就在咱们身边。
工作流这个名词概念在计算机领域中,起源于生产组织和办公自动化畛域,是针对日常工作中具备固定程序流动而提出的一个概念,目标是通过将工作分解成定义良好的工作或角色,依照肯定的规定和过程来执行这些工作并对其进行监控,达到进步工作效率、更好的管制过程、加强对客户的服务、无效治理业务流程等目标。
要走“走流程”的人是苦楚的,慢、麻烦置信是很多人对走流程的印象,而解决“走流程”的人也并不开心,简单的过程令人心力憔悴。而在这个计算机互联网时代,流程也都逐步开始“上网”,形成所谓的信息化的一个重要组成部分。这就催生了后盾工作流框架,比拟驰名的有jBPM和Activiti,本文的配角就是Activiti。
Activiti简介
本文以Activiti 5.22作为示例和剖析的根底。还是先上官话:Activiti5是由Alfresco软件在2010年5月17日公布的业务流程治理(BPM)框架,它是笼罩了业务流程治理、工作流、服务合作等畛域的一个开源的、灵便的、易扩大的可执行流程语言框架。
Activiti实现了BPMN 2.0标准,能够公布设计好的流程定义,并通过api进行流程调度。Activiti流程引擎重点关注在零碎开发的易用性和轻量性上。每一项 BPM 业务性能 Activiti 流程引擎都以服务的模式提供给开发人员。通过应用这些服务,开发人员可能构建出功能丰富、轻便且高效的 BPM 应用程序。
本文指标
记录上手过程,疾速了解、入门Actitviti,并不深挖以及应用骚操作。
上手过程
筹备工作
- 首先Activiti的数据基于数据库,所以首先须要一个数据库,根本支流的数据库Activiti都反对,选用mysql就ok。
- 去官网下载Activiti,外面不仅蕴含了须要的jar包,还有文档、sql文件、war包等。
- 配置IDE,尽管说eclipse插件是Activiti的一个长处,然而目前IDEA的风行水平更高一些,还是选用IDEA作为开发测试工具,IDEA也有Activiti插件名为actiBPM,然而集体感觉不太好用,截止目前这个插件最初更新工夫是2014年,看起来如同不在保护了,比拟难堪。
- 框架集成,Activiti绝大多数状况还是作为一个组件集成到后盾框架中,为了不便,缩小其余因素烦扰,选用SpringBoot。不过很惋惜在练习的时候想当然地选了SpringBoot2.0,集成起来产生了问题节约了很多工夫。
- 简略理解下BPMN,业务流程建模与标注(Business Process Model and Notation,BPMN),定义了流程图的内容和表白,最新的是BPMN 2.0标准。流程内容个别采纳XML格局来承载表白,通过图形化工具来疾速、直观地设计流程。
流程图图解
很多教程喜爱上来就说API、说数据库表,但我认为还是该从最直观的流程图来作为切入点,一步一步引出各个概念。下图是一个最简略的流程图,流程的目标是员工退出公司的审批。
对应的XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" 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" xmlns:tns="http://www.activiti.org/test" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id="m1534942345607" name="" targetNamespace="http://www.activiti.org/test" typeLanguage="http://www.w3.org/2001/XMLSchema"> <process id="joinProcess" isClosed="false" isExecutable="true" processType="None"> <startEvent id="_2" name="Join process"> <extensionElements> <activiti:formProperty id="personId" name="person Id" required="true" type="long"/> <activiti:formProperty id="compId" name="company Id" required="true" type="long"/> </extensionElements> </startEvent> <userTask activiti:exclusive="true" id="_3" name="主管审批" activiti:candidateUsers="${joinService.findUsers(execution)}" isForCompensation="true"> <extensionElements> <activiti:formProperty id="joinApproved" name="Join Approved" type="enum"> <activiti:value id="true" name="Approve" /> <activiti:value id="false" name="Reject" /> </activiti:formProperty> </extensionElements> </userTask> <endEvent id="_4" name="EndEvent"/> <serviceTask activiti:exclusive="true" id="_5" name="审批解决" activiti:expression="${joinService.joinGroup(execution)}" /> <sequenceFlow id="_6" sourceRef="_2" targetRef="_3"/> <sequenceFlow id="_7" sourceRef="_3" targetRef="_5"/> <sequenceFlow id="_8" sourceRef="_5" targetRef="_4"/> </process> <bpmndi:BPMNDiagram documentation="background=#FFFFFF;count=1;horizontalcount=1;orientation=0; width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0" id="Diagram-_1" name="New Diagram"> <bpmndi:BPMNPlane bpmnElement="myProcess_1"> <bpmndi:BPMNShape bpmnElement="_2" id="Shape-_2"> <omgdc:Bounds height="32.0" width="32.0" x="70.0" y="181.5"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="_3" id="Shape-_3"> <omgdc:Bounds height="55.0" width="85.0" x="160.0" y="170.0"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="_4" id="Shape-_4"> <omgdc:Bounds height="32.0" width="32.0" x="455.0" y="181.5"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="_5" id="Shape-_5"> <omgdc:Bounds height="55.0" width="85.0" x="310.0" y="170.0"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNEdge bpmnElement="_6" id="BPMNEdge__6" sourceElement="_2" targetElement="_3"> <omgdi:waypoint x="102.0" y="197.5"/> <omgdi:waypoint x="160.0" y="197.5"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="_7" id="BPMNEdge__7" sourceElement="_3" targetElement="_5"> <omgdi:waypoint x="245.0" y="197.5"/> <omgdi:waypoint x="310.0" y="197.5"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="_8" id="BPMNEdge__8" sourceElement="_5" targetElement="_4"> <omgdi:waypoint x="395.0" y="197.5"/> <omgdi:waypoint x="455.0" y="197.5"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> </bpmndi:BPMNPlane> </bpmndi:BPMNDiagram></definitions>
图中内容相当简略,两个开始和完结的圆圈,两个流程的步骤。
先用直白的文字描述这个流程:人事提交员工退出公司的审批 -> 主管审批 -> 完结,通过后要生成一条入职数据。
而流程图中体现的是:开始流程 -> 主管审批 -> 审批解决 -> 完结。
可见还是有肯定的差异,依据我集体的感觉,BPMN流程图的表白和直白的思维是有肯定的区别的,这也是我一开始上手时感到困惑的点。其一是Activiti流程开始后并不会在开始节点停留,所以提交审批这个流程在图中没有间接的体现,其二是对于一个审批工作来说艰深思维会认为审批和解决属于同一步操作,而对于Activiti每一步操作是一个工作,工作辨别明确,其中尤以人为的操作(UserTask)和程序处理(ServiceTask)这两个为主,因而主管审批是一步,而审批解决生成数据是另外一步。
图中bpmndi:BPMNDiagram
节点下的内容代表的是流程图各个节点的地位信息,以图的左上角为原点,用xy坐标值示意流程节点在图中的地位。
次要概念
工作
很天然地引申出工作这个点,更精确地说应该是执行打算(excution)。Task用来形容业务过程中所有可能产生工时的行为,它次要包含UserTask、ServiceTask、ScriptTask、ReceiveTask、MailTask等等。具体阐明一下其中最根底的两种:
- UserTask:人工工作,用来形容认为参加的操作,流程执行到此节点时须人工响应后能力持续向下流转。人工工作最终要的属性就是办理工作的执行者,有assignee(繁多执行人)、candidateUsers(多个候选执行人)、candidateGroups(候选执行组)这几种属性可选。
- ServiceTask:Java服务工作,容许指定一个实现了指定接口的java类,或者执行一个表达式。与User Task不同,流程引擎流经此节点会主动调用Java类中定义的办法,办法执行结束主动向下一流程节点流转。
程序流
有了工作节点就天然须要把他们连接起来,图中的箭头连线称为程序流(sequenceFlow),用于形容节点的流转方向和程序。次要属性有sourceRef(起始节点Id)、targetRef(指向节点Id)、conditionExpression(条件限度的表白)。
网关
网关(gateways)在示例的图中没有体现,然而它是流程定义重要的因素之一。实在的流程并不会如此简略,很多时候流程须要分叉、并行等等,而网关就是用来决定流程流转指向的,可能会被用作条件分支或聚合,也能够被用作并行执行或基于事件的排它性条件判断。罕用的网关有互斥关口(exclusiveGateway,流程通过时只能走其中一个程序流)和并行关口(parallelGateway,通过关口后会同时通过所有程序流,所有流程实现后会一起通过指向的并行关口)。
事件
说完上述的还有两个圆圈没有讲到,在BPMN标准下圆圈个别示意事件。启动、完结、边界条件以及每个流动的创立、开始、流转等都是流程事件,利用事件机制,能够通过事件控制器为零碎减少辅助性能。开始和完结是每个流程都必须蕴含的事件节点。
工作和程序流以及未介绍的子流程能够同称为流动(Activities),加上网关和事件就形成了BPMN2.0对流程执行语义定义的三类基本要素。
流程变量
流程变量在整个工作流中用于传递业务变量,流程变量的作用域范畴是只对应一个流程实例,在开启流程和实现工作时都能够设置变量,间接设置变量时,分setVariable和setVariableLocal,local示意绑定当前任务,流程继续执行时下个工作获取不到这个流程变量,波及的数据库表为act_ru_variable、act_hi_varinst(变量历史记录)。
留神,流程变量须要实现Serializable接口且要求过程中属性不能变动(反序列化),须要增加序列化ID,如果是JavaBean作为流程变量,序列化的bean会寄存到act_ge_bytearray这张表中。
流程能够定义须要哪些变量,能够查看xml中activiti:formProperty相干的信息。
外围API
理解了流程图之后,介绍Activiti的外围API,疾速造成对于Activiti的基本概念。Activiti最外围的类是流程引擎(ProcessEngine),其余所有类都通过引擎来获取。引擎能够获取各种各种各样的服务(Service)对应解决各种需要,所有流程的具体操作都对应执行某一项服务提供的办法。
服务
- RepositoryService:仓库服务。业务流程的定义都须要应用一些定义文件,定义了流程须要将其部署,部署之后可能须要查问部署的信息和相干的文件,这些需要就由RepositoryService提供。
- RuntimeService:流程执行服务。在Activiti中,每当一个流程定义被启动一次之后,都会生成一个相应的流程对象实例。RuntimeService提供了启动流程、查问流程实例、设置获取流程实例变量等性能。
- TaskService:工作服务。它提供了运行时工作查问、支付、实现、删除以及变量设置等性能。
- HistoryService:历史服务。流程、工作执行实现之后可能须要追溯、查问历史,这就须要用到HistoryService。
- IdentityService:身份服务。Activiti中内置了用户以及组治理的性能,必须应用这些用户和组的信息能力获取到相应的Task。IdentityService提供了对Activiti 零碎中的用户和组的治理性能。当然用户和组也能够自定义提供,然而这些内容不在本文探讨范畴之内
- ManagementService: 治理服务。它提供了对Activiti流程引擎的治理和保护性能,这些性能不在工作流驱动的应用程序中应用,次要用于Activiti零碎的日常保护。
对象
除了服务,还有以接口模式表白的几个要害对象:
- Deployment:流程部署对象,是对一个部署的抽象化表白。
- ProcessDefinition:流程定义,部署胜利后主动创立。
- ProcessInstance:代表流程实例,启动流程时创立。
- Execution:执行打算,流程实例和流程执行中的所有节点都是Execution。当流程复线执行时ProcessInstance与Execution内容保持一致,并发流程中,总线路为ProcessInstance,分线路中每个流动由Execution表白。
- Task:工作,在Activiti中的Task仅指有角色参加的工作,包含上述的UserTask以及MannualTask。
入门示例
说完了概念性的货色,接下来就须要残缺地走一遍流程。示例的同时介绍相干的数据表,Activiti所有的内容信息都以数据库作为根底,各种服务提供的查问实质上都是对数据库的查问。
还是以上述的简略流程作为示例来进行演示。
工程搭建
关上IDEA创立一个SpringBoot我的项目(能够选2.0,有坑然而会加以阐明解决),勾选组件:Web、JPA(想用其余的ORM也能够)、MySQL即可,我的项目构建采纳Maven。工程创立胜利后,在POM文件中减少Activiti的依赖。
<dependency> <groupId>org.activiti</groupId> <artifactId>activiti-spring-boot-starter-basic</artifactId> <version>5.22.0</version></dependency>
这里有个整合的坑点,Activiti目前的版本落后于SpringBoot和SpringSecurity,如果间接就这么运行工程会产生短少SpringSecurity依赖的谬误,然而能够在POM中能够看到SpringSecurity的依赖的Optional属性为True,而且平安相干的主动配置增加了@AutoConfigureBefore
,确保在SpringSecurity主动配置实现后执行。尝试退出SpringSecurity的依赖仍然报错,能够发现Activiti里依赖的一个类在SpringSecurity5.0版本之后曾经挪动了地位。因而必须强制排除产生谬误的Activiti的主动配置类,批改主类Application如下:
@EnableAutoConfiguration(exclude = { org.activiti.spring.boot.SecurityAutoConfiguration.class})@SpringBootApplicationpublic class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); }}
数据筹备与流程部署
创立Person和Comp两个实体类以及相干的JpaRepository,用于示意员工和公司以及体现生成数据的操作。而后保留几个实例以供应用。
@Entitypublic class Person { @Id @GeneratedValue private Long personId; private String personName; @ManyToOne private Comp comp; public Person(String personName) { this.personName = personName; } // Getter & Setter // ...}@Entitypublic class Comp { @Id @GeneratedValue private Long compId; private String compName; @OneToMany(mappedBy = "comp") private List<Person> people; public Comp(String compName) { this.compName = compName; } // Getter & Setter // ...}
在测试类中写入:
@Autowiredprivate PersonRepository personRepository;@Autowiredprivate CompRepository compRepository;@Beforepublic void contextLoads() { // 筹备数据 if (personRepository.findAll().size() == 0) { personRepository.save(new Person("wtr")); personRepository.save(new Person("wyf")); personRepository.save(new Person("admin")); } if (compRepository.findAll().size() == 0) { Comp group = new Comp("great company"); compRepository.save(group); Person admin = personRepository.findByPersonName("admin"); Person wtr = personRepository.findByPersonName("wtr"); admin.setComp(group); wtr.setComp(group); personRepository.save(admin); personRepository.save(wtr); }}
接下来将下面的流程XML代码拷贝进入一个xml文件,在resource目录下新建一个process文件夹,将xml文件放入这个文件夹,复制文件更改后缀为bpmn,这么做是因为IDEA的插件编辑器无奈编辑某些属性,而且从新关上bpmn文件会发现配置的属性看不到,所以会把xml放在同一个目录下进行参考。设计流程时能够先用插件画图,而后更改为xml后缀进行属性编辑,编辑实现后复制一份并更改为bpmn后缀。
因为和springboot集成,process目录下的流程会主动部署,省去了部署这件事,不过还是把一般的部署代码贴出来。
@Testpublic void showDeploy(){ ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); Deployment deploy = processEngine.getRepositoryService() .createDeployment() .name("testDeploy") .addClasspathResource("processes/example.bpmn") .deploy(); System.out.println(deploy.getId() + " " + deploy.getName());}
与部署相干的数据表以ACT_RE结尾,在执行以上步骤或者主动部署后,能够在相干表中查看到新生成的部署信息以及流程定义的信息。另外流程文件(包含bpmn、png、bpmn20.xml等)会间接以二进制模式存入act_ge_bytearray表,ACT_GE结尾的表寄存通用数据。
同时,还须要筹备身份信息,也就是增加执行人以及执行组,然而这一步并不是必要的,起因同样能够从数据库中窥得一二。上文提到了Activiti提供了一个默认的身份服务,相干的数据表以ACT_ID结尾,很显著act_id_user寄存的就是用户的信息,不过工作相干的表并没有和用户表有外键束缚,所以工作执行的时候即便用户表中没有相干信息,相干的工作表仍然能够存储用户的ID标识,也能够以ID来查问。同样还是放出一段增加用户和组的代码,以供理解参考,示例工程为了不便就不增加用户和组了。
@Testpublic void addUserAndGroup(){ ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); IdentityService identityService = processEngine.getIdentityService(); identityService.saveGroup(new GroupEntity("主管"));//建设组 identityService.saveGroup(new GroupEntity("经理")); identityService.saveUser(new UserEntity("小明"));// 建设用户 identityService.saveUser(new UserEntity("小红")); UserEntity littileMount = new UserEntity("小山"); littileMount.setEmail("xxx@fake.com"); // 设置用户相干详细信息 identityService.saveUser(littileMount); identityService.createMembership("小明", "主管");//建设组和用户关系 identityService.createMembership("小红", "主管"); identityService.createMembership("小山", "经理");}
开启流程实例
以下相干操作为了不便都写在测试方法中,更规范地做法是写几个Controller和Service来进行申请,不过理论失效的代码是统一的。不要立马运行这些代码,因为前面还须要写一些货色,看完一遍当前再入手练习。
筹备得当之后,首先就是开启一个流程。每开启一个定义好的流程就会产生一个流程实例,相干的数据表为act_ru_execution。
@Autowiredprivate RuntimeService runtimeService;@Testpublic void startProcess() { runtimeService.startProcessInstanceByKey("joinProcess");}
因为和Spring整合,Activiti的引擎和服务都在Spring中以供拆卸。开启流程只有一句话,很简略,给出的这个参数值能够在定义流程的xml中找到,找到了天然就了解了。不过认真想想,其实还漏了一些货色,开始流程的时候须要提供这个审批过程须要的信息,就好比去办手续总是要你提交身份证复印件一样。对于这个审批员工退出公司的示例流程来说,最根本的信息就是两个:员工id和公司id,须要在流程开启时传入,这就是流程变量的概念。所以残缺的开启流程代码应该如下所示:
@Autowiredprivate RuntimeService runtimeService;@Testpublic void startProcess() { Person wyf = personRepository.findByPersonName("wyf"); Comp comp = compRepository.findAll().get(0); Map<String, Object> variables = new HashMap<String, Object>(); variables.put("personId", wyf.getId()); // 员工id variables.put("compId", comp.getId()); // 公司id runtimeService.startProcessInstanceByKey("joinProcess",variables);}
实现人工工作
如之前所说,流程开启后不会在开始节点停留,那么很显然目前流程位于主管审批这个节点。人工工作须要响应后流程才会持续,这一步就是抽象化的主管审批动作。
查问工作
首先,Activiti须要晓得由谁来执行某个工作,查看流程xml文件能够发现userTask节点有一个属性:activiti:candidateUsers,这就是在指定执行工作的候选人。它的值是一个表达式(也能够间接填入候选人的id,指定执行者有多种办法),能够了解为执行某个java办法来获取候选人的id。创立一个类JoinService,并且将其交由Spring治理。
@Servicepublic class JoinService { //获取符合条件的审批人,演示不便这里写死,应用时利用理论代码 public List<String> findUsers(DelegateExecution execution) { return Arrays.asList("admin", "wtr"); }}
这就对应了表达式:"${joinService.findUsers(execution)}"
。这里指定了admin和wtr能够执行这个审批。然而理论利用过程中工作不会间接摆在审批人背后,咱们须要查问工作。查问工作的形式有许多种,这里就介绍最根本的依照用户id查问。
@Autowiredprivate ActivitiService activitiService;@Testpublic void query() { List<Task> tasks = activitiService.getTasks("admin"); System.out.println("----------------- task size : "+tasks.size()); for (Task task : tasks){ System.out.println("Id : "+task.getId()+" Name : "+task.getName()); } return ;}
执行实现
查问到这个工作后就能够将其实现。代码也很少,不过别忘了输出代表审批后果的参数。执行完这个办法后,人工工作就实现了,流程将进入下一个节点。
@Autowiredprivate TaskService taskService;@Testpublic void completeTasks() { Map<String, Object> taskVariables = new HashMap<String, Object>(); taskVariables.put("joinApproved", true); // 这里间接给予true示意通过 String taskId = "1"; // 更改成上个办法查问出的工作Id taskService.complete(taskId, taskVariables); }
服务工作的执行
能够在图中看到接下来的节点是一个服务工作。如上文所述,与人工工作不同,服务工作会在执行完设置的办法或者表达式之后主动完结进入下一步。那么很显然最重要的就是如何设置执行的办法,查看流程定义xml文件中的serviceTask节点,很显著就是它的activiti:expression属性指定了执行的办法。依据这个属性值,须要在之前创立的JoinService类中增加一个名为joinGroup的办法,残缺的JoinService类如下。
@Servicepublic class JoinService { @Autowired PersonRepository personRepository; @Autowired private CompRepository compRepository; //退出公司操作,可从DelegateExecution获取流程中的变量 public void joinGroup(DelegateExecution execution) { Boolean bool = execution.getVariable("joinApproved",Boolean.class); if (bool) { Long personId = execution.getVariable("personId", Long.class); Long compId = execution.getVariable("compId",Long.class); Comp comp = compRepository.findById(compId).get(); Person person = personRepository.findById(personId).get(); person.setComp(comp); personRepository.save(person); System.out.println("退出组织胜利"); } else { System.out.println("退出组织失败"); } } //获取符合条件的审批人,演示不便这里写死,应用时利用理论代码 public List<String> findUsers(DelegateExecution execution) { return Arrays.asList("admin", "wtr"); }}
在joinGroup办法中能够通过入参DelegateExcution来获取流程中的参数。如果审批通过则在数据库中减少Person和Comp的关联,示意员工退出了公司。
查问历史记录
到上一步其实能够发现整个示例流程曾经完结。然而还有一个很重要的需要就是历史记录的查问,流程实例完结之后能够查问相干的历史记录,次要包含历史流程实例查问、历史流动实例查问、历史工作实例查问和历史流程变量查问等,这些办法都来自HistoryService。历史相干的数据库表以ACT_HI结尾,一共有8张历史记录相干的表。
值得一提的是正在运行中的流程相干信息由RuntimeService提供查问,而完结的流程信息才可能通过HistoryService获取到,信息存储在不同的数据表,这是为了缩小单表数据量提高效率,大部分的操作次要是对执行中流程的查问。因而在人工工作期待期间能够在act_ru_execution表中查到相干数据,而流程完结之后能够发现相干信息曾经从表中删除。
总结
看完上述内容,并且实际过示例流程后,置信曾经建设了对于Activiti的根本了解,对于创立、解决简略的流程应该不成问题,当然理论我的项目的利用须要解决的问题肯定不限于此,Activiti框架自身也不止于此。本文只是入门,想进一步理解还是应该查看官网文档、源码以及高阶的教程。
另外,官网下载的Activiti文件中蕴含了一个演示我的项目的war包:activiti-explorer.war,部署后能够在线编辑流程图,作为一个官网Demo也有助于疾速入门。部署也比较简单,在mysql中创立一个数据库,应用给予的sql文件创建Activiti相干的表,而后将war包解压置入tomcat,找到activiti-explorer\WEB-INF\classes下的db.properties配置文件并关上,批改数据库连贯信息如下。
db=mysqljdbc.driver=com.mysql.jdbc.Driverjdbc.url=jdbc:mysql://localhost:3306/activiti #更改为创立的数据库名jdbc.username=root #数据库用户jdbc.password=123456 #用户明码
复制mysql连贯的jar包mysql-connector-java-xxx.jar(没有的话先下载)到WEB-INF\lib目录下即可。启动tomcat,不出问题关上http://localhost:8080/activiti-explorer,应用用户kermit,明码kermit登录即可开始体验操作。