Activiti项目是一项新的基于Apache许可的开源BPM平台,从基础开始构建,旨在提供支持新的BPMN 2.0标准,包括支持对象管理组(OMG),面对新技术的机遇,诸如互操作性和云架构,提供技术实现。
架构师Tom Baeyens说:“ Activiti有非常大的影响力来改变目前BPM的生态。Activiti的Apache授权,完整的功能,将使Activiti到达一个新的水平。Activiti将推动业界的创新,因为BPM技术可以广泛而自由地被应用。通过实现这些想法以及开源社区的努力,也让Activiti成为事实上的 BPM和BPMN标准执行“。
SpringSource的首席技术官Adrian Coyler说道:”这是一个对Spring开发人员和Java社区总体的发展非常令人兴奋的事情,长期以来一直需要一个Apache许可的流程引擎,这对许多应用系统非常实用的需求。我们认为,Activiti作为新的应用领域扩展到的Java和开源的发展,特别是在云架构上”。
扯的有点远了,Activiti7主要是分两大块 一、Activiti Cloud是一组从头开始设计的Cloud Native组件,可在分布式环境中使用。我们选择了Kubernetes作为我们的主要部署基础架构,并且我们将Spring Cloud / Spring Boot与Docker一起用于这些组件的容器化。但是GitHub上关注的人都很少,本次就忽略了。 二、Activiti Core就是对以前的版本进行了一些归纳和整理。也是今儿的主题。
Java8,Springboot2,Activiti7,druid1.1.16,mysql8
地址:http://start.spring.io/ 其它方式都行,具体...略...
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- 阿里 druid 数据源 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.activiti.dependencies</groupId>
<artifactId>activiti-dependencies</artifactId>
<version>7.1.0.M5</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter</artifactId>
<version>7.1.0.M5</version>
</dependency>
<!-- Activiti生成流程图 -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-image-generator</artifactId>
<version>7.1.0.M5</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- 工具jar Start -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.57</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!-- 工具jar end -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
因为acitviti是整合了springSecurity的,根据官方dome找到2个工具类:
把这个2个类注入到spring容器中。
我的是:
<?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="myProcess_1" name="My process" isExecutable="true">
<startEvent id="startevent1" name="Start"></startEvent>
<userTask id="usertask1" name="one" activiti:candidateGroups="activitiTeam"></userTask>
<sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow>
<userTask id="usertask2" name="two" activiti:candidateGroups="activitiTeam"></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_myProcess_1">
<bpmndi:BPMNPlane bpmnElement="myProcess_1" id="BPMNPlane_myProcess_1">
<bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
<omgdc:Bounds height="35.0" width="35.0" x="50.0" y="160.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
<omgdc:Bounds height="55.0" width="105.0" x="130.0" y="150.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2">
<omgdc:Bounds height="55.0" width="105.0" x="280.0" y="150.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
<omgdc:Bounds height="35.0" width="35.0" x="430.0" y="160.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
<omgdi:waypoint x="85.0" y="177.0"></omgdi:waypoint>
<omgdi:waypoint x="130.0" y="177.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
<omgdi:waypoint x="235.0" y="177.0"></omgdi:waypoint>
<omgdi:waypoint x="280.0" y="177.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
<omgdi:waypoint x="385.0" y="177.0"></omgdi:waypoint>
<omgdi:waypoint x="430.0" y="177.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
图:
很简单的一个流程。
@RunWith(SpringRunner.class)
@SpringBootTest
public class BootActivitiApplicationTests {
@Autowired
private ProcessRuntime processRuntime;
@Autowired
private TaskRuntime taskRuntime;
@Autowired
private SecurityUtil securityUtil;
@Autowired
private RepositoryService repositoryService;
@Test // 查看流程
public void contextLoads() {
securityUtil.logInAs("salaboy");
Page processDefinitionPage = processRuntime.processDefinitions(Pageable.of(0, 10));
System.err.println("已部署的流程个数:" + processDefinitionPage.getTotalItems());
for (Object obj : processDefinitionPage.getContent()) {
System.err.println("流程定义:" + obj);
}
}
}
如果你的版本和我是一样的话,多半就会报错,sql少字段。这个应该是一个官方的BUG,只需要在 act_re_deployment中加两个字段就好了: VERSION_和 PROJECT_RELEASE_VERSION_ 然后重新运行,应该就对了。但是打印的已部署个数却是0。说好的 processes 下自动部署呢,最后自己部署一下,发现一切都对了的。下面我给一些我测试的部署,查询,启动、执行的例子。
@RunWith(SpringRunner.class)
@SpringBootTest
public class BootActivitiApplicationTests {
@Autowired
private ProcessRuntime processRuntime;
@Autowired
private TaskRuntime taskRuntime;
@Autowired
private SecurityUtil securityUtil;
@Autowired
private RepositoryService repositoryService;
@Test // 部署流程
public void deploy() {
securityUtil.logInAs("salaboy");
String bpmnName = "MyProcess";
DeploymentBuilder deploymentBuilder = repositoryService.createDeployment().name("请假流程");
Deployment deployment = null;
try {
deployment = deploymentBuilder.addClasspathResource("processes/" + bpmnName + ".bpmn")
.addClasspathResource("processes/" + bpmnName + ".png").deploy();
} catch (Exception e) {
e.printStackTrace();
}
}
@Test // 远程外部BPMN
public void deploy2() {
securityUtil.logInAs("salaboy");
try {
Deployment deployment = null;
InputStream in = new FileInputStream(new File("C:\\Users\\飞牛\\git\\SpringBoot2_Activiti7\\src\\main\\resources\\processes\\leaveProcess.zip"));
ZipInputStream zipInputStream = new ZipInputStream(in);
deployment = repositoryService.createDeployment().name("请假流程2")
// 指定zip格式的文件完成部署
.addZipInputStream(zipInputStream).deploy();// 完成部署
zipInputStream.close();
} catch (Exception e) {
// TODO 上线时删除
e.printStackTrace();
}
}
@Test // 查看流程
public void contextLoads() {
securityUtil.logInAs("salaboy");
Page processDefinitionPage = processRuntime.processDefinitions(Pageable.of(0, 10));
System.err.println("已部署的流程个数:" + processDefinitionPage.getTotalItems());
for (Object obj : processDefinitionPage.getContent()) {
System.err.println("流程定义:" + obj);
}
}
@Test // 启动流程
public void startInstance() {
securityUtil.logInAs("salaboy");
ProcessInstance processInstance = processRuntime
.start(ProcessPayloadBuilder.start().withProcessDefinitionKey("myProcess_1").build());
System.err.println("流程实例ID:" + processInstance.getId());
}
@Test // 执行流程
public void testTask() {
securityUtil.logInAs("salaboy");
Page<Task> page = taskRuntime.tasks(Pageable.of(0, 10));
if (page.getTotalItems() > 0) {
for (Task task : page.getContent()) {
System.err.println("当前任务有1:" + task);
// 拾取
taskRuntime.claim(TaskPayloadBuilder.claim().withTaskId(task.getId()).build());
// 执行
taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(task.getId()).build());
}
} else {
System.err.println("没的任务1");
}
page = taskRuntime.tasks(Pageable.of(0, 10));
if (page.getTotalItems() > 0) {
for (Task task : page.getContent()) {
System.err.println("当前任务有2:" + task);
}
} else {
System.err.println("没的任务2");
}
}
}