activiti初使用

这周开始使用activiti工作流。任务要求:做一个二级审批流程(可驳回)

遇到的一些问题:

  • IDEA集成activiti,2019版本的IDEA插件商店和别的版本不同。
  • bpmn会出现乱码问题,需要更改IDEA的相关配置文件
  • activiti操作数据库会出现乱码问题,需要在activiti.cfg.xml中URL那里配置编码信息
  • activiti.cfg.xml必须在资源根路径下,看它的源码是这样规定的,也就是要在resources下
  • activiti是有官网的
  • 看不懂官网上7的教程
  • 5,6版本有官方教程和API,在官网首页的下部
  • 5,6版本的activiti和7差异较大
  • 7版本的activiti整合spring boot的时候是默认集成spring security。所以启动项目会被拦截到一个登录页面上面。需要去关闭security的配置。或者更换版本。
  • 看官方API的时候,查找某个方法很麻烦,其实API有个index的索引,里面可以直接用CTRL+F来搜索相关方法。
  • spring boot的控制器层的类,注解失效,是因为把启动类的路径放的过深,这样自动装配没法扫描到这些类,它只会扫描本包下的类。
  • gson的使用,因为传回前端的key是无规律的。所以不知道怎么拿数据。最后直接把整段json展示在文本域中,没有进行处理。

最开始跟着网上的教程手把手教你如何玩转Activiti工作流_Cs_hnu_scw的博客-CSDN博客_activiti工作流
以及B站视频黑马程序员java教程最新工作流引擎Activiti7基础到进阶,Activiti和Spring框架、SpringBoot整合_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili

跟着敲的一些基础的测试用例,大概对activiti的工作流程有所了解,使用activiti对固定的工作流程进行CRUD会很方便,尤其是OA系统。但是对activiti的各个表之间的关系还是不够熟悉。以及流程引擎的各种常用API不熟练。

然后试着去若依官网找扩展项目activiti的时候,没能成功运行起来相关的activiti开源项目。
其中vue前后端分离版本。缺少node_module,原因是没下载相关包,需要npm install。因为为了减少项目大小,所以一般都会把这个包删掉。只要package.json存在就可以,类似pom.xml文件。

最后前端写一些表单和后端进行交互。
参考:
Activiti工作流几种驳回方式的实现与比较 - kongbin - 博客园

测试用例代码

public class ActivitiDemo  {

    /**
     * 流程定义部署
     */
    @Test
    public void createProcess(){

        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        RepositoryService repositoryService = processEngine.getRepositoryService();

        Deployment deploy = repositoryService.createDeployment()
                .addClasspathResource("diagrams/evection.bpmn")
                .addClasspathResource("diagrams/evection.png")
                .name("出差申请")
                .deploy();

        System.out.println("流程部署id:" + deploy.getId());
        System.out.println("流程部署名称:" + deploy.getName());

    }

    /**
     * 启动流程实例
     */
    @Test
    public void startProcess(){
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        RuntimeService runtimeService = processEngine.getRuntimeService();
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("myEvention");
        System.out.println("流程定义id:" + processInstance.getProcessDefinitionId());
        System.out.println("流程实例id:" + processInstance.getId());
        System.out.println("当前活动id:" + processInstance.getActivityId());
    }


    /**
     * 任务负责人查询自己需要处理的任务
     */
    @Test
    public void findPersonalTaskList(){
        String assignee = "zhangsan";
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        TaskService taskService = processEngine.getTaskService();
        List<Task> list = taskService.createTaskQuery()
                .processDefinitionKey("myEvention")
                .taskAssignee(assignee)
                .list();

        for (Task task : list){
            System.out.println("流程实例id:" + task.getProcessInstanceId());
            System.out.println("任务id:" + task.getId());
            System.out.println("任务负责人:" + task.getAssignee());
            System.out.println("任务名称:" + task.getName());
        }
    }


    /**
     * 负责人查询待办任务,选择任务进行处理,完成任务
     */
    @Test
    public void completTask(){
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        TaskService taskService = processEngine.getTaskService();

        Task task = taskService.createTaskQuery()
                .processDefinitionKey("myEvention")
                .taskAssignee("jerry")
                .singleResult();

        taskService.complete(task.getId());
    }


    /**
     * 查询流程相关信息,包含流程定义,流程部署,流程定义版本
     */
    @Test
    public void queryProcessDefinition(){
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        RepositoryService repositoryService = processEngine.getRepositoryService();
        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();

        List<ProcessDefinition> definitionList = processDefinitionQuery.processDefinitionKey("myEvention")
                .orderByProcessDefinitionVersion()
                .desc()
                .list();

        for (ProcessDefinition processDefinition : definitionList){
            System.out.println("流程定义 id="+processDefinition.getId());
            System.out.println("流程定义 name="+processDefinition.getName());
            System.out.println("流程定义 key="+processDefinition.getKey());
            System.out.println("流程定义 Version="+processDefinition.getVersion());
            System.out.println("流程部署ID ="+processDefinition.getDeploymentId());
        }
    }


    /**
     * 流程删除
     */
    @Test
    public void deleteDeployment(){
        String deploymentId = "1";

        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        RepositoryService repositoryService = processEngine.getRepositoryService();
        repositoryService.deleteDeployment(deploymentId);

    }

    /**
     * 启动流程实例,添加businessKey
     */
    @Test
    public void addBusinessKey(){
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        RuntimeService runtimeService = processEngine.getRuntimeService();
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("myEvention", "10001");
        System.out.println("业务id==" + processInstance.getBusinessKey());
    }


    /**
     * 查询流程实例
     */
    @Test
    public void queryProcessInstance(){
        String processDefinitionKey = "myEvention";

        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        RuntimeService runtimeService = processEngine.getRuntimeService();

        List<ProcessInstance> list = runtimeService
                .createProcessInstanceQuery()
                .processDefinitionKey(processDefinitionKey)//
                .list();

        for (ProcessInstance processInstance : list) {
            System.out.println("----------------------------");
            System.out.println("流程实例id:"
                    + processInstance.getProcessInstanceId());
            System.out.println("所属流程定义id:"
                    + processInstance.getProcessDefinitionId());
            System.out.println("是否执行完成:" + processInstance.isEnded());
            System.out.println("是否暂停:" + processInstance.isSuspended());
            System.out.println("当前活动标识:" + processInstance.getActivityId());
        }
    }

    /**
     * 审批驳回
     */
    @Test
    public void reject() {

        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        TaskService taskService = processEngine.getTaskService();
        HistoryService historyService = processEngine.getHistoryService();
        RuntimeService runtimeService = processEngine.getRuntimeService();
        RepositoryService repositoryService = processEngine.getRepositoryService();
        String taskId = "20002";//这里根据你自己的taskid来写
        Map variables = new HashMap<>();

        //获取当前任务
        HistoricTaskInstance currTask = historyService.createHistoricTaskInstanceQuery()
                .taskId(taskId)
                .singleResult();
        //获取流程实例
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(currTask.getProcessInstanceId())
                .singleResult();
        //获取流程定义
        ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
                .getDeployedProcessDefinition(currTask.getProcessDefinitionId());
        if (processDefinitionEntity == null) {
            System.out.println("不存在的流程定义。");

        }

        //获取当前activity
        ActivityImpl currActivity = ((ProcessDefinitionImpl) processDefinitionEntity)
                .findActivity(currTask.getTaskDefinitionKey());

        //获取当前任务流入
        List<PvmTransition> histTransitionList = currActivity
                .getIncomingTransitions();


        //清除当前活动出口
        List<PvmTransition> originPvmTransitionList = new ArrayList<PvmTransition>();
        List<PvmTransition> pvmTransitionList = currActivity.getOutgoingTransitions();
        for (PvmTransition pvmTransition : pvmTransitionList) {
            originPvmTransitionList.add(pvmTransition);
        }
        pvmTransitionList.clear();

        //查找上一个user task节点
        List<HistoricActivityInstance> historicActivityInstances = historyService
                .createHistoricActivityInstanceQuery().activityType("userTask")
                .processInstanceId(processInstance.getId())
                .finished()
                .orderByHistoricActivityInstanceEndTime().desc().list();
        TransitionImpl transitionImpl = null;
        if (historicActivityInstances.size() > 0) {
            ActivityImpl lastActivity = ((ProcessDefinitionImpl) processDefinitionEntity)
                    .findActivity(historicActivityInstances.get(0).getActivityId());
            //创建当前任务的新出口
            transitionImpl = currActivity.createOutgoingTransition(lastActivity.getId());
            transitionImpl.setDestination(lastActivity);
        }else
        {
            System.out.println("上级节点不存在。");
        }
        variables = processInstance.getProcessVariables();
        // 完成任务
        List<Task> tasks = taskService.createTaskQuery()
                .processInstanceId(processInstance.getId())
                .taskDefinitionKey(currTask.getTaskDefinitionKey()).list();
        for (Task task : tasks) {
            taskService.complete(task.getId(), variables);
            historyService.deleteHistoricTaskInstance(task.getId());
        }

        // 恢复方向
        currActivity.getOutgoingTransitions().remove(transitionImpl);

        for (PvmTransition pvmTransition : originPvmTransitionList) {
            pvmTransitionList.add(pvmTransition);
        }
    }

}

前端index.html代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/jquery-3.6.0.min.js"></script>
</head>
<body>
<form>
    <div>
        <div>
            <label >事项名称:</label>
            <div>
                <input id="event" type="text" placeholder="请输入事项名称">
            </div>
        </div>

        <div>
            <label>请假原因:</label>
            <div>
                <textarea id="reason" type="text" placeholder="请输入请假原因"></textarea>
            </div>
        </div>
        <div >
            <label >是否报销:</label>
            <div>
                <label>
                    <input type="checkbox" value="yes" id="inlineCheckbox1">是</label>
            </div>
        </div>
        <div >
            <label >出行方式:</label>
            <div >
                <select class="form-control" id="way">
                    <option value="飞机">飞机</option>
                    <option value="动车">动车</option>
                </select>
            </div>
        </div>
        <div >
            <label >申请人:</label>
            <div >
                <input id="name" type="text" placeholder="请输入申请人">
            </div>
        </div>
        <button id="btnSubmit">提交</button>
    </div>
</form>

<button id="queryEvent" onclick="queryEventPage()">查询</button>
<button id="startEvent" onclick="startEvent()">开启</button>

<script type="text/javascript">
    var url = "../activiti/create";
    var startUrl = "../activiti/start";

    var params;

    $(function(){
        $("#btnSubmit").click(function () {
            var event = $("#event").val();
            var reason = $("#reason").val();
            var isPaid = $("#inlineCheckbox1").val();
            var way = $("#way").val();
            var name = $("#name").val();

            params = {
                event: event,
                reason: reason,
                isPaid : isPaid,
                way : way,
                name: name
            }
            console.log(params)

            $.post(url, params, function () {
                alert("你已经成功提交申请")
            })
        })
    })

    function queryEventPage() {
        window.location.href = "query.html"
    }

    function startEvent() {
        $.get(startUrl, function () {
            alert("你已经成功开启审批流程")
        })
    }
</script>
</body>
</html>

query.html代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/jquery-3.6.0.min.js"></script>
</head>
<body>

<form>
    <input type="text" id="queryName" />
</form>
<button id="btnQuery">查询</button>
<textarea id="queryResult"></textarea>

<form>
    <input type="text" id="completeId">
</form>
<button id="btnComplete">选择任务完成</button>
<button id="btnReturn">驳回指定任务</button>

<script>
    var queryUrl = "../activiti/query";
    var completeUrl = "../activiti/complete";
    var returnUrl = "../activiti/return"
    var name;
    var id;
    $(function(){
        $("#btnQuery").click(function () {
            name = $("#queryName").val();
            $.ajax({
                type : "POST", //提交方式
                url : queryUrl,//路径
                data : {
                    name : name
                },//数据,这里使用的是Json格式进行传输
                success : function(result) {//返回数据根据结果进行相应的处理
                    console.log(result)
                    $("#queryResult").val(result)
                }
            });

        })

        $("#btnComplete").click(function () {
            id = $("#completeId").val();
            $.ajax({
                type : "POST", //提交方式
                url : completeUrl,//路径
                data : {
                    id : id
                },//数据,这里使用的是Json格式进行传输
                success : function() {//返回数据根据结果进行相应的处理
                    alert("已完成"+id)
                }
            });
        })

        $("#btnReturn").click(function () {
            id = $("#completeId").val();
            $.ajax({
                type : "POST", //提交方式
                url : returnUrl,//路径
                data : {
                    id : id
                },//数据,这里使用的是Json格式进行传输
                success : function(result) {//返回数据根据结果进行相应的处理
                    alert("已驳回"+id + result)
                }
            });
        })
    })

</script>

</body>
</html>

后台控制器层代码

@RestController
@RequestMapping("/activiti")
public class ActivitiController {

    /**
     * 流程定义部署
     */
    @RequestMapping("/create")
    public void createProcess(Event event){

        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        RepositoryService repositoryService = processEngine.getRepositoryService();

        Deployment deploy = repositoryService.createDeployment()
                .addClasspathResource("diagrams/evection.bpmn")
                .addClasspathResource("diagrams/evection.png")
                .name(event.getEvent())
                .deploy();

        System.err.println(deploy);

    }

    /**
     * 启动流程实例
     */
    @RequestMapping("/start")
    public void startProcess(){
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        RuntimeService runtimeService = processEngine.getRuntimeService();
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("myEvention");
    }


    /**
     * 任务负责人查询自己需要处理的任务
     */
    @RequestMapping("/query")
    public String queryProcess(@Param("name") String name){
        String assignee = name;
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        TaskService taskService = processEngine.getTaskService();
        List<Task> list = taskService.createTaskQuery()
                .processDefinitionKey("myEvention")
                .taskAssignee(assignee)
                .list();
        System.err.println(list);

        Map<String, String> map = new HashMap<>();
        for (Task task : list){
            map.put(task.getId(), task.getName());
        }
        return new Gson().toJson(map);
    }


    /**
     * 负责人查询待办任务,选择任务进行处理,完成任务
     */
    @RequestMapping("/complete")
    public void completTask(@Param("id") String id){
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        TaskService taskService = processEngine.getTaskService();

        taskService.complete(id);
    }

    /**
     * 驳回功能
     * @param id
     */
    @RequestMapping("/return")
    public String rollBackWorkFlow(String id) {

        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        TaskService taskService = processEngine.getTaskService();
        HistoryService historyService = processEngine.getHistoryService();
        RuntimeService runtimeService = processEngine.getRuntimeService();
        RepositoryService repositoryService = processEngine.getRepositoryService();
        try {
            Map<String, Object> variables;
            // 取得当前任务.当前任务节点
            HistoricTaskInstance currTask = historyService
                    .createHistoricTaskInstanceQuery().taskId(id)
                    .singleResult();
            // 取得流程实例,流程实例
            ProcessInstance instance = runtimeService
                    .createProcessInstanceQuery()
                    .processInstanceId(currTask.getProcessInstanceId())
                    .singleResult();
            if (instance == null) {
                return "ERROR";
            }
            variables = instance.getProcessVariables();
            // 取得流程定义
            ProcessDefinitionEntity definition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
                    .getDeployedProcessDefinition(currTask
                            .getProcessDefinitionId());
            if (definition == null) {
                return "ERROR";
            }
            // 取得上一步活动
            ActivityImpl currActivity = ((ProcessDefinitionImpl) definition)
                    .findActivity(currTask.getTaskDefinitionKey());

            //也就是节点间的连线
            List<PvmTransition> nextTransitionList = currActivity
                    .getIncomingTransitions();
            // 清除当前活动的出口
            List<PvmTransition> oriPvmTransitionList = new ArrayList<PvmTransition>();
            //新建一个节点连线关系集合

            List<PvmTransition> pvmTransitionList = currActivity
                    .getOutgoingTransitions();
            //
            for (PvmTransition pvmTransition : pvmTransitionList) {
                oriPvmTransitionList.add(pvmTransition);
            }
            pvmTransitionList.clear();

            // 建立新出口
            List<TransitionImpl> newTransitions = new ArrayList<TransitionImpl>();
            for (PvmTransition nextTransition : nextTransitionList) {
                PvmActivity nextActivity = nextTransition.getSource();
                ActivityImpl nextActivityImpl = ((ProcessDefinitionImpl) definition)
                        .findActivity(nextActivity.getId());
                TransitionImpl newTransition = currActivity
                        .createOutgoingTransition();
                newTransition.setDestination(nextActivityImpl);
                newTransitions.add(newTransition);
            }
            // 完成任务
            List<Task> tasks = taskService.createTaskQuery()
                    .processInstanceId(instance.getId())
                    .taskDefinitionKey(currTask.getTaskDefinitionKey()).list();
            for (Task task : tasks) {
                taskService.claim(task.getId(), task.getAssignee());
                taskService.complete(task.getId(), variables);
                historyService.deleteHistoricTaskInstance(task.getId());
            }
            // 恢复方向
            for (TransitionImpl transitionImpl : newTransitions) {
                currActivity.getOutgoingTransitions().remove(transitionImpl);
            }
            for (PvmTransition pvmTransition : oriPvmTransitionList) {
                pvmTransitionList.add(pvmTransition);
            }
            return "SUCCESS";
        } catch (Exception e) {
            return "ERROR";
        }
    }
}

posted @ 2021-03-31 13:30  张三丰学Java  阅读(537)  评论(0编辑  收藏  举报