activiti7笔记2

一、动态分配

在这里插入图片描述

/**
 *  启动流程实例,动态设置assignee
 */
public class AssigneeUEL {


    public static void main(String[] args) {
        //1.得到ProcessEngine对象
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2.得到RuntimeService对象
        RuntimeService runtimeService = processEngine.getRuntimeService();

       //3.设置assignee的取值   用户可以在界面上设置流程的执行人
        Map<String,Object> map = new HashMap<>();
        map.put("assignee0","zhangsan");
        map.put("assignee1","lishi");
        map.put("assignee2","wangwu");

        //4.启动流程实例,同时还要设置流程定义的assignee的值
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("holiday2", map);

        //5.输出
        System.out.println(processEngine.getName());

    }
}

二、监听分配

我们也可以通过监听来分配assign:
开发中,一般通过上面的UEL的方式分配assign
Create:任务创建后触发
Assignment:任务分配后触发
Delete:任务完成后触发
All:所有事件发生都触发
在这里插入图片描述

public class MyTaskListener implements TaskListener{
    @Override
    public void notify(DelegateTask delegateTask) {
        delegateTask.setAssignee("zhangsan");
    }
}

三、流程变量

例如,如果请假时间大于三天,需要总经理审核。小于等于三天的,部门经理审核即可。

3.1 流程变量的类型

在这里插入图片描述
注意:如果将 pojo 存储到流程变量中,必须实现序列化接口 serializable,为了防止由于新增字段无
法反序列化,需要生成 serialVersionUID。

3.2流程变量的作用域

流程变量的作用域默认是一个流程实例(processInstance),也可以是一个任务(task)或一个执行实例
(execution),这三个作用域流程实例的范围最大,可以 称为 global 变量,任务和执行实例仅仅是针对
一个任务和一个执行实例范围,范围没有流程实例大,为 称为 local 变量

一个变量的作用范围只在当前节点,就是local变量。

global变量中变量名不允许重复,设置相同名称的变量,后设置的值会覆盖前设置的变量值。
Local变量由于在不同的任务或不同的执行实例中,作用域互不影响,变量名可以相同没有影响。
Local变量名也可以和 global变量名相同,没有影响。

3.3流程变量的使用方法

第一步:设置流程变量
第二步:通过 UEL表达式使用流程变量
1> 可以在 assignee 处设置 UEL表达式,表达式的值为任务的负责人
比如:${assignee},assignee 就是一个流程变量名称
Activiti获取 UEL 表达式的值 ,即流程变量 assignee 的值 ,将 assignee 的值作为任务的负责人
进行任务分配
2> 可以在连线上设置 UEL表达式,决定流程走向
比如:${price>=10000}${price<10000}: price 就是一个流程变量名称,uel 表达式结果类型为
布尔类型
如果 UEL表达式是 true,要决定 流程执行走向。

3.4案例

大于3天走总经理,小于等于三天部门经理审核即可。
在这里插入图片描述

public class Holiday implements Serializable {
    private Integer id;
    private String holidayName;//申请人的名字
    private Date beginDate;//开始时间
    private Date endDate;//结束日期
    private Float num;//请假天数
    private String reason;//事由
    private String type;//请假类型
 }

流程部署:

    //新的请假流程定义的部署
    public static void main1(String[] args) {
        //1.得到ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2.得到RepositoryService对象
        RepositoryService repositoryService = processEngine.getRepositoryService();

        //3.部署
        Deployment deploy = repositoryService.createDeployment()
                .addClasspathResource("diagram/holiday4.bpmn")
                .addClasspathResource("diagram/holiday4.png")
                .name("请假流程-流程变量")
                .deploy();

        System.out.println(deploy.getId());
        System.out.println(deploy.getName());
    }

3.5启动流程实例,设置流程变量的值

    //启动流程实例,同时还要设置流程变量的值
    // act_ge_bytearray
    // act_ru_variable
    public static void main(String[] args) {
        //1.得到ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2.得到RuntimeService
        RuntimeService runtimeService =  processEngine.getRuntimeService();

        //3.流程定义的key问题   myProcess_1
        String key = "myProcess_1";
        Map<String ,Object> map = new HashMap<>();

        Holiday holiday = new Holiday();
        holiday.setNum(5F);
        map.put("holiday",holiday);

        //4.启动流程实例,并且设置流程变量的值
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(key, map);

        //5.输出实例信息
        System.out.println(processInstance.getName());
        System.out.println(processInstance.getProcessDefinitionId());

    }

执行任务:

    //完成任务  zhangsan  -----lishi----判断流程变量的请假天数,1天----分支:人事经理存档(zhaoliu)
    public static void main3(String[] args) {
        //1.得到ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2.得到TaskService
        TaskService taskService = processEngine.getTaskService();

        //3.查询当前用户是否有任务
        String key = "myProcess_1";
        Task task = taskService.createTaskQuery().processDefinitionKey(key)
                .taskAssignee("zhaoliu").singleResult();

        //4.判断task!=null,说明当前用户有任务
        if(task!=null){
            taskService.complete(task.getId());
            System.out.println("任务执行完毕");
        }

    }

3.6第二种方式,任务办理的时候,设置流程变量的值

注意,在启动流程实例的时候就别设置流程变量了哦。

    //完成任务  zhangsan  -----lishi----判断流程变量的请假天数,1天----分支:人事经理存档(zhaoliu)
    public static void main(String[] args) {
        //1.得到ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2.得到TaskService
        TaskService taskService = processEngine.getTaskService();

        //3.查询当前用户是否有任务
        String key = "myProcess_1";
        Task task = taskService.createTaskQuery().processDefinitionKey(key)
                .taskAssignee("zhangsan").singleResult();

        //初始化一些参数
        Map<String ,Object> map = new HashMap<>();

        Holiday holiday = new Holiday();
        holiday.setNum(5F);
        map.put("holiday",holiday);

        //4.判断task!=null,说明当前用户有任务
        if(task!=null){
            taskService.complete(task.getId(),map);//完成任务时,设置流程变量的值
            System.out.println("任务执行完毕");
        }

    }

3.7第三种方式:通过流程实例id设置流程变量

所以先需要启动流程实例,因为这样才有流程实例id

    //新加入的:通过流程实例id,来测试流程变量
    public static void main(String[] args) {
        //1.得到ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2.得到RuntimeService
        RuntimeService runtimeService =  processEngine.getRuntimeService();

        //3.流程定义的key问题   myProcess_1
        //Map<String ,Object> map = new HashMap<>();

        Holiday holiday = new Holiday();
        holiday.setNum(5F);
       // map.put("holiday",holiday);

        //4.通过实例id,来设置流程变量
        //第一个参数:流程实例的id
        //第二个参数:流程变量名
        //第三个变量:流程变量名,所对应的值
        runtimeService.setVariable("2501","holiday",holiday);

    }

设置流程变量会在当前执行流程变量表插入记录,同时也会在历史流程变量表也插入记录。

SELECT * FROM act_ru_variable #当前流程变量表

记录当前运行流程实例可使用的流程变量,包括 global和 local变量
Id_:主键
Type_:变量类型
Name_:变量名称
Execution_id_:所属流程实例执行 id,global和 local变量都存储
Proc_inst_id_:所属流程实例 id,global和 local变量都存储
Task_id_:所属任务 id,local变量存储
Bytearray_:serializable 类型变量存储对应act_ge_bytearray 表的 id
Double_:double 类型变量值
Long_:long类型变量值
Text_:text 类型变量值

SELECT * FROM act_hi_varinst #历史流程变量表

记录所有已创建的流程变量,包括 global和 local变量
字段意义参考当前流程变量表。

3.8 任务办理的时候,设置local变量

public void setLocalVariableByTaskId(){
	//当前待办任务id
	String taskId="1404";
	TaskService taskService = processEngine.getTaskService();
	Holiday holiday = new Holiday ();
	holiday.setNum(3);
	//通过任务设置流程变量
	taskService.setVariableLocal(taskId, "holiday", holiday);
	//一次设置多个值
	//taskService.setVariablesLocal(taskId, variables)
}

四、设置候选人

在这里插入图片描述

五、组任务办理流程

第一步:查询组任务
指定候选人,查询该候选人当前的待办任务。
候选人不能办理任务。
第二步:拾取(claim)任务
该组任务的所有候选人都能拾取。
将候选人的组任务,变成个人任务。原来候选人就变成了该任务的负责人。
***如果拾取后不想办理该任务?
需要将已经拾取的个人任务归还到组里边,将个人任务变成了组任务。
第三步:查询个人任务
查询方式同个人任务部分,根据 assignee 查询用户负责的个人任务。
第四步:办理个人任务

/**
 *  组任务的测试
 */
public class GroupTest {

    //8.任务交接,前提要保证当前用户是这个任务的负责人,这时候他才可以有权限去将任务交接给其他候选人
    /*public static void main(String[] args) {
        //1.得到ProcessEngine对象
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2.得到TaskService对象
        TaskService taskService = processEngine.getTaskService();

        //3.设置一些参数,流程定义的key,用户
        String key = "myProcess_1";
        String assignee="zhangsan";

        //4.执行查询
        Task task = taskService.createTaskQuery()
                .processDefinitionKey(key)
                .taskAssignee(assignee)  //设置任务的负责人
                .singleResult();
        //5.判断是否有这个任务
        if(task!=null){
            taskService.setAssignee(task.getId(),"lisi");//交接任务为lisi  ,交接任务就是一个候选人拾取用户的过程
            System.out.println("交接任务完成~!");
        }
    }*/

    //7.当前用户完成自己的任务
    public static void main(String[] args) {
        //1.得到ProcessEngine对象
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2.得到TaskService对象
        TaskService taskService = processEngine.getTaskService();

        //3.设置一些参数,流程定义的key,用户
        String key = "myProcess_1";
        String assignee="lisi";

        //4.执行查询
        Task task = taskService.createTaskQuery()
                .processDefinitionKey(key)
                .taskAssignee(assignee)  //设置任务的负责人
                .singleResult();
        //5.执行当前的任务
        if(task!=null){
            taskService.complete(task.getId());
            System.out.println("任务执行完毕!");
        }

    }

    //6.当前的用户查询自己的任务
    /*public static void main(String[] args) {
        //1.得到ProcessEngine对象
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2.得到TaskService对象
        TaskService taskService = processEngine.getTaskService();

        //3.设置一些参数,流程定义的key,用户
        String key = "myProcess_1";
        String assignee="zhangsan";

        //4.执行查询
        List<Task> list = taskService.createTaskQuery()
                .processDefinitionKey(key)
                .taskAssignee(assignee)  //设置任务的负责人
                .list();
        //5.输出
        for(Task task :list){
            System.out.println(task.getProcessInstanceId());
            System.out.println(task.getId());
            System.out.println(task.getName());
            System.out.println(task.getAssignee());//任务的执行人
        }
    }*/

    //5.测试zhangsan用户,来拾取组任务
    //抽取任务的过程就是将候选用户转化为真正任务的负责人(让任务的assignee有值)
  /* public static void main(String[] args) {
        //1.得到ProcessEngine对象
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2.得到TaskService对象
        TaskService taskService = processEngine.getTaskService();

        //3.设置一些参数,流程定义的key,候选用户
        String key = "myProcess_1";
        String candidate_users="zhangsan";

        //4.执行查询
        Task task = taskService.createTaskQuery()
                .processDefinitionKey(key)
                .taskCandidateUser(candidate_users)//设置候选用户
                .singleResult();
        if(task!=null){
            taskService.claim(task.getId(),candidate_users);//第一个参数任务ID,第二个参数为具体的候选用户名
            System.out.println("任务拾取完毕!");
        }
    }
*/
    //4.查询候选用户的组任务

    /*public static void main(String[] args) {
        //1.得到ProcessEngine对象
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2.得到TaskService对象
        TaskService taskService = processEngine.getTaskService();

        //3.设置一些参数,流程定义的key,候选用户
        String key = "myProcess_1";
        String candidate_users="zhangsan";

        //4.执行查询
        List<Task> list = taskService.createTaskQuery()
                .processDefinitionKey(key)
                .taskCandidateUser(candidate_users)//设置候选用户
                .list();
        //5.输出
        for(Task task :list){
            System.out.println(task.getProcessInstanceId());
            System.out.println(task.getId());
            System.out.println(task.getName());
            System.out.println(task.getAssignee());//为null,说明当前的zhangsan只是一个候选人,并不是任务的执行人
        }
    }*/


    //3.填写请假单的任务要执行完成
    /*public static void main(String[] args) {
        //1.得到ProcessEngine对象
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2.得到TaskService对象
        TaskService taskService = processEngine.getTaskService();

        //3.查询当前用户的任务
        Task task = taskService.createTaskQuery()
                .processDefinitionKey("myProcess_1")
                .taskAssignee("xiaozhang")
                .singleResult();

        //4.处理任务,结合当前用户任务列表的查询操作的话,任务ID:task.getId()
        if(task!=null){
            taskService.complete(task.getId());
            System.out.println("用户任务执行完毕...");
        }


        //5.输出任务的id
        System.out.println(task.getId());
    }*/

    //2.启动流程实例
   /* 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("myProcess_1");


            //4.输出实例的相关信息
            System.out.println("流程定义ID"+processInstance.getProcessDefinitionId());//holiday:1:4
            System.out.println("流程实例ID"+processInstance.getId());//2501
    }*/


    //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/holiday5.bpmn")  //添加bpmn资源
                // .addClasspathResource("diagram/holiday5.png")
                .name("请假申请单流程")
                .deploy();

        //4.输出部署的一些信息
        System.out.println(deployment.getName());
        System.out.println(deployment.getId());
    }*/
}

任务交接:部门经理有事,将这个交给别人来处理,而这个人就变成了候选人
数据库影响:
在这里插入图片描述

六、排他网关

即使两个分支都满足条件,也只能选择其中一个分支来执行
在这里插入图片描述

加了排他网关之后,默认走id值小的分支。
如果没有加排他网关,两个分支都会走。

设置分支条件时,如果所有分支条件都不是 true,报错:
org.activiti.engine.ActivitiException: No outgoing sequence flow of the exclusive gateway
‘exclusivegateway1’ could be selected for continuing the process
at
org.activiti.engine.impl.bpmn.behavior.ExclusiveGatewayActivityBehavior.leave(ExclusiveGatewayActivit
yBehavior.java:85)

七、并行网关

在这里插入图片描述
并行网关允许将流程分成多条分支,也可以把多条分支汇聚到一起,并行网关的功能是基于进
入和外出顺序流的:

  • fork 分支:
    并行后的所有外出顺序流,为每个顺序流都创建一个并发分支。
  • join 汇聚:
    所有到达并行网关,在此等待的进入分支, 直到所有进入顺序流的分支都到达以后, 流程就会通
    过汇聚网关。
    与其他网关的主要区别是,并行网关不会解析条件。 即使顺序流中定义了条件,也会被忽略

数据库影响:
当执行到并行网关数据库跟踪如下:
当前任务表:SELECT * FROM act_ru_task #当前任务表
在这里插入图片描述
上图中:有两个(多个)任务当前执行。
通过流程实例执行表:SELECT * FROM act_ru_execution #流程实例的执行表
在这里插入图片描述
上图中,说明当前流程实例有多个分支(两个)在运行。

对并行任务的执行:
并行任务执行不分前后,由任务的负责人去执行即可。
当完成并任务中一个任务后:
已完成的任务在当前任务表 act_ru_task_已被删除。
在流程实例执行表:SELECT * FROM act_ru_execution 有中多个分支存在且有并行网关的汇聚结点。
在这里插入图片描述
有并行网关的汇聚结点:说明有一个分支已经到汇聚,等待其它的分支到达。
当所有分支任务都完成,都到达汇聚结点后:
流程实例执行表:SELECT * FROM act_ru_execution,执行流程实例不存在,说明流程执行结束。
总结:所有分支到达汇聚结点,并行网关执行完成。

八、包含网关

在这里插入图片描述

/**
 *  测试包含网关
 *     特点:具有排他网关和并行网并的一些共同点
 *           可以设置流程变量,当流程变量取值都成立时,此时若干个分支都可以执行
 *
 */
public class InclusiveGateWayTest {

    //3.任务执行完成
    public static void main(String[] args) {
        //1.得到ProcessEngine对象
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2.得到TaskService对象
        TaskService taskService = processEngine.getTaskService();

        //3.查询当前用户的任务
        Task task = taskService.createTaskQuery()
                .processDefinitionKey("examine")
                .taskAssignee("xiaowang")
                .singleResult();

        //4.处理任务,结合当前用户任务列表的查询操作的话,任务ID:task.getId()
        if(task!=null){
            taskService.complete(task.getId());
            System.out.println("用户任务执行完毕...");
        }


        //5.输出任务的id
        System.out.println(task.getId());
    }

    //2.启动流程实例
/*   public static void main(String[] args) {
            //1.得到ProcessEngine对象
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

            //2.得到RunService对象
            RuntimeService runtimeService = processEngine.getRuntimeService();

        Integer userType = 2;//代表管理者
        Map<String,Object> map = new HashMap<>();
        map.put("userType",userType);//流程变量赋值

            //3.创建流程实例  流程定义的key需要知道 holiday
            ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("examine",map);


            //4.输出实例的相关信息
            System.out.println("流程定义ID"+processInstance.getProcessDefinitionId());//holiday:1:4
            System.out.println("流程实例ID"+processInstance.getId());//2501
    }*/


    //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/day05/examine.bpmn")  //添加bpmn资源
                //.addClasspathResource("diagram/day05/examine.png")
                .name("体检流程")
                .deploy();

        //4.输出部署的一些信息
        System.out.println(deployment.getName());
        System.out.println(deployment.getId());
    }*/
}

如果包含网关设置的条件中,流程变量不存在,报错;
org.activiti.engine.ActivitiException: Unknown property used in expression: ${userType==‘1’ ||
userType==‘2’}

需要在流程启动时设置流程变量 userType
当执行到包含网关:
流程实例执行表:SELECT * FROM act_ru_execution
在这里插入图片描述
在这里插入图片描述

九、spring整合activiti

9.1导入依赖

  <!--activiti与spring整合相关坐标引入
          activiti7相关的坐标,spring相关坐标,activiti-spring整合包,mysql驱动包...
    -->
    <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>
        <!--activiti与spring整合的-->
        <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>aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.5.4</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>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.0.7.RELEASE</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>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-nop</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>

9.2 activiti-spring.xml配置文件

<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"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
    ">

    <!-- 数据源 -->
    <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"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
        <property name="maxActive" value="3"/>
        <property name="maxIdle" value="1"/>
    </bean>

    <!-- 工作流引擎配置bean -->
    <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
        <!-- 数据源 -->
        <property name="dataSource" ref="dataSource"/>
        <!-- 使用spring事务管理器 -->
        <property name="transactionManager" ref="transactionManager"/>
        <!-- 数据库策略 -->
        <property name="databaseSchemaUpdate" value="drop-create"/>
    </bean>


    <!-- 流程引擎 -->
    <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
        <property name="processEngineConfiguration" ref="processEngineConfiguration"/>
    </bean>
    <!-- 资源服务service -->
    <bean id="repositoryService" factory-bean="processEngine"
          factory-method="getRepositoryService"/>
    <!-- 流程运行service -->
    <bean id="runtimeService" factory-bean="processEngine"
          factory-method="getRuntimeService"/>
    <!-- 任务管理service -->
    <bean id="taskService" factory-bean="processEngine"
          factory-method="getTaskService"/>
    <!-- 历史管理service -->
    <bean id="historyService" factory-bean="processEngine"
          factory-method="getHistoryService"/>

    <!-- 事务管理器 -->
    <bean id="transactionManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- 通知 -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!-- 传播行为 -->
            <tx:method name="save*" propagation="REQUIRED"/>
            <tx:method name="insert*" propagation="REQUIRED"/>
            <tx:method name="delete*" propagation="REQUIRED"/>
            <tx:method name="update*" propagation="REQUIRED"/>
            <tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
            <tx:method name="get*" propagation="SUPPORTS" read-only="true"/>
        </tx:attributes>
    </tx:advice>

    <!-- 切面,根据具体项目修改切点配置 -->
    <aop:config proxy-target-class="true">
        <aop:advisor advice-ref="txAdvice"
                     pointcut="execution(* com.itheima.service.impl.*.*(..))"/>
    </aop:config>
</beans>

9.3测试整合

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:activiti-spring.xml")
public class ActivitiSpringIntegrationTest {

    @Autowired
    private RepositoryService repositoryService;

    @Test
    public void testDeploymentObj(){
        System.out.println("部署对象:"+repositoryService);
    }
}

十、springboot整合activiti

10.1导入依赖

    <!--activiti7与SpringBoot整合的相关依赖-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.activiti/activiti-spring-boot-starter -->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring-boot-starter</artifactId>
            <version>7.0.0.Beta2</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.27</version>
        </dependency>


    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

10.2 application.yml文件

如果没有history相关的表,参考:https://blog.csdn.net/m0_38052384/article/details/104612908

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/activiti?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT
    username : root
    password : root
    driver-class-name: com.mysql.jdbc.Driver

10.3 在activiti-examples中复制两个类放入到项目中

/*
 * Copyright 2018 Alfresco, Inc. and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.itheima.activiti;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Configuration
@EnableWebSecurity
public class DemoApplicationConfiguration extends WebSecurityConfigurerAdapter {

    private Logger logger = LoggerFactory.getLogger(DemoApplicationConfiguration.class);

    @Override
    @Autowired
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(myUserDetailsService());
    }

    @Bean
    public UserDetailsService myUserDetailsService() {

        InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();

        String[][] usersGroupsAndRoles = {
                {"salaboy", "password", "ROLE_ACTIVITI_USER", "GROUP_activitiTeam"},
                {"ryandawsonuk", "password", "ROLE_ACTIVITI_USER", "GROUP_activitiTeam"},
                {"erdemedeiros", "password", "ROLE_ACTIVITI_USER", "GROUP_activitiTeam"},
                {"other", "password", "ROLE_ACTIVITI_USER", "GROUP_otherTeam"},
                {"admin", "password", "ROLE_ACTIVITI_ADMIN"},
        };

        for (String[] user : usersGroupsAndRoles) {
            List<String> authoritiesStrings = Arrays.asList(Arrays.copyOfRange(user, 2, user.length));
            logger.info("> Registering new user: " + user[0] + " with the following Authorities[" + authoritiesStrings + "]");
            inMemoryUserDetailsManager.createUser(new User(user[0], passwordEncoder().encode(user[1]),
                    authoritiesStrings.stream().map(s -> new SimpleGrantedAuthority(s)).collect(Collectors.toList())));
        }


        return inMemoryUserDetailsManager;
    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                .httpBasic();


    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

package com.itheima.activiti;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;

import java.util.Collection;

@Component
public class SecurityUtil {

    @Autowired
    private UserDetailsService userDetailsService;

    public void logInAs(String username) {

        UserDetails user = userDetailsService.loadUserByUsername(username);
        if (user == null) {
            throw new IllegalStateException("User " + username + " doesn't exist, please provide a valid user");
        }

        SecurityContextHolder.setContext(new SecurityContextImpl(new Authentication() {
            @Override
            public Collection<? extends GrantedAuthority> getAuthorities() {
                return user.getAuthorities();
            }

            @Override
            public Object getCredentials() {
                return user.getPassword();
            }

            @Override
            public Object getDetails() {
                return user;
            }

            @Override
            public Object getPrincipal() {
                return user;
            }

            @Override
            public boolean isAuthenticated() {
                return true;
            }

            @Override
            public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {

            }

            @Override
            public String getName() {
                return user.getUsername();
            }
        }));
        org.activiti.engine.impl.identity.Authentication.setAuthenticatedUserId(username);
    }
}

10.4 BPMN文件

在新特性中,流程部署会自动完成部署,只要bpmn文件放置在src\main\resources\processes下。
在这里插入图片描述
使用用户组,注意,这个用户组是springsecurity中定义过:GROUP_activitiTeam
要求以GROUP_开头,真正的组名是activitiTeam。

10.5 流程的相关操作

import org.activiti.api.process.model.ProcessDefinition;
import org.activiti.api.process.model.ProcessInstance;
import org.activiti.api.process.model.builders.ProcessPayloadBuilder;
import org.activiti.api.process.runtime.ProcessRuntime;
import org.activiti.api.runtime.shared.query.Page;
import org.activiti.api.runtime.shared.query.Pageable;
import org.activiti.api.task.model.Task;
import org.activiti.api.task.model.builders.TaskPayloadBuilder;
import org.activiti.api.task.runtime.TaskRuntime;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class Actviti7DemoApplicationTests {
    @Autowired
    private ProcessRuntime processRuntime;
    @Autowired
    private TaskRuntime taskRuntime;
    @Autowired
    private SecurityUtil securityUtil;



//
//    /**
//     * 查看流程定义
//     */
    @Test
    public void contextLoads() {
        securityUtil.logInAs("salaboy");
        Page<ProcessDefinition> processDefinitionPage = processRuntime.processDefinitions(Pageable.of(0, 10));
        System.out.println("可用的流程定义数量:" + processDefinitionPage.getTotalItems());
        for (ProcessDefinition pd : processDefinitionPage.getContent()) {
            System.out.println("流程定义:" + pd);
        }
    }
//
//    /**
//     * 启动流程实例
//     */
   @Test
    public void testStartProcess() {
        securityUtil.logInAs("system");
        ProcessInstance pi = processRuntime.start(ProcessPayloadBuilder.start().withProcessDefinitionKey("myProcess")
                .build());
        System.out.println("流程实例ID:" + pi.getId());
    }
//

    /**
     * 查询任务,并完成自己的任务
     */
    @Test
    public void testTask() {
        securityUtil.logInAs("ryandawsonuk");
        Page<Task> taskPage=taskRuntime.tasks(Pageable.of(0,10));
        if (taskPage.getTotalItems()>0){
            for (Task task:taskPage.getContent()){
                taskRuntime.claim(TaskPayloadBuilder.claim().withTaskId(task.getId()).build());
                System.out.println("任务:"+task);
                taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(task.getId()).build());
            }
        }
        Page<Task> taskPage2=taskRuntime.tasks(Pageable.of(0,10));
        if (taskPage2.getTotalItems()>0){
            System.out.println("任务:"+taskPage2.getContent());
        }
    }
}

10.6 添加controller

@RestController
public class TestController {
    private Logger logger = LoggerFactory.getLogger(TestController.class);
    @Autowired
    private ProcessRuntime processRuntime;
    @Autowired
    private TaskRuntime taskRuntime;
    @Autowired
    private SecurityUtil securityUtil;

    @RequestMapping(value = "/hello")
    public void hello() {
        // 首先,取出项目中的最多 10 个流程定义
        Page<ProcessDefinition> processDefinitionPage = processRuntime.processDefinitions(Pageable.of(0, 10));

        if (processDefinitionPage.getTotalItems() > 0) {
            // 然后,对取出的流程进行启动
            for (ProcessDefinition definition : processDefinitionPage.getContent()) {
                logger.info(" 流程定义信息:" + definition);
                processRuntime.start(ProcessPayloadBuilder.start().withProcessDefinitionId(definition.getId()).build());
            }
        }
        // 完成流程启动后,由于当前项目中只有 other.bpmn 一个流程,且该流程在设计时,已分配给activitiTeam 组
        // 因此我们登录一个 activitiTeam 组成员 , 该账号信息会被设置到 security 上下文中, activiti 会对其信息进行读取
        // 获取当前用户任务,最多 10 个
        Page<Task> taskPage = taskRuntime.tasks(Pageable.of(0, 10));
        // 由于目前只有一个流程,两个任务,我们尝试一下完成一个,看看会发生什么变化
        if (taskPage.getTotalItems() > 0) {
            for (Task task : taskPage.getContent()) {
                logger.info(" 任务信息:" + task);
                // 注意,完成任务前必须先声明
                taskRuntime.claim(TaskPayloadBuilder.claim().withTaskId(task.getId()).build());
                // 完成任务
                taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(task.getId()).build()
                );
            }
        }
        // 上一轮任务完成,再看一下,现在流程是否走到了 second ?
        Page<Task> taskPage2 = taskRuntime.tasks(Pageable.of(0, 10));
        if (taskPage2.getTotalItems() > 0) {
            logger.info(" 任务信息:" + taskPage2.getContent());
        }
    }
}

启动类:

@SpringBootApplication(exclude = SecurityAutoConfiguration.class)
public class Actviti7DemoApplication {
    private Logger logger = LoggerFactory.getLogger(Actviti7DemoApplication.class);
    public static void main(String[] args) {
        SpringApplication.run(Actviti7DemoApplication.class, args);
    }
    @Bean
    public Connector testConnector() {
        return integrationContext -> {
            logger.info("以前叫代理,现在叫连接器被调用啦~~");
            return integrationContext;
        };
    }
}

activiti7新特性文档:https://github.com/Activiti/activiti-7-developers-guide/blob/51a1681c0e4bb5e2f96a6dea73516c9fd53d8521/getting-started/getting-started-activiti-core.md

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值