Activiti快速入门

1.什么是Activiti

在解释activiti之前我们看一下什么是工作流。
工作流(Workflow),就是“业务过程的部分或整体在计算机应用环境下的自动化”,它主要解决的是“使在多个参与者之间按照某种预定义的规则传递文档、信息或任务的过程自动进行,从而实现某个预期的业务目标,或者促使此目标的实现”。
我的理解是,工作流将一套大的业务逻辑分解成业务逻辑段, 并统一控制这些业务逻辑段的执行条件,执行顺序以及相互通信。 实现业务逻辑的分解和解耦。
Activiti是一个开源的工作流引擎,它实现了BPMN 2.0规范,可以发布设计好的流程定义,并通过api进行流程调度。
BPMN即业务流程建模与标注(Business Process Model and Notation,BPMN) ,描述流程的基本符号,包括这些图元如何组合成一个业务流程图(Business Process Diagram)。

BPMN的流程图长这样子

 

activiti5.13使用了23张表支持整个工作流框架,底层使用mybatis操作数据库。这些数据库表为


1)ACT_RE_*: 'RE'表示repository。 这个前缀的表包含了流程定义相关的静态资源(图片,规则等)。
2)ACT_RU_*: 'RU'表示runtime。 运行时表,包含流程实例,任务,变量,异步任务等运行中的数据。流程结束时这些记录会被删除。
3)ACT_ID_*: 'ID'表示identity。 这些表包含用户和组的信息。
4)ACT_HI_*: 'HI'表示history。 这些表包含历史数据,比如历史流程实例,变量,任务等。
5)ACT_GE_*: 通用数据,bytearray表保存文件等字节流对象。

工作流进行的基本过程如下:
定义流程(框架外) -> 部署流程定义 -> 启动流程实例, 框架移动到任务1 -> 拾取组任务 -> 办理个人任务, 框架移动到任务2 -> 拾取组任务 -> 办理个人任务...

组任务是多个用户都可以完成的任务。没有组任务直接办理个人任务; 有组任务需先通过拾取将组任务变成个人任务, 然后再办理。

个人任务/组任务在表中的区别

个人任务: 表act_ru_task的ASSIGNEE段即指定的办理人

组任务: 表act_ru_task的ASSIGNEE段为null, 相关信息在表act_ru_identitylink中, 组任务1见userid段;  组任务2见groupid段, 当然还需查询act_id_xxx表才能精确到人.

 

2.Activiti的使用

2.1 创建processEngine

processEngine控制着工作流整个流程

public class processEngine {
    @Test
    public void createProcessEngine1() {
        String resource = "activiti-context.xml";    // 配置文件
        String beanName = "processEngineConfiguration";  // 配置文件中bean name
        // 从配置文件创建配置对象
        ProcessEngineConfiguration config = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource(resource, beanName);
        // 根据配置创建引擎对象
        ProcessEngine processEngine = config.buildProcessEngine();
    }

    /**
     *  一条语句创建processEngine, 要求:
     * 1、配置文件必须在classpath根目录下
     * 2、配置文件名必须为activiti-context.xml或activiti.cfg.xml
     * 3、工厂对象的id必须为processEngine
     */
    @Test
    public void createProcessEngine2() {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    }
}
<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.engine.impl.cfg.StandaloneProcessEngineConfiguration">
        <property name="jdbcDriver"  value="com.mysql.jdbc.Driver"/>
        <property name="jdbcUrl"  value="jdbc:mysql:///test_activiti"/>
        <property name="jdbcUsername"  value="root"/>
        <property name="jdbcPassword"  value="root"/>
        <!-- 创建processEngine时, activiti自动创建23张表 -->
        <property name="databaseSchemaUpdate" value="true"/>
    </bean>
    <!-- 使用配置创建引擎对象 -->
    <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
        <property name="processEngineConfiguration" ref="processEngineConfiguration"/>
    </bean>
</beans>

当然, 可以与spring进一步整合, 使用spring方式获取processEngine.  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="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql:///activiti_day2" />
        <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>
    <!-- 流程引擎配置对象 -->
    <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
        <!-- 注入数据源 -->
        <property name="dataSource" ref="dataSource"/>
        <!-- 注入事务管理器对象 -->
        <property name="transactionManager" ref="transactionManager"/>
        <property name="databaseSchemaUpdate" value="true" />
    </bean>
    <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
        <property name="processEngineConfiguration" ref="processEngineConfiguration" />
    </bean>
</beans>

 

2.2 部署流程定义

流程是由用户通过bpmn等文件(底层xml)定义的, 即上面列举的的bpmn流程图

定义好的流程需要部署给activiti才能被其使用

   /**
     * 部署流程定义 
     * 一套定义文件只有一个流程定义Key, 但可以被部署多次形成多个版本(部署表里多个id和流程定义表里多个id)
     * 涉及的表:act_re_deployment(部署表)、act_re_procdef(流程定义表)、act_ge_bytearray(二进制表)
     */
    @Test
    public void test() throws FileNotFoundException {
        DeploymentBuilder deploymentBuilder = processEngine.getRepositoryService().createDeployment();
        // 逐个文件部署
        // deploymentBuilder.addClasspathResource("qjlc.bpmn");
        // deploymentBuilder.addClasspathResource("qjlc.png");
        // 压缩文件打包部署, 推荐
        ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(new File("d:\\processDef.zip")));
        deploymentBuilder.addZipInputStream(zipInputStream );
        
        Deployment deployment = deploymentBuilder.deploy();
    }

 

2.3 启动流程实例

     /**
     * 启动一个流程实例
     * 涉及的表:
     * act_ru_execution(流程实例表), 管理流程进度
     * act_ru_task(任务表), 进行到哪一个流程的哪一个任务, 该由谁完成
     */
    @Test
    public void test() throws Exception{
        String processDefinitionKey = "qjlc";
        //方式一:根据流程定义id启动流程实例
        //String processDefinitionId = "qjlc:6:904";
        //ProcessInstance processInstance = processEngine.getRuntimeService().startProcessInstanceById(processDefinitionId);
        
        //方式二:根据流程定义Key启动流程实例   推荐!流程定义有多个版本时会选择最新版本
        ProcessInstance processInstance = processEngine.getRuntimeService().startProcessInstanceByKey(processDefinitionKey);
    }        

 

2.4 办理任务

  /**
    * 办理任务, 办理后框架自动移动到下一任务
    * 涉及的表: act_ru_execution(流程实例表)、act_ru_task(任务表)
    */
    @Test
    public void test() throws Exception{
        String taskId = "1304";
        processEngine.getTaskService().complete(taskId);
    }

 

2.5 其他操作

   /**
    * 查询流程定义
    * 涉及的表:act_re_procdef
    */
    @Test
    public void test(){
        ProcessDefinitionQuery query = processEngine.getRepositoryService().createProcessDefinitionQuery();
        // 查询条件过滤
        query.processDefinitionKey("qjlc");
        query.orderByProcessDefinitionVersion().asc();
        List<ProcessDefinition> list = query.listPage(0, 10);
        for (ProcessDefinition processDefinition : list) {
            System.out.println(processDefinition.getId());
        }
    }

activiti中查询的套路:  processEngine.getXXXService().createXXXQuery().list()/singleResult()
processEngine.getRepositoryService().createDeploymentQuery().list(); // 查询部署
processEngine.getRuntimeService().createProcessInstanceQuery().list(); // 查询流程实例
processEngine.getTaskService().createTaskQuery().list(); // 查询个人任务
processEngine.getIdentityService().createUserQuery().list(); // 查询用户
processEngine.getHistoryService().createHistoricActivityInstanceQuery().list(); //查询历史
过滤条件
查询个人任务 query.taskAssignee()
查询组任务    query.taskCandidate()

几个javabean(和表对应):
Deployment------act_re_deployment
ProcessDefinition-----act_re_procdef
ProcessInstance------act_ru_execution
Task-----act_ru_task
几个Query对象
DeploymentQuery------act_re_deployment
ProcessDefinitionQuery-----act_re_procdef
ProcessInstanceQuery------act_ru_execution
TaskQuery-----act_ru_task
几个Service
RepositoryService----操作部署表、流程定义表等静态资源信息表
RuntimeService----操作流程实例表、任务表等动态信息表
TaskService-----操作任务表
HistoryService----操作历史表
IdentityService----操作用户表、组表、关系表

  // 删除流程定义
    @Test
    public void test1(){
        String deploymentId = "101";  //部署id
        boolean cascade = false;  // 级联删除, 设置为true的话, 有正在跑的流程实例及任务也会被删除
        processEngine.getRepositoryService().deleteDeployment(deploymentId, cascade);
    }
    // 删除流程实例
    @Test
    public void test2() throws Exception{
        String processInstanceId = "1201";
        String deleteReason = "不请假了";  // 可以添加删除原因
        processEngine.getRuntimeService().deleteProcessInstance(processInstanceId, deleteReason);
    }
  // 根据部署id, 获取定义文件 @Test public void test3() throws Exception{ String deploymentId = "201"; //部署id // 先获得定义文件的名字 List<String> names = processEngine.getRepositoryService().getDeploymentResourceNames(deploymentId); for (String name : names) { InputStream in = processEngine.getRepositoryService().getResourceAsStream(deploymentId, name); FileUtils.copyInputStreamToFile(in, new File("d:\\"+name)); in.close(); } } // 根据流程定义id, 获取定义文件 @Test public void test4() throws Exception{ String processDefinitionId = "qjlc:6:904"; //流程定义id InputStream pngStream = processEngine.getRepositoryService().getProcessDiagram(processDefinitionId); FileUtils.copyInputStreamToFile(pngStream, new File("d:\\abc.png")); }

通过javabean能访问到某些需要的字段, 例如

processInstance.getActivityId() -> 当前执行的任务名

processDefinition.getDiagramResourceName() -> 定义文件中图片的名字

 

2.6  流程变量

多个任务间可以通过流程变量通信.

流程变量以key-value形式存放, 存于表 act_ru_variable. 在同一流程实例里, 不同方式设置变量, key相同时会覆盖

    // 启动流程实例时 设置流程变量
    @Test
    public void test1() {
        String processDefinitionKey = "bxlc";
        Map<String, Object> variables = new HashMap<String, Object>();
        variables.put("key", "value");
        ProcessInstance pi = processEngine.getRuntimeService().startProcessInstanceByKey(processDefinitionKey, variables);
    }
    // 办理任务时 设置流程变量, 更实用!
    @Test
    public void test2() {
        String taskId = "206";
        Map<String, Object> variables = new HashMap<>();
        variables.put("key", "value");
        processEngine.getTaskService().complete(taskId, variables);
    }
    // 通过RuntimeService 设置流程变量
    @Test
    public void test3() {
        String executionId = "201"; // 流程实例id
        Map<String, Object> variables = new HashMap<>();
        variables.put("key", "value");
        //processEngine.getRuntimeService().setVariable(executionId, variableName, value);
        processEngine.getRuntimeService().setVariables(executionId, variables);
    }
    // 通过TaskService 设置流程变量
    @Test
    public void test4() {
        String taskId = "304";
        String key = "key";
        Object value = "value";
        processEngine.getTaskService().setVariable(taskId , key, value);
    }

 

// 通过RuntimeService 获取流程变量
    @Test
    public void test5() {
        String executionId = "201";
        Object value = processEngine.getTaskService().getVariable(executionId, "user");
        System.out.println(value);
    }
     // 通过TaskService 获取流程变量
    @Test
    public void test6() {
        String taskId = "304";
        Object value = processEngine.getTaskService().getVariable(taskId, "user");
        System.out.println(value);
    }

流程变量还可以通过在定义流程用表达式${}.  框架在该段任务执行前从act_ru_variable表里动态获取

另外, 启动流程实例还有一个重载函数, 除了流程变量variables还能指定业务主键businessKey

processEngine.getRuntimeService().startProcessInstanceByKey(processDefinitionKey, businessKey, variables);

businessKey一般设置为业务表的主键值, 在使用activiti的时候, 通过查询业务表主键, 能方便地查询出业务的最新状态

 

 

2.7  组任务

 

组任务1

  // 查询组任务
    @Test
    public void test1() {
        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 test2() {
        String taskId = "1102";
        processEngine.getTaskService().claim(taskId , "财务二");
    }
    // 办理组任务, 无需指定办理人
    @Test
    public void test3() throws Exception{
        String taskId = "1102";
        processEngine.getTaskService().complete(taskId);
    }

组任务2

  // activiti使用自己的用户与组的权限表, 因此需要设置. 但需注意要与框架外用户/组同步设置
    @Test
    public void test2() {
        // 创建组
        Group group = new GroupEntity();
        group.setId("财务组");
        processEngine.getIdentityService().saveGroup(group);
        // 创建用户
        User user = new UserEntity();
        user.setId("2");
        processEngine.getIdentityService().saveUser(user);
        // 维护用户与组的关系
        processEngine.getIdentityService().createMembership("2", "财务组");
    }
    // 查询组任务
    @Test
    public void test2() {
        TaskQuery query = processEngine.getTaskService().createTaskQuery();
        String candidateUser = "2";
        // 使用候选人过滤
        query.taskCandidateUser(candidateUser);
        // 使用组过滤
        //query.taskCandidateGroup("财务组");
        List<Task> list = query.list();
        for (Task task : list) {
            System.out.println(task.getId());
        }
    }
    // 拾取组任务
    @Test
    public void test3() {
        String taskId = "1902";
        processEngine.getTaskService().claim(taskId , "2");
    }
    // 办理组任务略

 

2.8 排他网关

设置分支条件

 

3. 一些使用经验

1)

考虑到工作流中的一个任务, 对应一个业务段, 可以将taskDefinitionKey设置成strus action类的method, 使之具有一定的通用性

2)

两种对流程定义的查询, 后者能获得更多定义的细节信息  processDefinitionEntity.findActivity(taskId) 工作流中某任务的信息

repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult()

(ProcessDefinitionEntity) repositoryService.getProcessDefinition(processDefinitionId)

 

posted on 2017-04-07 00:29 myJavaEE 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/myJavaEE/p/6676226.html

Activiti 是一个流程引擎框架,可以帮助开发者快速实现工作流相关的应用。下面是使用 Activiti 创建流程引擎的步骤: 1. 创建 maven 项目,添加 Activiti 依赖。 在项目的 pom.xml 文件中添加以下依赖: ``` <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-engine</artifactId> <version>5.22.0</version> </dependency> ``` 2. 创建流程引擎配置类。 在项目中创建一个 Java 类,用于配置流程引擎。可以在该类中指定数据库连接信息、流程图文件路径等信息。以下是一个示例配置类: ``` import java.io.IOException; import java.io.InputStream; import java.util.Properties; import org.activiti.engine.ProcessEngine; import org.activiti.engine.ProcessEngineConfiguration; import org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration; public class ActivitiConfig { public ProcessEngine getProcessEngine() throws IOException { // 读取配置文件 InputStream inputStream = getClass().getResourceAsStream("/activiti.properties"); Properties properties = new Properties(); properties.load(inputStream); // 配置流程引擎 ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration() .setJdbcUrl(properties.getProperty("jdbc.url")) .setJdbcUsername(properties.getProperty("jdbc.username")) .setJdbcPassword(properties.getProperty("jdbc.password")) .setJdbcDriver(properties.getProperty("jdbc.driver")) .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_FALSE); // 创建流程引擎 ProcessEngine processEngine = cfg.buildProcessEngine(); return processEngine; } } ``` 在该配置类中,我们读取一个名为 activiti.properties 的配置文件,该文件包含了数据库连接信息。在实际开发中,我们可以将这些信息存储在外部配置文件中,以便于修改和管理。 3. 创建流程图文件。 使用 Activiti Modeler 工具创建流程图文件,或者手动编写 BPMN 2.0 标准的 XML 文件。将该文件放置在项目的 classpath 下,以便于程序能够读取。 4. 启动流程引擎。 在程序中使用上述配置类创建流程引擎实例,并启动该实例。以下是一个示例代码: ``` public static void main(String[] args) throws IOException { // 创建流程引擎配置类 ActivitiConfig config = new ActivitiConfig(); // 获取流程引擎实例 ProcessEngine processEngine = config.getProcessEngine(); // 输出流程引擎信息 String name = processEngine.getName(); String version = ProcessEngine.VERSION; System.out.println("流程引擎名称:" + name); System.out.println("流程引擎版本:" + version); // 关闭流程引擎 processEngine.close(); } ``` 在上述示例代码中,我们创建了一个 ActivitiConfig 实例,并使用该实例获取了流程引擎。获取流程引擎后,我们可以输出其名称和版本信息,并在程序结束时关闭该引擎。 以上就是使用 Activiti 创建流程引擎的步骤。开发者可以根据自己的需求对流程引擎进行配置和使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值