Spring Boot中使用Activiti的方法教程(二)

前言

前面一节我们已经了解了Activiti的基础概念,包括流程定义的用语和它的API功能,已经如何入手Activiti,在这一节我们将结合代码具体学习使用。小图是我们需要完成的请假流程图:

正如我们在图中看到的,这是一个非常简单的流程:员工提出休假请求,提供休假天数和开始日期。请求发送给经理。他们可以批准/拒绝该请求。

如果获得批准,则会定义一个服务任务serviceTask来发送确认电子邮件。如果被拒绝,员工可以选择修改并重新发送请求,也可以不执行任何操作。

此流程的BPMN 2.0定义文件VacationRequest.bpmn20.xml将start事件定义为:

<startEvent id="startEvent" name="请假" activiti:initiator="employeeName">
 <extensionElements>
  <activiti:formProperty id="numberOfDays" name="Number of days" type="long"
        required="true"/>
  <activiti:formProperty id="startDate" name="Vacation start date (MM-dd-yyyy)"
        type="date" datePattern="MM-dd-yyyy hh:mm" required="true"/>
  <activiti:formProperty id="reason" name="Reason for leave" type="string"/>
  <modeler:editor-resource-id><![CDATA[startEvent1]]></modeler:editor-resource-id>
 </extensionElements>
</startEvent>

分配给用户组“management”的第一个用户任务userTask将如下所示:

<userTask id="handle_vacation_request" name="申请请假">
 <documentation>${employeeName} 请假 ${numberOfDays} 天
  (Motivation: ${reason}).
 </documentation>
 <extensionElements>
  <activiti:formProperty id="vacationApproval"
        name="你要批准这个请假要求吗?"
        type="enum"
        required="true"/>
  <activiti:formProperty id="comments" name="经理的批示" type="string"/>
  <modeler:allow-send-email><![CDATA[true]]></modeler:allow-send-email>
  <modeler:activiti-idm-initiator><![CDATA[true]]></modeler:activiti-idm-initiator>
  <modeler:editor-resource-id>
   <![CDATA[sid-B9AA8E66-2F11-45D0-A270-B052E1A9248E]]></modeler:editor-resource-id>
 </extensionElements>
 <potentialOwner>
  <resourceAssignmentExpression>
   <formalExpression>management</formalExpression>
  </resourceAssignmentExpression>
 </potentialOwner>
</userTask>

使用ServiceTask,我们需要定义要执行的代码段。我们将SendEmailServiceTask.java类作为这段代码执行者。

<serviceTask id="send-email-confirmation" name="发送邮件确认"
    activiti:class="com.example.activitiwithspring.servicetasks.SendEmailServiceTask.java">
 <extensionElements>
  <modeler:editor-resource-id>
   <![CDATA[sid-2C5E1831-9101-4F70-9AEF-4BA72B704205]]></modeler:editor-resource-id>
 </extensionElements>
</serviceTask>

SendEmailServiceTask的代码如下:实现JavaDelegate接口,实现其execute方法:

public class SendEmailServiceTask implements JavaDelegate {

 public void execute(DelegateExecution execution) {
  //logic to sent email confirmation
 }

}

通过在“sequenceFlow”中添加“conditionExpression”标记来决定发送邮件在什么条件下触发,也就是定义一个条件流:

<sequenceFlow id="flow3" name="批准"
    sourceRef="sid-12A577AE-5227-4918-8DE1-DC077D70967C"
    targetRef="send-email-confirmation">
 <extensionElements>
  <modeler:editor-resource-id>
   <![CDATA[sid-609BEB69-E833-4D2F-BD14-FC8F7FD3E9C7]]></modeler:editor-resource-id>
 </extensionElements>
 <conditionExpression xsi:type="tFormalExpression">
  <![CDATA[${vacationApproved == 'true'}]]></conditionExpression>
</sequenceFlow>

这里,vacationApproved是上面的UserTask的formProperty。

部署流程

为了使我们的流程被Activiti Engine所知,我们需要部署该流程。我们可以使用RepositoryService以编程方式执行此操作。让我们编写一个JUnit测试来看看:

@Test
public void givenBPMN_whenDeployProcess_thenDeployed() {
 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
 RepositoryService repositoryService = processEngine.getRepositoryService();
 repositoryService.createDeployment()
  .addClasspathResource("org/activiti/test/vacationRequest.bpmn20.xml")
  .deploy();
 Long count = repositoryService.createProcessDefinitionQuery().count();
 assertTrue(count >= 1);
}

部署意味着引擎将解析BPMN流程定义文件并将其转换为可执行文件。此外,还会将记录添加到每个部署的Repository表中。之后,我们可以查询Repository服务从而获取已部署的进程:也就是ProcessDefinitions。

启动流程实例ProcessInstance

在将ProcessDefinition部署到Activiti Engine之后,我们可以通过创建ProcessInstances来执行该流程定义。如果说ProcessDefinition绘制的是一幅蓝图,那么processInstance就是它的执行实现。

对于一个ProcessDefinition,可以有多个ProcessInstances。

可以通过RuntimeService访问与ProcessInstances相关的所有详细信息。

在我们的示例中,在开始事件中,我们需要传递休假天数、开始日期和原因。我们将使用流程变量,并在创建ProcessInstance时传递它们。

编写一个JUnit测试用例实现上面想法:

@Test
public void givenDeployedProcess_whenStartProcessInstance_thenRunning() {
 //deploy the process definition
 Map<String, Object> variables = new HashMap >();
 variables.put("employeeName", "John");
 variables.put("numberOfDays", 4);
 variables.put("vacationMotivation", "I need a break!");

 RuntimeService runtimeService = processEngine.getRuntimeService();
 ProcessInstance processInstance = runtimeService
   .startProcessInstanceByKey("vacationRequest", variables);
 Long count=runtimeService.createProcessInstanceQuery().count();

 assertEquals("1", count.toString());
}

某个流程定义的多个实例将因流程变量而异,也就是说,同一份流程定义,因为变量不同,导致流程实例也会不同。

有多种方法启动流程实例,在这里,我们正在使用该流程的key:vacationRequest启动流程,启动流程实例后,我们可以通过查询RuntimeService来获取有关它的信息。

完成任务

当我们的流程实例开始运行时,第一步执行的是用户任务userTask,分配任务给用户组“management”的用户。该用户可能有一个收件箱,其中包含要由他们完成的任务列表。现在,如果我们想继续执行流程,则需要用户完成此任务。对于Activiti Engine,它被称为“完成任务”。

我们可以查询TaskService,获取任务对象,然后完成它。

@Test
public void givenProcessInstance_whenCompleteTask_thenGotNextTask() {
 // 部署流程并开始一个流程实例
 TaskService taskService = processEngine.getTaskService();
 List<Task> tasks = taskService.createTaskQuery()
   .taskCandidateGroup("management").list();
 Task task = tasks.get(0);

 Map<String, Object> taskVariables = new HashMap<>();
 taskVariables.put("vacationApproved", "false");
 taskVariables.put("comments", "We have a tight deadline!");
 taskService.complete(task.getId(), taskVariables);

 Task currentTask = taskService.createTaskQuery()
   .taskName("修改休假请求").singleResult();
 assertNotNull(currentTask);
}

请注意,TaskService的complete()方法也接受所需的流程变量。我们传递了经理的回复。

在此之后,流程引擎将继续下一步。在这里,下一步询问员工是否要重新发送休假请求。

因此,我们的ProcessInstance正在等待此UserTask,其名称为“修改休假请求”。

暂停和激活流程

我们可以暂停ProcessDefinition和ProcessInstance。如果我们暂停一个流程定义ProcessDefinition,则在它暂停挂起时我们就无法创建它的实例。我们可以使用RepositoryService来做到这一点:

@Test(expected = ActivitiException.class)
public void givenDeployedProcess_whenSuspend_thenNoProcessInstance() {
 // deploy the process definition
 repositoryService.suspendProcessDefinitionByKey("vacationRequest");
 runtimeService.startProcessInstanceByKey("vacationRequest");
}

要再次激活它,我们只需要调用其中一个repositoryService.activateProcessDefinitionXXX方法。

同样,我们可以使用RuntimeService暂停ProcessInstance 。

结论

在本文中,我们了解了如何将Activiti与Spring Boot结合使用。我们创建了一个示例ProcessEngineCofiguration文件,它可以帮助我们创建ProcessEngine。ProcessEngine提供的服务帮助我们管理和跟踪ProcessDefinitions,ProcessInstances,UserTasks等。

示例代码位于GitHub上。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • Spring Boot中使用activiti的方法教程(一)

    前言 Activiti API是一个工作流程(workflow)和业务流程管理(BPM)系统,可以定义流程.执行流程并以不同方式对其实现运行.使用API​​的开发可以在任何IDE中完成,但是要使用Activiti Designer需要Eclipse,IDEA中使用actiBPM插件. 定义流程有几种方式: 1. 使用BPMN 2.0标准在定义一个流程XML. 2. 使用StartEvent,EndEvent,UserTask,SequenceFlow等Java类. 如果我们想要运行进程或访问任何

  • Android实现Activities之间进行数据传递的方法

    本文实例讲述了Android实现Activities之间进行数据传递的方法.分享给大家供大家参考.具体分析如下: 首先,先说明一下Activity的启动及关闭: 1. startActivity(Intent intent);  启动Activity        finish();  结束当前Activity 2. startActivityForResult(Intent intent, int requestCode);  以指定的请求码requestCode启动Activity fini

  • Android开发之activiti节点跳转

    activiti使用的时候,通常需要跟业务紧密的结合在一起,有些业务非常的复杂,比如一个简单的采购流程:流程如下: 供应商上新商品的时候,提交商务审核,商务审核通过提交运营审核,审核失败退回供应商. 运营审核成功提交合同签订.交运营审核审核失败退回商务审核或者直接退回供应商. 合同签订审核通过结束,合同签订审核不通过返回运营审核或者退回商务审核,或者退回供应商. 上面的流程就出现了一个问题,什么问题呢? 我们来观察一下退回线的问题. 1.商务审核退回供应商上新. 2.运营审核可能退回商务审核,运

  • Activiti流程图查看实例

    本文实例展示了Activiti流程图查看的实现方法,具体步骤如下所示: 1.测试用例查看图片代码如下: public void viewImage() throws Exception { // 创建仓库服务对对象 RepositoryService repositoryService = processEngine.getRepositoryService(); // 从仓库中找需要展示的文件 String deploymentId = "701"; List<String&g

  • SpringBoot2整合activiti6环境搭建过程解析

    这篇文章主要介绍了SpringBoot2整合activiti6环境搭建过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 依赖 <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </d

  • 解决Springboot2.1.x配置Activiti7单独数据源问题

    1|1简介 最近基于最新的Activiti7配置了SpringBoot2. 简单上手使用了一番.发现市面上解决Activiti7的教程很少,采坑也比较多,在Activiti6配置数据源和Activiti7有所区别,基于Activiti6在Activiti7里是无法正常使用的.接下来让我们看下区别. 1|2问题 Activiti6多数据源配置 6的配置比较简单点. 先加入配置: # activiti 数据源 spring.datasource.activiti.driver=com.mysql.j

  • spring boot activiti工作流的搭建与简单使用

    前言 最近一直研究springboot,根据工作需求,工作流需要作为一个单独的微服务工程来提供给其他服务调用,现在简单的写下工作流(使用的activiti)微服务的搭建与简单使用 jdk:1.8 数据库:mysql  5.7 IDE:eclipse springboot:1.5.8 activiti:6.0.0 1.新建空白的maven微服务架构 新建maven项目的流程不在阐述,这里添加上activiti.myslq连接的依赖,只贴主要代码 pox.xml <project xmlns="

  • Spring Boot中使用Activiti的方法教程(二)

    前言 前面一节我们已经了解了Activiti的基础概念,包括流程定义的用语和它的API功能,已经如何入手Activiti,在这一节我们将结合代码具体学习使用.小图是我们需要完成的请假流程图: 正如我们在图中看到的,这是一个非常简单的流程:员工提出休假请求,提供休假天数和开始日期.请求发送给经理.他们可以批准/拒绝该请求. 如果获得批准,则会定义一个服务任务serviceTask来发送确认电子邮件.如果被拒绝,员工可以选择修改并重新发送请求,也可以不执行任何操作. 此流程的BPMN 2.0定义文件

  • 在Spring Boot中使用swagger-bootstrap-ui的方法

    swagger-bootstrap-ui 是基于swagger接口api实现的一套UI,因swagger原生ui是上下结构的,在浏览接口时不是很清晰,所以, swagger-bootstrap-ui 是基于左右菜单风格的方式,适用与我们在开发后台系统左右结构这种风格类似,方便与接口浏览 GitHub: https://github.com/xiaoymin/Swagger-Bootstrap-UI 界面预览: 引入swagger 在pom.xml文件中引入swagger以及ui的jar包依赖 <

  • 详解Spring Boot中MyBatis的使用方法

    orm框架的本质是简化编程中操作数据库的编码,发展到现在基本上就剩两家了,一个是宣称可以不用写一句SQL的hibernate,一个是可以灵活调试动态sql的mybatis,两者各有特点,在企业级系统开发中可以根据需求灵活使用.发现一个有趣的现象:传统企业大都喜欢使用hibernate,互联网行业通常使用mybatis. hibernate特点就是所有的sql都用Java代码来生成,不用跳出程序去写(看)sql,有着编程的完整性,发展到最顶端就是spring data jpa这种模式了,基本上根据

  • 在Spring Boot2中使用CompletableFuture的方法教程

    前言 在Spring Boot中有一个注释@Async,可以帮助开发人员开发并发应用程序.但使用此功能非常棘手.在本博客中,我们将了解如何将此功能与CompletableFuture一起使用.我认为你已经知道关于CompletableFuture的基础,所以我不会在这里重复这个概念. 首先,您需要使用@EnableAsync来注释您的应用程序类,这个注释告诉Spring查找使用@Async注释的方法并在单独的执行程序中运行它们. @SpringBootApplication @EnableAsy

  • Spring Boot中@ConditionalOnProperty的使用方法

    前言 在Spring Boot的自动配置中经常看到@ConditionalOnProperty注解的使用,本篇文章带大家来了解一下该注解的功能.下面话不多说了,来一起看看详细的介绍吧. Spring Boot中的使用 在Spring Boot的源码中,比如涉及到Http编码的自动配置.数据源类型的自动配置等大量的使用到了@ConditionalOnProperty的注解. HttpEncodingAutoConfiguration类中部分源代码: @Configuration(proxyBean

  • Spring Boot + Kotlin整合MyBatis的方法教程

    前言 最近使用jpa比较多,再看看mybatis的xml方式写sql觉得不爽,接口定义与映射离散在不同文件中,使得阅读起来并不是特别方便. 因此使用Spring Boot去整合MyBatis,在注解里写sql 参考<我的第一个Kotlin应用> 创建项目,在build.gradle文件中引入依赖 compile "org.mybatis.spring.boot:mybatis-spring-boot-starter:$mybatis_version" compile &qu

  • 关于spring boot中几种注入方法的一些个人看法

    前言 最近在知乎上面看到一篇关于程序员面试的问题,面试官问我们一般有几种注入的方法,这几种注入的方法分别在什么时候运用比合理,当时我看到这个时候懵逼了,由于我自己也是刚刚接触springboot不久,所以就自己在平时运用的上面总结了一些知识点常用的几种springboot的注入方法,由于我是一个小萌新,所只要是能够起道注入的方法的注解我都列出来,有可能会有错,希望大家能够及时提出来我来解决: @Autowired @Resource @Component @Configuration @Qual

  • Spring boot中使用ElasticSearch的方法详解

    0.版本选择 我这里选择了5.6.x,记得如果spring-boot-starter-parent是1.x可以选择2.x版本的elasticsearch,版本要对应,不然会有莫名其妙的问题 1.安装ElasticSearch https://www.elastic.co/downloads/past-releases windows 测试的,解压就能用 解压,到bin目录,双击elasticsearch.bat 1.1安装elasticsearch-head https://github.com

  • spring boot添加新模块的方法教程

    前言 在springboot项目框架里,把一个项目两大模块,主项目main和测试项目test,而我们的测试项目根据功能又可以再分,比如可以有单元测试,集成测试,业务测试等等. 对于一个初学者来说,建立模块的方式需要我们掌握,网上的资料不多,很少讲到这个功能点,大叔在这里普及一下! springboot项目基本结构如图: 下面我们来建立一个集成测试模块intTest,有的团队愿意叫它integTest,都可以,intTest这个名字来自于gradle官方的文档上,大叔也借鉴一下(https://d

随机推荐