day58_BOS项目_10

  • 今天内容安排:
    • 1、流程变量(设置、获取)
    • 2、组任务操作(候选人、候选组)
    • 3、排他网关的使用
    • 4、spring 整合 activiti框架
    • 5、将activiti框架应用到bos项目中
    • 6、在bos项目中实现流程定义管理(部署、查询、查看png、删除)

1、流程变量(设置、获取)

之前的请假流程,是没有实际意义的,我们要使得我们流程变得有意义(有实际意义),需要在流程向下推进的过程中带着数据推进才有意义。如下图所示:

1.1、设置流程变量的方式

准备工作:重新新建一个数据库,名为activiti_day02,使用框架提供的sql文件建表,今天我们执行Windows批处理文件建表,再使用插件设计一个报销流程图。之后我们部署流程定义。 批处理文件内容如下: ActivitiAcutoCreateTable.bat

@echo off
title Activiti5-CreateTableProcess
color b
@echo activiti_day02数据库导入中...

mysql -uroot -proot activiti_day02 < activiti.mysql.create.engine.sql
mysql -uroot -proot activiti_day02 < activiti.mysql.create.history.sql
mysql -uroot -proot activiti_day02 < activiti.mysql.create.identity.sql

@rem pause

if "%OS%"=="Windows_NT" ENDLOCAL

一共有4种设置流程变量方式,实际开发中都会用到。

  • 方式一:启动流程实例时设置流程变量
    /**
     * 方式一:启动流程实例时设置流程变量
     */
    @Test
    public void test2() {
        String processDefinitionKey = "baoxiaoliucheng"; // 流程定义id
        Map<String, Object> variables = new HashMap<>(); // 注意:第二个参数是一个HashMap
        // 设置流程变量
        variables.put("key1", "value1");
        variables.put("key2", 100);
        ProcessInstance processInstance = processEngine.getRuntimeService().startProcessInstanceByKey(processDefinitionKey, variables);
        System.out.println(processInstance.getId());
    }
  • 方式二:办理任务时设置流程变量
    /**
     * 方式二:办理任务时设置流程变量
     */
    @Test
    public void test3() {
        String taskId = "106";
        Map<String, Object> variables = new HashMap<>(); // 注意:第二个参数是也一个HashMap
        // 设置流程变量
        variables.put("reason", "差旅费用");
        variables.put("money", 500);
        processEngine.getTaskService().complete(taskId, variables);
    }

就我们当前的报销场景来说,方式二:办理任务时设置流程变量更合理,因为我们在办报销任务的时候,浏览器端会给用户提供一个用户页面,在页面上有一个表单,在表单上可以填写报销原因、报销金额等信息。填写完表单后,一点击提交按钮,这个任务就办理了。所以方式二:办理任务时设置流程变量更合理。在服务器端会将表单提交过来的数据保存至数据库中。


  • 方式三:使用RuntimeService的set方法时设置流程变量
    /**
     * 方式三:使用RuntimeService的set方法时设置流程变量
     */
    @Test
    public void test4() {
        String executionId = "101"; // 流程实例id
        Map<String, Object> variables = new HashMap<>(); // 注意:第二个参数是也一个HashMap集合
        // 设置流程变量
        variables.put("审批意见", "报销原因不够详细");
        variables.put("user", new User(10, 25, "北京市朝阳区")); // 设置的是自定义的类型
        processEngine.getRuntimeService().setVariables(executionId, variables);
        // processEngine.getRuntimeService().setVariable(executionId, variableName, value); // 一个一个的设置
    }

注意:如果设置的是自定义的类型,如User,需要该类实现序列化接口。

  • 方式四:使用TaskService的set方法时设置流程变量
    /**
     * 方式四:使用TaskService的set方法时设置流程变量
     */
    @Test
    public void test5() {
        String taskId = "204"; // 任务id
        String variableName = "审批意见"; // 注意:在同一个流程实例里面,流程变量的key是不能重复的,若出现重复,会覆盖
        String value = "不批,需要详细写清楚报销原因";
        processEngine.getTaskService().setVariable(taskId, variableName, value);
    }

1.2、获取流程变量的方式

  • 方式一:使用RuntimeService的get方法时获取流程变量
    /**
     * 方式一:使用RuntimeService的get方法获取流程变量
     */
    @Test
    public void test6() {
        String executionId = "101"; // 流程实例id
        Map<String, Object> variables = processEngine.getRuntimeService().getVariables(executionId);
        System.out.println(variables); // Map集合的toString()方法比较友好,还可以看

        // 如果我们自己遍历Map:通过键找值
        Set<String> keySet = variables.keySet(); // 先获得键集合
        for (String key : keySet) {
            Object value = variables.get(key); // 通过键找值
            System.out.println(key + " = " + value); 
            // 注意:为了使得自定义的类型User打印出来的结果好看些,我们需要在User类中重写User的toString()方法,但是需要重新进行序列化,不然反序列化的时候会报错
        }
    }
  • 方式二:使用TaskService的get方法时获取流程变量
    /**
     * 方式二:使用TaskService的get方法时获取流程变量
     */
    @Test
    public void test7() {
        String taskId = "204"; // 任务id
        Object value = processEngine.getTaskService().getVariable(taskId , "user");
        System.out.println(value);
    }
  • 方式三:使用框架提供的表达式获取流程变量 示例演示的是:当创建任务的时候(即启动流程实例时),${variableName}表示activiti框架会拿着variableName(流程变量的name,即键key)到流程变量表中去找对应的name。其他的同理。 相应的代码截图:

相应的流程图截图:

相应的数据库表截图:

2、组任务操作(候选人、候选组)

2.1、候选人的组任务(了解)

示例代码如下:

package com.itheima.activiti.grouptask;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.repository.DeploymentBuilder;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.junit.Test;

/**
 * 组任务测试(候选人)
 * @author Bruce
 *
 */
public class GroupTaskTest {
    // 获取默认流程引擎(全局变量)
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

    /**
     * 部署流程定义
     */
    @Test
    public void test1() {
        DeploymentBuilder deploymentBuilder = processEngine.getRepositoryService().createDeployment();
        deploymentBuilder.addClasspathResource("com/itheima/activiti/grouptask/baoxiaoliucheng.bpmn");
        deploymentBuilder.addClasspathResource("com/itheima/activiti/variable/baoxiaoliucheng.png");
        deploymentBuilder.deploy();
    }

    /**
     * 启动流程实例时设置流程变量
     */
    @Test
    public void test2() {
        String processDefinitionKey = "baoxiaoliucheng"; // 流程定义id
        Map<String, Object> variables = new HashMap<>(); // 注意:第二个参数是一个HashMap集合
        // 设置流程变量
        variables.put("loginUser", "熊五");
        ProcessInstance processInstance = processEngine.getRuntimeService().startProcessInstanceByKey(processDefinitionKey, variables);
        System.out.println(processInstance.getId());
    }

    /**
     * 办理任务
     */
    @Test
    public void test3() {
        String taskId = "1002"; // 任务id
        processEngine.getTaskService().complete(taskId);
    }

    /**
     * 查询组任务
     *      如果财务二拾取了组任务,财务三就查询不到组任务了。
     */
    @Test
    public void test4() {
        TaskQuery query = processEngine.getTaskService().createTaskQuery();
        String candidateUser = "财务三";
        query.taskCandidateUser(candidateUser); // 使用候选人过滤
        List<Task> list = query.list();
        for (Task task : list) {
            System.out.println(task.getId());
        }
    }

    /**
     * 拾取组任务,即将组任务变为个人任务
     *      不能两个人拾取同一组任务,若拾取,框架会抛异常
     */
    @Test
    public void test5() {
        String taskId = "902";
        processEngine.getTaskService().claim(taskId , "财务二");
    }
}

候选人的组任务相对于个人任务来说,先进了一些,但是还不够灵活,虽然写了3个具体的人,但是一旦3个人中有人离职了,那么这个流程就不能正常运行了。于是,有个更加灵活的候选组的组任务。

2.2、候选组的组任务(重点)

示例代码如下:

package com.itheima.activiti.grouptask;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.identity.Group;
import org.activiti.engine.identity.User;
import org.activiti.engine.impl.persistence.entity.GroupEntity;
import org.activiti.engine.impl.persistence.entity.UserEntity;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.DeploymentBuilder;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.junit.Test;

/**
 * 组任务测试(候选组)
 * @author Bruce
 *
 */
public class GroupTaskTest2 {
    // 获取默认流程引擎(全局变量)
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

    /**
     * 部署流程定义
     */
    @Test
    public void test1() {
        DeploymentBuilder deploymentBuilder = processEngine.getRepositoryService().createDeployment();
        deploymentBuilder.addClasspathResource("com/itheima/activiti/grouptask/baoxiaoliucheng2.bpmn");
        deploymentBuilder.addClasspathResource("com/itheima/activiti/grouptask/baoxiaoliucheng2.png");
        deploymentBuilder.deploy();
    }

    /**
     * 创建组
     */
    @Test
    public void test2() {
        Group group = new GroupEntity(); // 注意:后期框架act_id_group表与BOS项目的auth_role同步
        group.setId("财务组"); // 与流程图的一致
        group.setName("管理财务");
        processEngine.getIdentityService().saveGroup(group);
    }

    /**
     * 创建用户
     */
    @Test
    public void test3() {
        User user = new UserEntity(); // 注意:后期框架act_id_user表与BOS项目的t_user同步
        user.setId("2");
        processEngine.getIdentityService().saveUser(user);
    }

    /**
     * 建立用户和组的关系
     */
    @Test
    public void test4() {
        processEngine.getIdentityService().createMembership("2", "财务组");
    }

    /**
     * 启动流程实例时设置流程变量
     */
    @Test
    public void test5() {
        String processDefinitionKey = "baoxiaoliucheng"; // 流程定义key
        Map<String, Object> variables = new HashMap<String, Object>();
        variables.put("loginUser", "晓艺");
        ProcessInstance pi = processEngine.getRuntimeService().startProcessInstanceByKey(processDefinitionKey, variables);
        System.out.println(pi.getId());
    }

    /**
     * 办理任务
     */
    @Test
    public void test6() {
        String taskId = "1605";
        processEngine.getTaskService().complete(taskId);
    }

    /**
     * 查询组任务
     */
    @Test
    public void test7() {
        TaskQuery query = processEngine.getTaskService().createTaskQuery();
        String candidateUser = "2";
        query.taskCandidateUser(candidateUser); // 使用候选人过滤,更实用直接,因为User是从session中取过来
        // query.taskCandidateGroup("财务组");  // 使用候选组过滤,Group是从角色中取过来,稍微麻烦些
        List<Task> list = query.list();
        for (Task task : list) {
            System.out.println(task.getId());
        }
    }

    /**
     * 拾取组任务,将组任务变为个人任务
     */
    @Test
    public void test8() {
        String taskId = "1702";
        processEngine.getTaskService().claim(taskId , "1");
    }

    /**
     * 删除 所有部署流程定义数据(带级联删除)
     */
    @Test
    public void test9() {
        List<Deployment> list = processEngine.getRepositoryService().createDeploymentQuery().list();
        for (Deployment deployment : list) {
            processEngine.getRepositoryService().deleteDeployment(deployment.getId(), true); 
        }
    }
}

3、排他网关的使用(常用)

示例代码如下:

package com.itheima.activiti.gateway;

import java.util.HashMap;
import java.util.Map;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.repository.DeploymentBuilder;
import org.activiti.engine.runtime.ProcessInstance;
import org.junit.Test;

/**
 * 排他网关的测试
 * @author Bruce
 *
 */
public class GatewayTest {
    // 获取默认流程引擎(全局变量)
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

    /**
     * 部署流程定义
     */
    @Test
    public void test1() {
        DeploymentBuilder deploymentBuilder = processEngine.getRepositoryService().createDeployment();
        deploymentBuilder.addClasspathResource("com/itheima/activiti/gateway/qingjialiucheng.bpmn");
        deploymentBuilder.addClasspathResource("com/itheima/activiti/gateway/qingjialiucheng.png");
        deploymentBuilder.deploy();
    }

    /**
     * 方式一:启动流程实例时设置流程变量
     */
    @Test
    public void test2() {
        String processDefinitionKey = "qingjialiucheng"; // 流程定义id
        Map<String, Object> variables = new HashMap<>(); // 注意:第二个参数是一个HashMap集合
        // 设置流程变量
        variables.put("qjts", 2);
        ProcessInstance processInstance = processEngine.getRuntimeService().startProcessInstanceByKey(processDefinitionKey, variables);
        System.out.println(processInstance.getId());
    }

    /**
     * 方式二:办理任务时设置流程变量
     */
    @Test
    public void test3() {
        String taskId = "2005"; // 任务id
        Map<String, Object> variables = new HashMap<>(); // 注意:第二个参数是也一个HashMap集合
        // 设置流程变量
        variables.put("qjts", 5);
        processEngine.getTaskService().complete(taskId, variables);
    }
}

4、spring 整合 activiti框架

步骤一:读取(加载)spring配置文件,使用spring提供的流程引擎配置对象 步骤二:提供数据源和事务管理器 步骤三:使用spring提供的流程引擎工厂bean创建流程引擎对象 示例代码如下: applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:tx="http://www.springframework.org/schema/tx"
    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
                        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
                        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
    <!-- 配置流程引擎配置对象 -->
    <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
        <!-- 注入数据源 -->
        <property name="dataSource" ref="dataSource"></property>
        <!-- 注入事务管理器对象 -->
        <property name="transactionManager" ref="transactionManager"></property>
        <!-- 开启自动建表 -->
        <property name="databaseSchemaUpdate" value="true"/>
    </bean>

    <!-- 使用工厂创建流程引擎对象 -->
    <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
        <property name="processEngineConfiguration" ref="processEngineConfiguration"></property>
    </bean>

    <!-- 注册一个数据源:暂时使用Spring框架提供的 (实际用的是c3p0)-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/activiti_day02"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>
    <!-- 注册事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
</beans>

步骤四:读取spring配置文件,创建spring工厂,从工厂中获得默认流程引擎对象

package com.itheima.activiti.spring;

import java.util.List;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.repository.ProcessDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringActivitiTest {

    public static void main(String[] args) {
        // 读取(加载)spring配置文件,创建spring工厂
        ApplicationContext ctx = new ClassPathXmlApplicationContext("com\\itheima\\activiti\\spring\\applicationContext.xml");
        // 从工厂中获得默认流程引擎对象
        ProcessEngine processEngine = (ProcessEngine) ctx.getBean("processEngine");
        List<ProcessDefinition> list = processEngine.getRepositoryService().createProcessDefinitionQuery().list();
        for (ProcessDefinition processDefinition : list) {
            System.out.println(processDefinition);
        }
    }
}

5、将activiti框架应用到bos项目中

5.1、查询流程定义

第一步:添加jar包,修改Spring配置文件,测试整合是否成功,在UserAction中通过注解注入ProcessEngine,在登录的时候打印输出该对象,能打印出来,说明整合成功,否则失败。 第二步:修改admin.json,加入工作流相关的菜单

浏览器显示效果如下:

第三步:在spring配置文件中配置activiti框架使用的Service

第四步:提供ProcessDefinitionAction,使用注解注入RepositoryService,提供list()方法

package com.itheima.bos.web.action;

import java.util.List;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

/**
 * 流程定义管理
 * @author Bruce
 *
 */
@Controller
@Scope("prototype")
public class ProcessDefinitionAction extends ActionSupport { // 我们不用去继承BaseAction<T>,因为我们没有合适的模型对象来对应

    // 注入流程引擎
    // @Autowired
    // private ProcessEngine processEngine; 

    // 注入Service
    @Autowired
    private RepositoryService repositoryService;
    /**
     * 查询最新版本的流程定义列表数据
     * @return
     */
    public String list() {
        // 创建流程定义查询对象
        // ProcessDefinitionQuery query = processEngine.getRepositoryService().createNativeProcessDefinitionQuery();
        // 我们发现,在Action中注入流程引擎后,每次使用都是通过流程引擎getXxxService,那么我们直接注入Service该多好啊!!!
        ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery();
        query.latestVersion(); // 查询最新版本的流程定义
        query.orderByProcessDefinitionName().desc(); // 根据流程定义名称降序
        List<ProcessDefinition> list = query.list(); // 执行查询,获得流程定义列表数据
        // 将流程定义列表数据压入值栈
        ActionContext.getContext().getValueStack().set("list", list); 
        return "list";
    }
}

第五步:配置struts.xml

    <!-- 流程定义管理:配置processDefinitionAction-->
    <action name="processDefinitionAction_*" class="processDefinitionAction" method="{1}">
        <result name="list">/WEB-INF/pages/workflow/processdefinition_list.jsp</result>
    </action>

第六步:提供processdefinition_list.jsp页面,展示流程定义列表数据

注意:上述流程列表页面使用的是jQuery easyUI 数据网格控件 datagrid,我们这里使用的是datagrid显示数据的方式一:将HTML代码渲染成datagrid样式,为什么呢? 答:因为我们看到的代码<s:iterator>...</s:iterator>不是最终效果,因为jsp其实是一个类,是一个servlet,这句代码<s:iterator>...</s:iterator>实际上是运行在服务端的,在服务端计算出Html代码,计算完毕后,生成静态代码发回给浏览器进行显示。所以说,我们浏览器接收到的是静态的Html代码。 浏览器显示效果:

5.2、部署流程定义(即发布新流程)

FreeMarke(模板引擎)简介:

  • 我们通常看到的购物网站,比如淘宝,我们看见的每一个页面的格式都差不多,怎么做的呢?
  • 答:使用模板技术。静态的模板 + 动态的数据 = html页面。所以我们在淘宝上看到的页面就是静态的,淘宝后台有商品发布系统。
  • 比如:一个商品上架会向数据库中插入一条数据,并在web服务器里面生成一个静态页面。
    • 参考链接:https://freemarker.apache.org/
  • 比如:我们使用的struts标签,其实也是模板,我们只需要给它动态的数据,它就可以形成静态的网页(html代码),浏览器一解析,就显示出来了。
    • 模板文件的后缀名为:xxx.ftl。

第一步:提供部署流程定义页面 文件位置:/bos19/WebContent/WEB-INF/pages/workflow/processdefinition_deploy.jsp

<s:form action="processDefinitionAction_deploy" theme="simple" 
        method="post" enctype="multipart/form-data" id="uploadForm">
    <table class="table-edit" width="100%" >
        <tr class="title"><td colspan="2">发布新流程</td></tr>
        <tr>
            <td width="200">浏览流程定义的zip压缩文件</td>
            <td>
                <input type="file" name="zipFile" />
            </td>
        </tr>
        <tr>
            <td colspan="2">
                <a id="btn" href="javascript:$('#uploadForm').submit();" 
                   class="easyui-linkbutton" data-options="iconCls:'icon-save'">发布新流程</a>  
            </td>
        </tr>
    </table>
</s:form>

第二步:在ProcessDefinitionAction中提供deploy()方法,提供zipFile的属性和相应的set方法接收上传的文件

    // 提供zipFile的属性和相应的set方法接收上传的文件
    private File zipFile;
    public void setZipFile(File zipFile) {
        this.zipFile = zipFile;
    }

    /**
     * 部署流程定义(即发布新流程)
     * @return
     * @throws FileNotFoundException
     */
    public String deploy() throws FileNotFoundException {
        DeploymentBuilder deploymentBuilder = repositoryService.createDeployment();
        deploymentBuilder.addZipInputStream(new ZipInputStream(new FileInputStream(zipFile)));
        deploymentBuilder.deploy();
        return "toList";
    }

第三步:配置struts.xml

    <!-- 流程定义管理:配置processDefinitionAction-->
    <action name="processDefinitionAction_*" class="processDefinitionAction" method="{1}">
        <result name="list">/WEB-INF/pages/workflow/processdefinition_list.jsp</result>
        <result name="toList" type="redirectAction"> <!-- 请求重定向 -->
            processDefinitionAction_list
        </result>
    </action>

5.3、查看png图片

第一步:修改jsp页面中弹出窗口的效果

第二步:在Action中提供showpng()方法,提供id属性和对应的set方法,用于接收页面提交过来的参数:流程定义id

    /**
     * 展示png图片
     */
    public String showpng() {
        // 获取png图片对应的输入流(根据流程定义id获取)
        InputStream pngStream = repositoryService.getProcessDiagram(id);
        // 使用Struts框架提供的文件下载功能(文件下载结果集):通过输出流把服务端的资源写到客户端
        // 先把输入流压入值栈
        ActionContext.getContext().getValueStack().set("pngStream", pngStream);
        return "showpng";
    }

第三步:配置struts.xml,配置struts文件下载结果集

    <!-- 流程定义管理:配置processDefinitionAction-->
    <action name="processDefinitionAction_*" class="processDefinitionAction" method="{1}">
        <result name="list">/WEB-INF/pages/workflow/processdefinition_list.jsp</result>
        <result name="toList" type="redirectAction"> <!-- 请求重定向 -->
            processDefinitionAction_list
        </result>
        <result name="showpng" type="stream">
            <param name="contentType">image/png</param>
            <param name="inputName">pngStream</param><!-- 输入流压栈时起的名字 -->
            <!-- 
            <param name="contentDisposition">attachment;filename="abc.png"</param>
            <param name="bufferSize">1024</param>
             -->
        </result>
    </action>

5.4、删除流程定义

第一步:在jsp页面中提供删除按钮,指定onclick事件

定义删除方法

第二步:在Action中提供delete()方法

    /**
     * 删除流程定义(即删除流程部署定义)
     */
    public String delete() {
        String deltag = "0"; // 设置删除标志
        // 根据流程定义id获取部署id
        ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery(); // 创建流程定义查询对象
        query.processDefinitionId(id); // 根据流程定义id过滤
        ProcessDefinition processDefinition = query.singleResult(); // 得到流程定义对象
        String deploymentId = processDefinition.getDeploymentId(); // 根据流程定义id获取部署id
        try {
            repositoryService.deleteDeployment(deploymentId);
        } catch (Exception e) {
            // 说明当前删除的流程定义正在使用
            deltag = "1";
            // 把删除标志位存进值栈,便于页面取出来判断
            ActionContext.getContext().getValueStack().set("deltag", deltag);

            // 重新查询最新版本的流程定义列表数据
            ProcessDefinitionQuery query2 = repositoryService.createProcessDefinitionQuery();
            query2.latestVersion(); // 查询最新版本的流程定义
            query2.orderByProcessDefinitionName().desc(); // 根据流程定义名称降序
            List<ProcessDefinition> list = query2.list(); // 执行查询,获得列表数据
            // 将列表数据压入值栈
            ActionContext.getContext().getValueStack().set("list", list); 
            return "list";
        }
        return "toList"; // 正常删除,页面发生变化,需要请求重定向
    }

第三步:在jsp页面中根据deltag标志位判断删除是否成功 注意:下面的代码只能放到页面的最后面,不然会出现提示信息无法显示的问题,可能与js的加载顺序有关,之前我们写的代码放到了onload()里面,所以没有出现问题。

<script type="text/javascript">
    // 获取服务器响应回来的删除标志位
    var deltag = '${deltag}';
    // alert(deltag);
    if (deltag == '1') {
        // 存在关联数据,不能删除
        $.messager.alert("提示信息","当前流程定义正在使用,不能删除!","warning");
    }
</script>

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏闻道于事

多线程基础必要知识点!看了学习多线程事半功倍

3483
来自专栏Java成神之路

【转】 Java 多线程之一

进程:一个计算机程序的运行实例,包含了需要执行的指令;有自己的独立地址空间,包含程序内容和数据;不同进程的地址空间是互相隔离的;进程拥有各种资源和状态信息,包括...

1103
来自专栏LEo的网络日志

shell技巧分享(六)

1545
来自专栏顶级程序员

为什么文件名要小写?

来自:阮一峰的网络日志 链接:www.ruanyifeng.com/blog/2017/02/filename-should-be-lowercase.htm...

2985
来自专栏大内老A

ASP.NET Core中如影随形的”依赖注入”[上]: 从两个不同的ServiceProvider说起

我们一致在说 ASP.NET Core广泛地使用到了依赖注入,通过前面两个系列的介绍,相信读者朋友已经体会到了这一点。由于前面两章已经涵盖了依赖注入在管道构建过...

4187
来自专栏王清培的专栏

.NET/ASP.NET MVC Controller 控制器(深入解析控制器运行原理)

阅读目录: 1.开篇介绍 2.ASP.NETMVC Controller 控制器的入口(Controller的执行流程) 3.ASP.NETMVC Contro...

2096
来自专栏zingpLiu

浅析Python多线程

学习Python多线程的资料很多,吐槽Python多线程的博客也不少。本文主要介绍Python多线程实际应用,且假设读者已经了解多线程的基本概念。如果读者对进程...

2158
来自专栏码神联盟

面试题 | 《Java面试题集》-- 第三套

varchar2分别在oracle的sql和pl/sql中都有使用,oracle 在sql参考手册和pl/sql参考手册中指出:oracle sql varch...

1522
来自专栏逸鹏说道

C# 温故而知新: 线程篇(四)

线程同步篇 (中):同步工具类的介绍 1 上篇回顾 2 继续介绍基元内核模式中的 monitor类 3 同步句柄:WaitHandle 4 EventW...

3136
来自专栏测试开发架构之路

【总结】梳理下接口功能测试

1403

扫码关注云+社区

领取腾讯云代金券