说明:

activiti -> activity

 

一、idea集成activity插件

1,File -> Settings -> Plugins -> 搜索actiBPM并安装:

java 调用activity工作流 activity工作流 idea_spring

安装好后,需要重启;

 

2,创建一个流程

项目工程 -> src/main/resources -> 右键鼠标:

java 调用activity工作流 activity工作流 idea_xml_02

 

java 调用activity工作流 activity工作流 idea_xml_03

java 调用activity工作流 activity工作流 idea_spring_04

 记得ctrl + s保存;

java 调用activity工作流 activity工作流 idea_java 调用activity工作流_05

 继续补全这个流程:

java 调用activity工作流 activity工作流 idea_java 调用activity工作流_06

 查看流程定义的xml:

java 调用activity工作流 activity工作流 idea_初始化_07

   

java 调用activity工作流 activity工作流 idea_springboot搭建_08

 

java 调用activity工作流 activity工作流 idea_java 调用activity工作流_09

 

 3,如果xml乱码了

java 调用activity工作流 activity工作流 idea_初始化_10

java 调用activity工作流 activity工作流 idea_java 调用activity工作流_11

或者:

java 调用activity工作流 activity工作流 idea_springboot搭建_12

 

二、pom引入依赖jar包

<!-- activiti 工作流需要依赖的jar -->
<dependency>
    <groupId>org.activiti</groupId>
    <artifactId>activiti-engine</artifactId>
    <version>${activiti-engine.version}</version>
</dependency>
<dependency>
    <groupId>org.activiti</groupId>
    <artifactId>activiti-spring</artifactId>
    <version>${activiti-spring.version}</version>
    <exclusions>
        <exclusion>
            <artifactId>spring-context</artifactId>
            <groupId>org.springframework</groupId>
        </exclusion>
    </exclusions>
</dependency>

如果maven你想使用另外一个settings.xml,可以把maven重新复制一遍,修改复制后的maven的settings.xml,

然后idea工作空间指定新的settings.xml;环境变量不需要重配,不影响拉取依赖jar包;

 

三、创建工作流配置文件

java 调用activity工作流 activity工作流 idea_初始化_13

 

java 调用activity工作流 activity工作流 idea_springboot搭建_14

 

java 调用activity工作流 activity工作流 idea_spring_15

 

四、一些准备工作

1,准备一些代码和页面

java 调用activity工作流 activity工作流 idea_java 调用activity工作流_16

 

java 调用activity工作流 activity工作流 idea_xml_17

 

五、初始化流程引擎

1,初始化前

我的数据库只有一张表:

java 调用activity工作流 activity工作流 idea_初始化_18

 

2,初始化

启动项目,加载activiti.cfg.xml,注入@Controller:

java 调用activity工作流 activity工作流 idea_springboot搭建_19

// 会默认按照Resources目录下的activiti.cfg.xml创建流程引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

初始化的过程中会自动创建工作流涉及的23张表;

初始化工作流引擎,也可以放在启动后;

java 调用activity工作流 activity工作流 idea_初始化_20

 

3,初始化后(即启动后)

 

java 调用activity工作流 activity工作流 idea_xml_21

只有这个表有数据:

java 调用activity工作流 activity工作流 idea_spring_22

 

 六、发布部署流程

java 调用activity工作流 activity工作流 idea_springboot搭建_23

java 调用activity工作流 activity工作流 idea_spring_24

 

java 调用activity工作流 activity工作流 idea_spring_25

查看数据库表变化:

java 调用activity工作流 activity工作流 idea_xml_26

java 调用activity工作流 activity工作流 idea_java 调用activity工作流_27

java 调用activity工作流 activity工作流 idea_java 调用activity工作流_28

其他表都为空;

 

七、启动流程

java 调用activity工作流 activity工作流 idea_spring_29

java 调用activity工作流 activity工作流 idea_初始化_30

 

java 调用activity工作流 activity工作流 idea_xml_31

 查看数据库表变化:

 

java 调用activity工作流 activity工作流 idea_springboot搭建_32

java 调用activity工作流 activity工作流 idea_java 调用activity工作流_33

java 调用activity工作流 activity工作流 idea_springboot搭建_34

java 调用activity工作流 activity工作流 idea_java 调用activity工作流_35

java 调用activity工作流 activity工作流 idea_初始化_36

 

八、user办理任务

1,但是我忘记指定代理人了,修改工作流配置后,需要重新发布工作流,所以我又把上面的流程重新走了一遍:

java 调用activity工作流 activity工作流 idea_java 调用activity工作流_37

java 调用activity工作流 activity工作流 idea_spring_38

 重新走了一遍之后:

 启动流程后变化:

java 调用activity工作流 activity工作流 idea_java 调用activity工作流_39

有些表的这个字段会更新:比如

java 调用activity工作流 activity工作流 idea_java 调用activity工作流_40

 

java 调用activity工作流 activity工作流 idea_java 调用activity工作流_41

 

2,代理人办理任务

java 调用activity工作流 activity工作流 idea_xml_42

 

java 调用activity工作流 activity工作流 idea_xml_43

 

java 调用activity工作流 activity工作流 idea_java 调用activity工作流_44

 

java 调用activity工作流 activity工作流 idea_初始化_45

 

java 调用activity工作流 activity工作流 idea_java 调用activity工作流_46

 查看数据库表变化:

java 调用activity工作流 activity工作流 idea_xml_47

 

java 调用activity工作流 activity工作流 idea_java 调用activity工作流_48

java 调用activity工作流 activity工作流 idea_springboot搭建_49

java 调用activity工作流 activity工作流 idea_java 调用activity工作流_50

 

java 调用activity工作流 activity工作流 idea_初始化_51

 

九、查看流程图

java 调用activity工作流 activity工作流 idea_xml_52

 

java 调用activity工作流 activity工作流 idea_初始化_53

 

十、代理人继续办理业务

java 调用activity工作流 activity工作流 idea_springboot搭建_54

java 调用activity工作流 activity工作流 idea_spring_55

 

java 调用activity工作流 activity工作流 idea_java 调用activity工作流_56

java 调用activity工作流 activity工作流 idea_java 调用activity工作流_57

 

java 调用activity工作流 activity工作流 idea_xml_58

流程走到这儿,再看下数据库表格变化:

java 调用activity工作流 activity工作流 idea_java 调用activity工作流_59

java 调用activity工作流 activity工作流 idea_java 调用activity工作流_60

 

java 调用activity工作流 activity工作流 idea_java 调用activity工作流_61

java 调用activity工作流 activity工作流 idea_初始化_62

 

java 调用activity工作流 activity工作流 idea_spring_63

java 调用activity工作流 activity工作流 idea_xml_64

 

java 调用activity工作流 activity工作流 idea_xml_65

 让“丹丹姐”完成她名下的待办任务:

java 调用activity工作流 activity工作流 idea_spring_66

至此,这个流程结束了:

java 调用activity工作流 activity工作流 idea_springboot搭建_67

java 调用activity工作流 activity工作流 idea_springboot搭建_68

 

java 调用activity工作流 activity工作流 idea_初始化_69

 

java 调用activity工作流 activity工作流 idea_spring_70

 

java 调用activity工作流 activity工作流 idea_spring_71

java 调用activity工作流 activity工作流 idea_spring_72

 

java 调用activity工作流 activity工作流 idea_java 调用activity工作流_73

 

十一、遇到的问题

1,项目启动的时候,通过@ImportResource加载xml,同时加载transaction.xml和activiti.cfg.xml:

java 调用activity工作流 activity工作流 idea_java 调用activity工作流_74

 

 

java 调用activity工作流 activity工作流 idea_spring_75

java 调用activity工作流 activity工作流 idea_初始化_76

 transaction.xml依赖druidDataSource就没报错,但是activiti.cfg.xml的那个bean依赖druidDataSource就报错了,说这个bean不存在;

 可以试试,在@ImportResource的时候再加一个注解,指定在某个类之后;

2,项目启动后,工作流并没有自动创建那23张表格,并且报错了,说表不存在,是因为代码走到了

isEngineTablePresent() = true

 ,需要在配置文件里面如下配置:

   

java 调用activity工作流 activity工作流 idea_xml_77

 

 ;加了如上配置,启动成功并且自动创建了23张表后,需要注释掉这个配置,不然下次启动时会报错;

3,工作流可以重复发布,没注意过这些重复的工作流的processKey是不是一样的,启动流程的时候需要processKey;

4,相关代码,也是从网上抄的,稍微修改了下,什么异常处理、日志、代码规范都没有做,仅供参考,

     当然工作流还要很多api:

package com.springbootbuild.contoller.activiti;

import com.springbootbuild.entity.activity.WorkFlowTask;
import org.activiti.engine.*;
import org.activiti.engine.repository.DeploymentBuilder;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.task.Task;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import sun.misc.BASE64Encoder;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 工作流测试<br>
 * 示例从网上copy的
 *
 * @Date 2020/12/11
 */
@Controller
@RequestMapping("/activity")
public class ActivityController {
    // 会默认按照Resources目录下的activiti.cfg.xml创建流程引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

    /**
     * 发布流程<br>
     * 可以重复发布
     *
     * @param bpmnName 流程定义文件名称
     */
    @ResponseBody
    @RequestMapping(value = "/deployProcess", method = RequestMethod.POST)
    public Map<String, Object> deployProcess(@RequestParam("bpmnName") String bpmnName) {
        Map<String, Object> responseMap = new HashMap<String, Object>();

        RepositoryService repositoryService = processEngine.getRepositoryService();
        DeploymentBuilder builder = repositoryService.createDeployment();
        builder.addClasspathResource(bpmnName);
        builder.deploy();

        responseMap.put("msg", "发布流程成功");
        return responseMap;
    }

    /**
     * 启动流程
     *
     * @param processKey 流程key
     */
    @ResponseBody
    @RequestMapping(value = "/startProcessByKey", method = RequestMethod.POST)
    public Map<String, Object> startProcessByKey(@RequestParam("processKey") String processKey) {
        Map<String, Object> responseMap = new HashMap<String, Object>();

        RuntimeService runtimeService = processEngine.getRuntimeService();
        runtimeService.startProcessInstanceByKey(processKey);

        responseMap.put("msg", "启动流程成功");
        return responseMap;
    }

    /**
     * 查看任务
     *
     * @param assigneeName 代理人
     */
    @ResponseBody
    @RequestMapping(value = "/queryTask", method = RequestMethod.POST)
    public Map<String, Object> queryTask(@RequestParam("assigneeName") String assigneeName) {
        Map<String, Object> responseMap = new HashMap<String, Object>();

        // 根据assignee(代理人)查询任务
        TaskService taskService = processEngine.getTaskService();
        List<Task> tasks = taskService.createTaskQuery().taskAssignee(assigneeName).list();
        if (CollectionUtils.isEmpty(tasks)) {
            return responseMap;
        }

        List<WorkFlowTask> wfTaskList = new ArrayList<>();
        for (Task task : tasks) {
            wfTaskList.add(new WorkFlowTask(task.getId(), task.getName(), task.getAssignee(), task.getCreateTime()));
        }

        responseMap.put("msg", "成功! ");
        responseMap.put("taskList", wfTaskList);
        return responseMap;
    }

    /**
     * 办理任务
     *
     * @param taskId 任务id
     */
    @ResponseBody
    @RequestMapping(value = "/handleTask", method = RequestMethod.POST)
    public Map<String, Object> handleTask(@RequestParam("taskId") String taskId) {
        Map<String, Object> responseMap = new HashMap<String, Object>();

        // 根据上一步生成的taskId执行任务
        TaskService taskService = processEngine.getTaskService();
        taskService.complete(taskId);

        responseMap.put("msg", "办理任务成功");
        return responseMap;
    }

    /**
     * 查看流程图
     *
     * @param processKey 流程key
     */
    @ResponseBody
    @RequestMapping(value = "/getProcessView", method = RequestMethod.POST)
    public Map<String, Object> getProcessView(@RequestParam("processKey") String processKey) throws IOException {
        Map<String, Object> responseMap = new HashMap<String, Object>();

        // 根据流程key查询流程定义,发布了几次流程,这个list就有几个,不要重复发布流程
        List<ProcessDefinition> processList = processEngine.getRepositoryService()
                .createProcessDefinitionQuery()
                .processDefinitionKey(processKey)
                .orderByProcessDefinitionVersion().desc()
                .list();

        List<String> list = processEngine.getRepositoryService().getDeploymentResourceNames(processList.get(0).getDeploymentId());
        String resourceName = "";
        if (list != null && list.size() > 0) {
            for (String name : list) {
                if (name.indexOf(".png") >= 0) {
                    resourceName = name;
                }
            }
        }

        //获取图片的输入流
        InputStream in = processEngine.getRepositoryService().getResourceAsStream(processList.get(0).getDeploymentId(), resourceName);

        byte[] data = new byte[in.available()];
        in.read(data);

        BASE64Encoder encoder = new BASE64Encoder();
        String viewCode = "data:image/png;base64, " + encoder.encode(data);

        responseMap.put("viewCode", viewCode);
        responseMap.put("msg", "查询成功");
        return responseMap;
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
        <property name="jdbcDriver" value="oracle.jdbc.driver.OracleDriver"></property>
        <property name="jdbcUrl" value="jdbc:oracle:thin:@127.0.0.1:1521:orcl"></property>
        <property name="jdbcUsername" value=""></property>
        <property name="jdbcPassword" value=""></property>
        <!-- 不知道为什么,druidDataSource可以在transaction.xml使用,在这儿就不行 -->
        <!--<property name="dataSource" ref="druidDataSource"></property>-->
        <!-- isEngineTablePresent() = true,不会创建初始化表格,需要加下面这个属性
                表格创建好后,记得把下面一行注释了-->
        <!--<property name="databaseSchema" value="ACTIVITI"></property>-->
        <property name="databaseSchemaUpdate" value="true"></property>
    </bean>

</beans>