Springboot2整合Activiti6工作流

简介


Activiti是领先的轻量级的,以Java为中心的开源BPMN(Business Process Modeling Notation)引擎,实现了真正的流程自动化。下面介绍如何在SpringBoot环境下使用Maven集成Activiti6,来实现一个简单的流程开发。

添加依赖(Springboot:2.2.1)


<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring-boot-starter-basic</artifactId>
            <version>6.0.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <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>

流程文件加创建或设置


SpringBoot集成activiti默认会从classpath下(如工程目录的resource目录)的processes目录下读取流程定义文件,所以需要在src/main/resources目录下添加processes目录,并在目录中创建流程文件。
tips:1、如果目录是其他位置,可在配置文件配置,配置项为:spring.activiti.process-definition-location-prefix;
2、Spring集成Activiti6默认支持 **.bpmn20.xml 和 **.bpmn 格式的流程定义文件,修改支持的文件格式,通过配置spring.activiti.process-definition-location-suffixes修改。
配置文件例如下:

#activiti配置
#是否自动检查、部署流程定义文件
spring.activiti.check-process-definitions=true
#自动更新数据库结构(默认是),生产环境时设置为false,减少启动时间。
spring.activiti.database-schema-update=true
#流程文件前缀和后缀(保存路径和文件名)
spring.activiti.process-definition-location-prefix=classpath:/processes/
spring.activiti.process-definition-location-suffixes=.bpmn20.xml,.bpmn

配置数据源


配置文件中配置一个数据源供使用。
注意,请配置全,不能跟单独的Springboot项目一样省略driver-class 和initial-size,而且url必须配置全,比如时区,否则启动会报错。

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/activiti?useUnicode=true&serverTimezone=Asia/Shanghai&characterEncoding=utf8&autoReconnect=true&useSSL=false&allowMultiQueries=true
spring.datasource.username=unm
spring.datasource.password=pwd
spring.datasource.tomcat.initial-size=4

创建一个流程


在processes文件夹下新建一个demo.bpmn文件,并编写一个简单的请假流程。

<?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="m1578292452475" name="" targetNamespace="http://www.activiti.org/test" typeLanguage="http://www.w3.org/2001/XMLSchema">
  <process id="demoProcess" name="请假流程" isClosed="false" isExecutable="true" processType="None">
    <startEvent id="start" name="startEvent"/>
    <sequenceFlow id="__4" sourceRef="start" targetRef="_1"/>
    <userTask activiti:exclusive="true" id="_1" name="领导审批" activiti:assignee="leader"/>
    <sequenceFlow id="__5" sourceRef="_1" targetRef="end"/>
    <endEvent id="end"/>
  </process>
</definitions>

启动测试


启动application时会报错:

java.lang.IllegalArgumentException: Could not find class [org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration]

解决方法:启动时排除这个类,修改注解:

@SpringBootApplication
改为
@SpringBootApplication(exclude = SecurityAutoConfiguration.class)

再次启动,已启动成功,检查数据库,表已建立。

编写接口


1、Task描述类 TaskRepresentation

@Data
@AllArgsConstructor
@NoArgsConstructor
public class TaskRepresentation {
    private String id;
    private String name;
}

2、控制器类 ProcessController

@RestController
@RequestMapping("/process")
public class ProcessController {

    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;

    /**
     * 发起一个请假流程。
     * @return 请假流程的id。
     */
    @GetMapping("/start")
    public ResponseEntity<String> startProcess(){
        //创建一个流程,参数key是bpmn文件内定义的流程的id。
        ProcessInstance pro = runtimeService.startProcessInstanceByKey("demoProcess");
        return ResponseEntity.ok(pro.getId());
    }

    /**
     * 获取待办任务列表
     * @param uid 用户id
     * @return
     */
    @GetMapping("/task/{uid}")
    public ResponseEntity<List<TaskRepresentation>> getTask(@PathVariable String uid) {
        List<Task> tasks = taskService.createTaskQuery().taskAssignee(uid).list();
        return ResponseEntity.ok(CommonUtil.transformTask(tasks));
    }

    /**
     * 审批通过
     * @param taskId
     * @return
     */
    @GetMapping("/task/apply/{taskId}")
    public ResponseEntity<String> apply(@PathVariable String taskId){
        taskService.complete(taskId);
        return ResponseEntity.ok("领导同意");
    }

}

3、Task转TaskRepresentation方法

public class CommonUtil {


    public static TaskRepresentation transformTask(Task task) {
        return new TaskRepresentation(task.getId(),task.getName());
    }

    public static List<TaskRepresentation> transformTask(List<Task> tasks){
        if (tasks != null) {
            final List<TaskRepresentation> list = new ArrayList<>();
            tasks.forEach(task -> {
                list.add(new TaskRepresentation(task.getId(),task.getName()));
            });
            return list;
        }else {
            return null;
        }
    }
}

接口测试


1、创建流程(注意,返回的是实例id)

http://localhost:8080/process/start
5001

2、查找待办流程(注意,这里的id是taskid,可以查看act_ru_task表)

http://localhost:8080/process/task/leader
[{“id”:“5005”,“name”:“领导审批”}]

3、审批同意(同意之后再调用上一步的接口时会发现,已无待办流程)

http://localhost:8080/process/task/apply/5005
领导同意

附:整个项目目录结构
image

至此,整合完毕。当然,离实际的应该还相差甚远,但是简单的流程已经可以走通,在此基础上进行拓展即可,欢迎用坑。

2 个赞