Activiti工作流学习

    技术2022-07-13  81

    Activit版本:7.0 MySql版本:8.0.18 Ide:Idea 学习地址:https://www.bilibili.com/video/BV1Jt4y117BV?p=21

    一、Activiti工作流环境搭建

    1、准备工作1-1、在Idea中下载actiBPM插件。1-2、新建一个Maven工程1-3、导入配置文件1-4、代码创建工作流所需要的表结构(25张)1-5、数据表名称说明1-6、Activiti7.0接口说明1-7、Activiti流程定义 二、Activiti应用2-1、流程定义部署2-1-1、单个流程部署2-1-2、压缩包形式批量部署 2-2、启动一个流程实例2-3、指定用户任务列表查询2-4、任务完成处理 三、Activiti操作3-1、流程定义信息查询3-2、流程删除3-3、流程图展示

    1、准备工作

    1-1、在Idea中下载actiBPM插件。

    Idea插件库自己搜索下载就行了。安装完成后别忘了重启一下Idea。

    1-2、新建一个Maven工程

    项目结构如下:

    1-3、导入配置文件

    1、XML文件

    <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.acitiviti</groupId> <artifactId>activiti</artifactId> <version>1.0-SNAPSHOT</version> <properties> <slf4j.version>1.6.6</slf4j.version> <log4j.version>1.2.12</log4j.version> </properties> <dependencies> <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-engine</artifactId> <version>7.0.0.Beta1</version> </dependency> <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-spring</artifactId> <version>7.0.0.Beta1</version> </dependency> <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-bpmn-model</artifactId> <version>7.0.0.Beta1</version> </dependency> <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-bpmn-converter</artifactId> <version>7.0.0.Beta1</version> </dependency> <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-json-converter</artifactId> <version>7.0.0.Beta1</version> </dependency> <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-bpmn-layout</artifactId> <version>7.0.0.Beta1</version> </dependency> <dependency> <groupId>org.activiti.cloud</groupId> <artifactId>activiti-cloud-services-api</artifactId> <version>7.0.0.Beta1</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.40</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <!-- log start --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${log4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${slf4j.version}</version> </dependency> <!-- log end --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.5</version> </dependency> <dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>1.4</version> </dependency> </dependencies> <repositories> <repository> <id>alfresco</id> <name>Activiti Releases</name> <url>https://artifacts.alfresco.com/nexus/content/repositories/activiti-releases/</url> <releases> <enabled>true</enabled> </releases> </repository> </repositories> </project>

    2、activiti.xml文件 放在resources下

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/contex http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!--数据源配置dbcp--> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/activiti?useUnicode=true&characterEncoding=utf8&nullCatalogMeansCurrent=true&useSSL=false&useLegacyDatetimeCode=false&serverTimezone=UTC" /> <property name="username" value="root" /> <property name="password" value="123" /> </bean> <!--activiti单独运行的ProcessEngine配置对象(processEngineConfiguration),使用单独启动方式 默认情况下:bean的id=processEngineConfiguration --> <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration"> <!--代表数据源--> <property name="dataSource" ref="dataSource"></property> <!-- <property name="jdbcDriver" value="com.mysql.jdbc.Driver" /> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/activiti" /> <property name="jdbcUsername" value="root" /> <property name="jdbcPassword" value="root" />--> <!--代表是否生成表结构--> <property name="databaseSchemaUpdate" value="true"/> </bean> </beans>

    3、Log文件 放在resources下

    # Set root category priority to INFO and its only appender to CONSOLE. #log4j.rootCategory=INFO, CONSOLE debug info warn error fatal log4j.rootCategory=debug, CONSOLE, LOGFILE # Set the enterprise logger category to FATAL and its only appender to CONSOLE. log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE # CONSOLE is set to be a ConsoleAppender using a PatternLayout. log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n # LOGFILE is set to be a File appender using a PatternLayout. log4j.appender.LOGFILE=org.apache.log4j.FileAppender log4j.appender.LOGFILE.File=c:/axis.log log4j.appender.LOGFILE.Append=true log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n

    1-4、代码创建工作流所需要的表结构(25张)

    新建一个测试类并运行下面的代码,创建表

    @Test public void testGenTable(){ //1.创建ProcessEngineConfiguration对象 第一个参数:配置文件名称 第二个参数是processEngineConfiguration的bean的id ProcessEngineConfiguration configuration = ProcessEngineConfiguration .createProcessEngineConfigurationFromResource("activiti.cfg.xml"); //2.创建ProcesEngine对象 ProcessEngine processEngine = configuration.buildProcessEngine(); //3.输出processEngine对象 System.out.println(processEngine); }

    1-5、数据表名称说明

    ACT_RE_*: 'RE’表示repository。 这个前缀的表包含了流程定义和流程静态资源 (图片,规则,等等)。ACT_RU_*: 'RU’表示runtime。 这些运行时的表,包含流程实例,任务,变量,异步任务,等运行中的数据。 Activiti只在流程实例执行过程中保存这些数据, 在流程结束时就会删除这些记录。 这样运行时表可以一直很小速度很快。ACT_ID_*: 'ID’表示identity。 这些表包含身份信息,比如用户,组等等。ACT_HI_*: 'HI’表示history。 这些表包含历史数据,比如历史流程实例, 变量,任务等等。ACT_GE_*: 'GE’表示general。通用数据, 用于不同场景下,如存放资源文件。

    1-6、Activiti7.0接口说明

    RepositoryService: 流程仓库Service,用于管理流程仓库,例如:部署,删除,读取流程资源 IdentityService:身份Service,可以管理,查询用户,组之间的关系 RuntimeService:运行时Service,可以处理所有正在运行状态的流程实例,任务等 TaskService:任务Service,用于管理,查询任务,例如:签收,办理,指派等 HistoryService:历史Service,可以查询所有历史数据,例如:流程实例,任务,活动,变量,附件等 FormService:表单Service,用于读取和流程,任务相关的表单数据 ManagementService:引擎管理Service,和具体业务无关,主要是可以查询引擎配置,数据库,作业等 DynamicBpmnService:一个新增的服务,用于动态修改流程中的一些参数信息等,是引擎中的一个辅助的服务

    1-7、Activiti流程定义

    在Idea中制作Activiti流程定义的PNG文件 前提:已经下载安装完毕ActiBPMN插件 步骤:1、在IDEA中创建BPMN文件

    节点简述: Connection—连接 Event—事件 Task—任务 Gateway—网关 Container—容器 Boundary event—边界事件 Intermediate event- -中间事件

    2、根据需要创建一个流程 3、将 bpmn 文件改为扩展名 xml 的文件名称 4、在 xml 文件上面,点右键并选择 Diagrams 菜单,再选择 Show BPMN2.0 Designer 5、打开后的效果图如下 如果出现乱码问题点击我

    二、Activiti应用

    2-1、流程定义部署

    2-1-1、单个流程部署

    public static void main(String[] args) { //1.创建ProcessEngine对象 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //2.得到RepositoryService实例 RepositoryService repositoryService = processEngine.getRepositoryService(); //3.进行部署 Deployment deployment = repositoryService.createDeployment() .addClasspathResource("diagram/holiday.bpmn") //添加bpmn资源 .addClasspathResource("diagram/holiday.png") .name("请假申请单流程") .deploy(); //4.输出部署的一些信息 System.out.println(deployment.getName()); System.out.println(deployment.getId()); }

    2-1-2、压缩包形式批量部署

    public static void main(String[] args) { //1.创建ProcessEngine对象 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //2.得到RepositoryService实例 RepositoryService repositoryService = processEngine.getRepositoryService(); //3.转化出ZipInputStream流对象 InputStream is = ActivitiDeployment.class.getClassLoader().getResourceAsStream("diagram/holidayBPMN.zip"); //将 inputstream流转化为ZipInputStream流 ZipInputStream zipInputStream = new ZipInputStream(is); //3.进行部署 Deployment deployment = repositoryService.createDeployment() .addZipInputStream(zipInputStream) .name("请假申请单流程") .deploy(); //4.输出部署的一些信息 System.out.println(deployment.getName()); System.out.println(deployment.getId()); } }

    2-2、启动一个流程实例

    /** * 启动流程实例: * 前提是先已经完成流程定义的部署工作 * * 背后影响的表: * act_hi_actinst 已完成的活动信息 act_hi_identitylink 参与者信息 act_hi_procinst 流程实例 act_hi_taskinst 任务实例 act_ru_execution 执行表 act_ru_identitylink 参与者信息 act_ru_task 任务 */ public class ActivitiStartInstance { public static void main(String[] args) { //1.得到ProcessEngine对象 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //2.得到RunService对象 RuntimeService runtimeService = processEngine.getRuntimeService(); //3.创建流程实例 流程定义的key需要知道 holiday ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("holiday"); //4.输出实例的相关信息 System.out.println("流程部署ID"+processInstance.getDeploymentId());//null System.out.println("流程定义ID"+processInstance.getProcessDefinitionId());//holiday:1:4 System.out.println("流程实例ID"+processInstance.getId());//2501 System.out.println("活动ID"+processInstance.getActivityId());//null } }

    2-3、指定用户任务列表查询

    public static void main(String[] args) { //1.得到ProcessEngine对象 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //2.得到TaskService对象 TaskService taskService = processEngine.getTaskService(); //3.根据流程定义的key,负责人assignee来实现当前用户的任务列表查询 List<Task> taskList = taskService.createTaskQuery() .processDefinitionKey("holiday") .taskAssignee("zhangsan") .list(); //4.任务列表的展示 for(Task task :taskList){ System.out.println("流程实例ID:"+task.getProcessInstanceId()); System.out.println("任务ID:"+task.getId()); System.out.println("任务负责人:"+task.getAssignee()); System.out.println("任务名称:"+task.getName()); } }

    2-4、任务完成处理

    public static void main(String[] args) { //1.得到ProcessEngine对象 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //2.得到TaskService对象 TaskService taskService = processEngine.getTaskService(); //3.处理任务,结合当前用户任务列表的查询操作的话,任务ID:2505 taskService.complete("2505"); }

    三、Activiti操作

    3-1、流程定义信息查询

    查询流程定义信息

    public class QueryProcessDefinition { public static void main(String[] args) { //1.得到ProcessEngine对象 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //2.创建RepositoryService对象 RepositoryService repositoryService = processEngine.getRepositoryService(); //3.得到ProcessDefinitionQuery对象,可以认为它就是一个查询器 ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery(); //4.设置条件,并查询出当前的所有流程定义 查询条件:流程定义的key=holiday //orderByProcessDefinitionVersion() 设置排序方式,根据流程定义的版本号进行排序 List<ProcessDefinition> list = processDefinitionQuery.processDefinitionKey("holiday") .orderByProcessDefinitionVersion() .desc().list(); //5.输出流程定义信息 for(ProcessDefinition processDefinition :list){ System.out.println("流程定义ID:"+processDefinition.getId()); System.out.println("流程定义名称:"+processDefinition.getName()); System.out.println("流程定义的Key:"+processDefinition.getKey()); System.out.println("流程定义的版本号:"+processDefinition.getVersion()); System.out.println("流程部署的ID:"+processDefinition.getDeploymentId()); } } }

    输出结果

    3-2、流程删除

    /** * 删除已经部署的流程定义 * * 背后影响的表: * act_ge_bytearray act_re_deployment act_re_procdef */ public class DeleteProcessDefinition { /** * 注意事项: * 1.当我们正在执行的这一套流程没有完全审批结束的时候,此时如果要删除流程定义信息就会失败 * 2.如果公司层面要强制删除,可以使用repositoryService.deleteDeployment("1",true); * //参数true代表级联删除,此时就会先删除没有完成的流程结点,最后就可以删除流程定义信息 false的值代表不级联 * * @param args */ public static void main(String[] args) { //1.得到ProcessEngine对象 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //2.创建RepositoryService对象 RepositoryService repositoryService = processEngine.getRepositoryService(); //3.执行删除流程定义 参数代表流程部署的id repositoryService.deleteDeployment("1"); } }

    3-3、流程图展示

    package com.itheima.day03.activiti; import org.activiti.engine.ProcessEngine; import org.activiti.engine.ProcessEngines; import org.activiti.engine.RepositoryService; import org.activiti.engine.repository.ProcessDefinition; import org.activiti.engine.repository.ProcessDefinitionQuery; import org.apache.commons.io.IOUtils; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; /** * 需求: * 1.从Activiti的act_ge_bytearray表中读取两个资源文件 * 2.将两个资源文件保存到路径: G:\Activiti7开发计划\Activiti7-day03\资料 * * 技术方案: * 1.第一种方式使用actviti的api来实现 * 2.第二种方式:其实就是原理层面,可以使用jdbc的对blob类型,clob类型数据的读取,并保存 * IO流转换,最好commons-io.jar包可以轻松解决IO操作 * * 真实应用场景:用户想查看这个请假流程具体有哪些步骤要走? * * */ public class QueryBpmnFile { public static void main(String[] args) throws IOException { //1.得到ProcessEngine对象 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //2.得到RepositoryService对象 RepositoryService repositoryService = processEngine.getRepositoryService(); //3.得到查询器:ProcessDefinitionQuery对象 ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery(); //4.设置查询条件 processDefinitionQuery.processDefinitionKey("holiday");//参数是流程定义的key //5.执行查询操作,查询出想要的流程定义 ProcessDefinition processDefinition = processDefinitionQuery.singleResult(); //6.通过流程定义信息,得到部署ID String deploymentId = processDefinition.getDeploymentId(); //7.通过repositoryService的方法,实现读取图片信息及bpmn文件信息(输入流) //getResourceAsStream()方法的参数说明:第一个参数部署id,第二个参数代表资源名称 //processDefinition.getDiagramResourceName() 代表获取png图片资源的名称 //processDefinition.getResourceName()代表获取bpmn文件的名称 InputStream pngIs = repositoryService .getResourceAsStream(deploymentId,processDefinition.getDiagramResourceName()); InputStream bpmnIs = repositoryService .getResourceAsStream(deploymentId,processDefinition.getResourceName()); //8.构建出OutputStream流 OutputStream pngOs = new FileOutputStream("C:\\activiti资料\\"+processDefinition.getDiagramResourceName()); OutputStream bpmnOs = new FileOutputStream("C:\\activiti资料\\"+processDefinition.getResourceName()); //9.输入流,输出流的转换 commons-io-xx.jar中的方法 IOUtils.copy(pngIs,pngOs); IOUtils.copy(bpmnIs,bpmnOs); //10.关闭流 pngOs.close(); bpmnOs.close(); pngIs.close(); bpmnIs.close(); } }
    Processed: 0.011, SQL: 9