activiti7入门教程

这篇具有很好参考价值的文章主要介绍了activiti7入门教程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、相关概念

  1. 工作流概念

    工作流是指业务过程的部分或整体在计算机应用环境下的自动化。是对工作流程及其各操作步骤之间业务规则的抽象、概括描述。

  2. activiti介绍

    activiti是一个工作流引擎,可以将业务系统中复杂的业务流程抽取出来,使用专门的建模语言BPMN进行定义,业务流程按照预先定义的流程进行执行。实现了系统的流程由activiti进行管理,减少业务系统由于流程变更进行系统升级改造的工作流量,从而提高系统的健壮性,同时也减少了系统开发维护成本。

  3. BPM(Business Process Management)

    业务流程管理

  4. BPM软件

    通过BPM软件可以实现对业务流程的整个生命周期进行建模、自动化、管理监控和优化。

  5. BPMN(Business Process MOdel And Notation 业务流程模型和符号)

    业务流程模型和符号,是由BPMI开发的一套标准的业务流程建模符号,使用BPMN提供的符号可以创建业务流程。

  6. ProcessDefinition:流程定义

  7. ProcessInstance:流程实例

二、使用步骤

  1. 部署activiti

    activiti是一个工作流程,业务系统访问activiti的接口,就可以方便操作流程间的相关数据,这样就可以把工作流环境和业务系统的环境集成在一起。

  2. 流程定义

    使用activiti建模工具定义业务流程,生成.bpmn文件(通过xml定义业务流程)。

  3. 流程定义部署

    使用activiti提供的api把流程定义的内容存储起来,再Activiti执行过中可以查询的内容。activiti执行把流程定内容存储在数据库中。

  4. 启动一个流程实例

    流程实例也叫ProcessInstance

    启动一个流程实例表示开始一次业务流程的执行

    比如同一个流程,张三可以启动,李四也可以启动,但是两次流程实例是互不影响的。

  5. 用户查询待办任务

    由于集成了activiti,所有的任务都可以直接通过activiti提供的api进行查询,不需要我们自己查库。

  6. 用户办理任务

    流程办理等操作,也是可以直接使用activiti提供的api即可。

  7. 流程结束

    当没有下一个需要办理的节点,说明任务就结束了。

三、activiti配置生成表

  1. idea软件安装actiBPM插件,若idea找不到插件,可去官网下载,导入即可,可参考

    https://blog.csdn.net/weixin_40496191/article/details/125097860

  2. pom配置

    <!-- springboot -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
    <!-- 工作流 -->
    <dependency>
        <groupId>org.activiti</groupId>
        <artifactId>activiti-spring-boot-starter</artifactId>
        <version>7.1.0.M1</version>
    </dependency>
    <dependency>
        <groupId>org.activiti</groupId>
        <artifactId>activiti-json-converter</artifactId>
        <version>7.1.0.M1</version>
    </dependency>
    <dependency>
        <groupId>org.activiti</groupId>
        <artifactId>activiti-image-generator</artifactId>
        <version>7.1.0.M1</version>
    </dependency>
    <dependency>
        <groupId>org.apache.xmlgraphics</groupId>
        <artifactId>batik-all</artifactId>
        <version>1.10</version>
    </dependency>
    
    <!-- 数据库 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.2.2</version>
    </dependency>
    
  3. 配置文件配置activiti相关参数和数据库信息

    server:
      port: 8080
    
    spring:
      datasource:
        driver-class-name: com.mysql.cj.jdbc.Driver
        username: root
        password: tiger
        url: jdbc:mysql://localhost:3306/activiti?useUnicode=true&characterEncoding=utf-8 &allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2b8&nullCatalogMeansCurrent=true
        type: com.alibaba.druid.pool.DruidDataSource
        servlet:
          multipart:
            max-file-size: 100MB
            max-request-size: 100MB
      activiti:
        #    false:默认,数据库表不变,但是如果版本不对或者缺失表会抛出异常(生产使用)
        #    true:表不存在,自动创建(开发使用)
        #    create_drop: 启动时创建,关闭时删除表(测试使用)
        #    drop_create: 启动时删除表,在创建表 (不需要手动关闭引擎)
        database-schema-update: true
        #监测历史表是否存在,activities7默认不开启历史表
        db-history-used: true
        #none:不保存任何历史数据,流程中这是最高效的
        #activity:只保存流程实例和流程行为
        #audit:除了activity,还保存全部的流程任务以及其属性,audit为history默认值
        #full:除了audit、还保存其他全部流程相关的细节数据,包括一些流程参数
        history-level: full
        #校验流程文件,默认校验resources下的process 文件夹的流程文件
        check-process-definitions: true
    
  4. 启动项目,即可生成相关表

    activiti7,新手,数据库,运维,大数据

  5. 相关表关系

    re表:流程定义和流程相关属性

    ru表:运行时产生的数据

    hi表:历史信息

    ge表:通用信息

activiti7,新手,数据库,运维,大数据

四、简单画一个流程

  1. 画图

    创建demo.bpmn文件,简单实现流程图,id为“myLeave“,流程名称为“员工请假审批流程”,责任人从上往下依次为worker、manager、financer。
    activiti7,新手,数据库,运维,大数据

  2. 画完图后,可以将流程图导出来

    1)复制一份新的文件,以xml结尾

    2)右键显示图标

    activiti7,新手,数据库,运维,大数据
    3)导出png图片
    activiti7,新手,数据库,运维,大数据

五、activiti接口基础api示例

1. 代码创建流程

/**
 * 部署流程
 */
@RequestMapping("createProcesses")
@ResponseBody
public void createProcesses() {
    //使用获取RepositoryService进行部署
    Deployment deployment = repositoryService.createDeployment()
        .addClasspathResource("static/bpmn/demo.bpmn")//添加bpmn资源
        .addClasspathResource("static/bpmn/demo.png")//添加png资源
        .name("员工请假审批流程")
        .deploy();//部署流程
    //输出流程部署的信息
    System.out.println("流程部署id:" + deployment.getId());
    System.out.println("流程部署名称:" + deployment.getName());
}

//结果:
//流程部署id:1fb480d0-0773-11ed-8dc3-005056c00001
//流程部署名称:员工请假审批流程

执行后可以去数据库查看相关的表数据

act_re_deployment:查看相关的流程的创建

act_re_procdef:查看流程的定义

act_ge_bytearray:流程文件存储

2. 查询流程的定义

/**
 * 查询流程的定义
 */
@RequestMapping("searchProcess")
@ResponseBody
public void searchProcess() {
    String key= "myLeave";
    //获取ProcessDefinitionQuery对象,用来查询操作
    ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
    List<ProcessDefinition> list = processDefinitionQuery.processDefinitionKey(key)
        .orderByProcessDefinitionVersion()//安装版本信息
        .desc()//倒序
        .list();
    //输出流程定义的信息
    for (ProcessDefinition processDefinition : list) {
        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());
        System.out.println("--------------------------------------------------");
    }

}

//结果
//相同key,则自动提升版本
//流程定义的id:myLeave:2:f6844e42-0774-11ed-96b3-005056c00001
//流程定义的name:员工请假审批流程
//流程定义的key:myLeave
//流程定义的version:2
//流程部署的id:f66888df-0774-11ed-96b3-005056c00001
//--------------------------------------------------
//流程定义的id:myLeave:1:fc307169-0773-11ed-9b87-005056c00001
//流程定义的name:员工请假审批流程
//流程定义的key:myLeave
//流程定义的version:1
//流程部署的id:fc1a2a46-0773-11ed-9b87-005056c00001
//--------------------------------------------------

3. 删除流程

/**
 * 删除流程
 */
@RequestMapping("deleteProcess")
@ResponseBody
public void deleteProcess() {
    String id = "f66888df-0774-11ed-96b3-005056c00001";
    //设置true,择优级联删除的效果。false如果已有实例,则会删除错误
    repositoryService.deleteDeployment(id, true);
}

4. 获取流程里面的资源文件

/**
 * 读取数据库中的资源文件
 */
@RequestMapping("searchProcesslFile")
@ResponseBody
public void searchProcesslFile() throws IOException {
    String id = "myLeave";
    //查询器
    ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
        .processDefinitionKey(id)
        .singleResult();
    //获取流程部署id
    String deploymentId = processDefinition.getDeploymentId();
    //通过repositoryService对象的相关方法来获取图片信息和bpmn信息
    //png图片
    InputStream pngInput = repositoryService
        .getResourceAsStream(deploymentId, processDefinition.getDiagramResourceName());
    //bpmn 文件的流
    InputStream bpmnInput = repositoryService
        .getResourceAsStream(deploymentId, processDefinition.getResourceName());
    //文件的保存
    File filePng = new File("E:/学习/activiti/evection.png");
    File fileBpmn = new File("E:/学习/activiti/evection.bpmn");
    OutputStream pngOut = new FileOutputStream(filePng);
    OutputStream bpmnOut = new FileOutputStream(fileBpmn);

    //输入流和输出流的转化 
    IOUtils.copy(pngInput, pngOut);
    IOUtils.copy(bpmnInput, bpmnOut);
    pngInput.close();
    pngOut.close();
    bpmnInput.close();
    bpmnOut.close();

}

5. 创建流程实例

/**
 * 创建流程实例
 */
@RequestMapping("addApplication")
@ResponseBody
public void addApplication() {
    String businessKey = "myLeave";
    //启动一个流程实例
    //ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(businessKey);
    //启动一个流程实例,设置业务id,长度最大255,通过processInstance.getBusinessKey()获取
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(businessKey,"businessKey");
    System.out.println("流程定义id:" + processInstance.getProcessDefinitionId());
    System.out.println("流程实例id:" + processInstance.getId());
    System.out.println("当前活动id:" + processInstance.getActivityId());
}

//结果:
//流程定义id:myLeave:2:a07c05cb-076f-11ed-afa5-005056c00001
//流程实例id:f6f5bf5a-0772-11ed-8dc3-005056c00001
//当前活动id:null

6. 查看流程底下存在哪些实例

/**
 * 查询流程下存在哪些实例
 * 可通过.processInstanceId等相关属性过滤
 */
@RequestMapping("searchProcessRunInstance")
@ResponseBody
public void searchProcessRunInstance() {
    String key = "myLeave";
    List<ProcessInstance> list = runtimeService.createProcessInstanceQuery().processDefinitionKey(key).list();
    //输出流程定义的信息
    for (ProcessInstance processInstance : list) {
        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());
        System.out.println("业务关键字:" + processInstance.getBusinessKey());
        System.out.println("------------" );
    }

}

//结果:
//流程实例id:906f1e33-0776-11ed-96b3-005056c00001
//所属流程定义id:myLeave:2:f6844e42-0774-11ed-96b3-005056c00001
//是否完成:false
//是否暂停:false
//当前活动标识:null
//业务关键字:null
//------------
//流程实例id:fece74da-0773-11ed-9b87-005056c00001
//所属流程定义id:myLeave:1:fc307169-0773-11ed-9b87-005056c00001
//是否完成:false
//是否暂停:false
//当前活动标识:null
//业务关键字:null
//------------

7. 根据流程和负责人查询任务

/**
 * 查询任务查询
 * 也可以不加过滤条件,查询出全部
 */
@RequestMapping("searchTask")
@ResponseBody
public void searchTask() {
    String assignee = "worker";
    String key = "myLeave";
    //根据流程的key和任务负责人 查询任务
    List<Task> list = taskService.createTaskQuery()
        .processDefinitionKey(key)
        .taskAssignee(assignee)
        .list();
    //输出当前用户具有的任务
    for (Task task : list) {
        System.out.println("流程实例id:" + task.getProcessDefinitionId());
        System.out.println("任务id:" + task.getId());
        System.out.println("任务负责人:" + task.getAssignee());
        System.out.println("任务名称:" + task.getName());
    }

}

//结果:
//流程实例id:myLeave:2:a07c05cb-076f-11ed-afa5-005056c00001
//任务id:2da138fa-0772-11ed-a901-005056c00001
//任务负责人:worker
//任务名称:创建请假流程

8. 处理流程

/**
 * 根据流程的key和任务负责人 处理任务
 */
@RequestMapping("solveTask")
@ResponseBody
public void solveTask() {
    String assignee = "worker";
    String key = "myLeave";
    //根据流程的key和任务负责人 查询任务
    Task task = taskService.createTaskQuery()
        .processDefinitionKey(key)
        .taskAssignee(assignee)
        .singleResult();
    //完成任务,跳到下一个流程
    taskService.complete(task.getId());
}

act_ru_execution:任务操作

act_ru_task:目前需要处理的任务表

9. 流程历史信息查看

/**
 * 流程历史信息查看
 * 即时删除了流程,但是流程的历史信息还是会被保存下来,存在hi**表中
 * 也可以不加过滤条件,查询出全部
 */
@RequestMapping("searchHistoricActivityInstance")
@ResponseBody
public void searchHistoricActivityInstance() {
    String id = "myLeave:1:fc307169-0773-11ed-9b87-005056c00001";
    //获取actinst表的查询对象
    HistoricActivityInstanceQuery historicActivityInstanceQuery = historyService.createHistoricActivityInstanceQuery();
    //查询actinst表,根据流程id查询
    HistoricActivityInstanceQuery historicActivityInstanceQuery1 = historicActivityInstanceQuery.processDefinitionId(id);
    //查询actinst表,根据流程实例id查询
    //historicActivityInstanceQuery.processInstanceId(流程实例id);
    //排序
    historicActivityInstanceQuery1.orderByHistoricActivityInstanceStartTime().desc();
    //获取查询结果
    List<HistoricActivityInstance> list = historicActivityInstanceQuery1.list();
    //输出查询结果
    for (HistoricActivityInstance hi : list) {
        System.out.println(hi.getActivityId());
        System.out.println(hi.getActivityName());
        System.out.println(hi.getActivityType());
        System.out.println(hi.getAssignee());
        System.out.println(hi.getProcessDefinitionId());
        System.out.println(hi.getProcessInstanceId());
    }
}

//结果:
//_4
//部门经理审批
//userTask
//manager
//myLeave:1:fc307169-0773-11ed-9b87-005056c00001
//fece74da-0773-11ed-9b87-005056c00001
//_3
//创建请假流程
//userTask
//worker
//myLeave:1:fc307169-0773-11ed-9b87-005056c00001
//fece74da-0773-11ed-9b87-005056c00001
//_2
//StartEvent
//startEvent
//null
//myLeave:1:fc307169-0773-11ed-9b87-005056c00001
//fece74da-0773-11ed-9b87-005056c00001

10. 单个流程全部实例挂起

/**
  * 全部流程实例挂起和激活
 */
@RequestMapping("allLockOrOpenPeocess")
@ResponseBody
public void allLockOrOpenPeocess() {
    String id = "myLeave";
    ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
        .processDefinitionKey(id)
        .singleResult();
    //获取流程的状态
    boolean suspended = processDefinition.isSuspended();
    String pdId = processDefinition.getId();
    //如果激活就挂起,挂起就激活
    if (suspended) {
        //表示当前是挂起的,需要激活。
        //参数:流程定义id、是否激活、激活时间
        repositoryService.activateProcessDefinitionById(pdId, true, null);
        System.out.println("流程定义:" + pdId + ",已激活");
    } else {
        //激活状态,则需要挂起
        //参数:流程定义id、是否挂起、挂起时间
        repositoryService.suspendProcessDefinitionById(pdId, true, null);
        System.out.println("流程定义:" + pdId + ",已挂起");
    }
}

11. 单个实例挂起和激活

/**
  * 单个流程实例挂起和激活
  */
@RequestMapping("singleLockOrOpenPeocess")
@ResponseBody
public void singleLockOrOpenPeocess() {
    //task表的proc_inst_id
    String id = "dc609b81-082e-11ed-a65d-005056c00001";
    //获取实例对象
    ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
        .processInstanceId(id)
        .singleResult();
    //获取状态
    boolean suspended = processInstance.isSuspended();
    String pdId = processInstance.getId();
    if (suspended) {
        //表示当前是挂起的,需要激活
        runtimeService.activateProcessInstanceById(pdId);
        System.out.println("流程定义:" + pdId + ",已激活");
    } else {
        //激活状态,则需要挂起
        runtimeService.suspendProcessInstanceById(pdId);
        System.out.println("流程定义:" + pdId + ",已挂起");
    }
}

六、activiti接口进阶(变量启动)

  1. 流程变量

    Global变量:这个是流程变量的默认作用域,表示是一个完整的流程实例。Global变量名不能重复,如果重复则会被后面的覆盖。

    Local变量:Local变量只针对一个任务或者一个执行实例,变量名可相同,互不影响。

    ps1:如果设置了流程变量,就必须复制,否则将会报错导致流程结束。

    ps2:如果连线分支不设置条件,默认走sequenceFlow id(可在xml查看)小的那条线。

  2. 画分支图,并且设置流程审批人变量,依次设置为 a s s i g n e e 0 、 {assignee0}、 assignee0{assignee1}、 a s s i g n e e 2 、 {assignee2}、 assignee2{assignee3}
    activiti7,新手,数据库,运维,大数据

  3. 启动流程,并且创建实例(带变量)

    /**
      * 启动流程(创建新的申请流程实例列表)
      */
    @RequestMapping("addApplication")
    @ResponseBody
    public void addApplication() {
        Map<String,Object> variables=new HashMap<>();
        Map<String ,Object>  evention=new HashMap<>();
        evention.put("num",2);
    
        variables.put("evention",evention);
        variables.put("assignee0","申请人");
        variables.put("assignee1","部门经理");
        variables.put("assignee2","总经理");
        variables.put("assignee3","财务人事");
    
        String key = "myLeave1";
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(key,variables);
    }
    
  4. 依次调用solveTask方法,可以发现最终走的分支是num小于3的分支,即不经过总经理审批。

  5. 也可以在每次执行时,重新设置本地变量

    ps:这里需要留意,7.1.0.M1版本的activiti无法直接在complete时覆盖全局和本地变量,只能通过设置本地变量覆盖。

    /**
     * 启动流程(创建新的申请流程实例列表)
     */
    @RequestMapping("addApplication")
    @ResponseBody
    public void addApplication() {
        Map<String,Object> variables=new HashMap<>();
        Map<String ,Object>  evention=new HashMap<>();
        evention.put("num",2);
    
        variables.put("evention",evention);
        variables.put("assignee0","申请人");
        variables.put("assignee1","部门经理");
        variables.put("assignee2","总经理");
        variables.put("assignee3","财务人事");
    
        String key = "myLeave1";
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(key,variables);
    }
    
    /**
     * 根据流程的key和任务负责人 处理任务
     */
    @RequestMapping("solveTask")
    @ResponseBody
    public void solveTask() {
        String assignee = "申请人";
        String id = "myLeave1";
        //根据流程的key和任务负责人 查询任务
        Task task = taskService.createTaskQuery()
            .processDefinitionKey(id)
            .taskAssignee(assignee)
            .singleResult();
    
        //完成任务,跳到下一个流程
        Map<String,Object> variables=new HashMap<>();
        Map<String ,Object>  evention=new HashMap<>();
        evention.put("num",2);
    
        variables.put("evention",evention);
        variables.put("assignee0","申请人1");
        variables.put("assignee1","部门经理1");
        variables.put("assignee2","总经理1");
        variables.put("assignee3","财务人事1");
    
        taskService.setVariablesLocal(task.getId(),variables);
        taskService.complete(task.getId());
    }
    
    /**
     * 根据流程的key和任务负责人 处理任务
     */
    @RequestMapping("solveTaskForVariables")
    @ResponseBody
    public void solveTaskForVariables() {
        String assignee = "部门经理1";
        String id = "myLeave1";
        //根据流程的key和任务负责人 查询任务
        Task task = taskService.createTaskQuery()
            .processDefinitionKey(id)
            .taskAssignee(assignee)
            .singleResult();
        //完成任务,跳到下一个流程
        Map<String,Object> variables=new HashMap<>();
        Map<String ,Object>  evention=new HashMap<>();
        evention.put("num",2);
    
        variables.put("evention",evention);
        variables.put("assignee0","申请人2");
        variables.put("assignee1","部门经理2");
        variables.put("assignee2","总经理2");
        variables.put("assignee3","财务人事2");
    
        taskService.setVariablesLocal(task.getId(),variables);
        taskService.complete(task.getId());
    }
    

    然后查询当前任务

    /**
     * 根据流程的key查询存在哪些任务
     */
    @RequestMapping("searchTaskByKey")
    @ResponseBody
    public void searchTaskByKey() {
        String key = "myLeave1";
        //根据流程的key和任务负责人 查询任务
        List<Task> tasks = taskService.createTaskQuery()
            .processDefinitionKey(key)
            .list();
    
        for (Task task : tasks) {
            System.out.println(task.getId());
            System.out.println(task.getName());
            System.out.println(task.getAssignee());
            System.out.println("--------------");
        }
    }
    
    //结果
    //3c18d52e-0841-11ed-b1d5-005056c00001
    //财务部审批
    //财务人事2
    //--------------
    

七、activiti网关

1. 排他网关

  1. 概念:用来在流程中实现决策。 当流程执行到这个网关,所有分支都会判断是否为true,如果为ture则执行。如果多个为true,则执行id值小的。如果没 有位true的,则抛出异常

  2. 流程图
    activiti7,新手,数据库,运维,大数据

2. 并行网关

  1. 概念:并行网关允许将流程分成多条分支,也可以把多条分支汇聚到一起。并行网关的线上面,写上条件也没有用,在并行网关的后面分支都要执行完成之后,才会走下一个任务,不然,只要有一个分支没有完成,后面的任务就不会走

  2. 流程图
    activiti7,新手,数据库,运维,大数据

3. 包含网关

  1. 概念:包含网关可以看做是排他网关和并行网关的结合体。和排他网关一样,你可以在外出顺序流上定义条件,包含网关会解析它们,不定义则默认放行。 但是主要的区别是包含网关可以选择多于一条顺序流,这和并行网关一样。这也是用的最多的网关。

  2. 流程图 activiti7,新手,数据库,运维,大数据

八、组任务流程

  1. 概念

    即任务的下一个处理人不再是一个具体的人员,而是一组候选人。候选人可以主动拾取任务,然后办理。

  2. 流程图,即再流程的第二步,经理或总经理需要拾取任务才能进行处理
    activiti7,新手,数据库,运维,大数据

  3. 代码实现

    由于activiti需要整合Security框架,所以需要做好权限配置,这里是简单做了个lisi用户的配置

    package activiti.config;
    
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.context.annotation.ComponentScan;
    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 {
        private Logger logger = LoggerFactory.getLogger(SecurityUtil.class);
    
        @Autowired
        @Qualifier("myUserDetailsService")
        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");
            }
            logger.info("> Logged in as: " + username);
    
            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);
        }
    }
    
    package activiti.config;
    
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    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
    public class SpringSecurityConfiguration {
        private Logger logger = LoggerFactory.getLogger(SpringSecurityConfiguration.class);
        @Bean
        public UserDetailsService myUserDetailsService() {
            InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();
            //这里添加用户,后面处理流程时用到的任务负责人,需要添加在这里
            String[][] usersGroupsAndRoles = {
                    {"lisi", "password", "ROLE_ACTIVITI_USER", "GROUP_activitiTeam"},
                    {"system", "password", "ROLE_ACTIVITI_USER"},
                    {"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;
        }
        @Bean
        public PasswordEncoder passwordEncoder() {
            return new BCryptPasswordEncoder();
        }
    }
    

    查找并且拾取任务

    /**
     * 根据流程的key和候选人拾取任务
     * 由于是测试,所以返回单个任务。正常应该是列表展示所有候选任务,然后选择拾取。
     */
    @RequestMapping("claimTask")
    @ResponseBody
    public void claimTask() {
        String taskCandidateUser = "lisi";
        String id = "myLeave5";
        //根据流程的key和任务负责人 查询任务
        Task task = taskService.createTaskQuery()
            .processDefinitionKey(id)
            .taskCandidateUser(taskCandidateUser)
            .singleResult();
    
        if(task!=null){
            taskService.claim(task.getId(),taskCandidateUser);
        }
    }	
    

    lisi处理任务文章来源地址https://www.toymoban.com/news/detail-645863.html

    /**
     * 根据流程的key和任务负责人 处理任务
     */
    @RequestMapping("solveTask")
    @ResponseBody
    public void solveTask() {
        String assignee = "lisi";
        String id = "myLeave5";
        //根据流程的key和任务负责人 查询任务
        Task task = taskService.createTaskQuery()
            .processDefinitionKey(id)
            .taskAssignee(assignee)
            .singleResult();
        //完成任务,跳到下一个流程
        taskService.complete(task.getId());
    }
    

到了这里,关于activiti7入门教程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 新手入门Jenkins自动化部署入门详细教程

    在实际开发中,我们经常要一边开发一边测试,当然这里说的测试并不是程序员对自己代码的单元测试,而是同组程序员将代码提交后,由测试人员测试; 或者前后端分离后,经常会修改接口,然后重新部署; 这些情况都会涉及到频繁的打包部署; 手动打包常规步骤: 1.提

    2024年02月13日
    浏览(53)
  • StarkNet新手入门教程:教你用bitget 钱包入门

    理想的Starknet (web3.bitget.com/zh/assets/starknet-wallet) 钱包取决于个人喜好,同时考虑安全性、用户友好性、帐户恢复选项和多通证支持等因素。尽管如此,无论您使用 Starknet (STRK) 的目的是持有还是交易,Bitget Wallet 都是您管理 STRK 以及其他以太坊和 Optimism 加密资产的理想钱包选择

    2024年03月12日
    浏览(52)
  • 【Jmeter】压力测试新手入门教程

    压力测试是每一个Web应用程序上线之前都需要做的一个测试,他可以帮助我们发现系统中的瓶颈问题,减少发布到生产环境后出问题的几率;预估系统的承载能力,使我们能根据其做出一些应对措施。所以压力测试是一个非常重要的步骤,下面我带大家来使用一款压力测试工

    2024年04月15日
    浏览(52)
  • 电脑黑客技术新手入门,自学黑客技术入门教程

    最近经常有小伙伴联系我说要学黑客技术,当然目的各种各样,有的就是觉得黑客很酷,单纯想要学技术,还有的就是想找人帮忙攻击赌博网站或者监听别人的电话(以女朋友的电话居多),对于想要单纯学技术的朋友我很欢迎他们问我问题,但对于那些想做违法事情的人我

    2024年02月10日
    浏览(49)
  • 小程序注册安装以及新手快速入门教程

    一、注册并安装微信小程序 1.打开  https://mp.weixin.qq.com/  网址,点击立即注册即可进入小程序开发账号的注册流程,注册的账号类型选择 小程序 。 2.根据注册要求注册,发送邮箱信息,接收到微信团队发送的邮箱信息后,点击链接进行激活,如果出现 红色感叹号 可参考下

    2024年02月09日
    浏览(61)
  • 你好,uv变换(新手入门向聊天教程)

    温馨提示:本文只是一篇入门聊天,不涉及代码教程,看不懂代码就跳过,没关系! 1、uv其实就是一个二维坐标系啊,就俩轴,就跟xy轴一样。 那为什么不叫xy,反而叫uv呢? 不知道,应该是为了跟空间坐标系xyz区别开来,以免在工作流程中产生误解吧吧吧。 2、uv坐标用于采

    2024年02月12日
    浏览(42)
  • Python电商爬虫保姆级入门教程(纯新手向)

    图灵Python课堂 长沙图灵教育于2001年开始进入教育行业,立足泛IT类职业教育,以打造高新技术人才为宗旨,专注于提供多层次、个性化的职业技能培训课程,为各行业培养技术开发、应用和管理等岗位的中高端人才,致力于成为优质的职业教育内容提供商。 0 1 Python优势 1、

    2024年02月15日
    浏览(48)
  • Python 安装教程,新手入门(超详细)含Pycharm开发环境安装教程

    目录 一、Python介绍 二、Python安装教程 (一)Python的下载 (二)Python的安装 三、Pycharm开发工具的安装 (一)Pycharm介绍 (二)Pycharm的下载 (三)Pycharm的安装 ​        Python由荷兰数学和计算机科学研究学会的吉多·范罗苏姆于1990年代初设计,作为一门叫做ABC语言的替

    2024年01月20日
    浏览(86)
  • MUI框架从新手入门【webapp开发教程】

    性能和体验的差距,一直是mobile app开发者放弃HTML5的首要原因。 浏览器天生的切页白屏、不忍直视的转页动画、浮动元素的抖动、无法流畅下拉刷新等问题,这些都让HTML5开发者倍感挫败,尤其拿到Android低端机运行,摔手机的心都有; 另一方面,浏览器默认控件样式又少又

    2024年02月04日
    浏览(47)
  • 微信小程序新手入门教程一:零基础上手

    小程序是一种全新的连接用户与服务的方式,它可以在微信内被便捷地获取和传播,同时具有出色的使用体验。它提供了一个简单、高效的应用开发框架和丰富的组件及API,帮助开发者在微信中开发具有原生 APP 体验的服务。 1.开发环境不同。 网页运行在浏览器环境中,而小

    2024年03月18日
    浏览(55)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包