文章目录

  • 一、相关概念
  • 二、使用步骤
  • 三、activiti配置生成表
  • 四、简单画一个流程
  • 五、activiti接口基础api示例
    • 1. 代码创建流程
    • 2. 查询流程的定义
    • 3. 删除流程
    • 4. 获取流程里面的资源文件
    • 5. 创建流程实例
    • 6. 查看流程底下存在哪些实例
    • 7. 根据流程和负责人查询任务
    • 8. 处理流程
    • 9. 流程历史信息查看
    • 10. 单个流程全部实例挂起
    • 11. 单个实例挂起和激活
  • 六、activiti接口进阶(变量启动)
  • 七、activiti网关
    • 1. 排他网关
    • 2. 并行网关
    • 3. 包含网关
  • 八、组任务流程

一、相关概念

  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: 8080spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverusername: rootpassword: tigerurl: jdbc:mysql://localhost:3306/activiti?useUnicode=true&characterEncoding=utf-8 &allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2b8&nullCatalogMeansCurrent=truetype: com.alibaba.druid.pool.DruidDataSourceservlet:multipart:max-file-size: 100MBmax-request-size: 100MBactiviti:#    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. 启动项目,即可生成相关表

  5. 相关表关系

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

    ru表:运行时产生的数据

    hi表:历史信息

    ge表:通用信息

四、简单画一个流程

  1. 画图

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

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

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

    2)右键显示图标


    3)导出png图片

五、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();//获取流程部署idString 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_idString 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. 画分支图,并且设置流程审批人变量,依次设置为assignee0、{assignee0}、assignee0、{assignee1}、assignee2、{assignee2}、assignee2、{assignee3}

  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. 流程图

2. 并行网关

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

  2. 流程图

3. 包含网关

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

  2. 流程图

八、组任务流程

  1. 概念

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

  2. 流程图,即再流程的第二步,经理或总经理需要拾取任务才能进行处理

  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() {@Overridepublic Collection<? extends GrantedAuthority> getAuthorities() {return user.getAuthorities();}@Overridepublic Object getCredentials() {return user.getPassword();}@Overridepublic Object getDetails() {return user;}@Overridepublic Object getPrincipal() {return user;}@Overridepublic boolean isAuthenticated() {return true;}@Overridepublic void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {}@Overridepublic 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);@Beanpublic 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;}@Beanpublic 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处理任务

    /*** 根据流程的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入门教程相关推荐

  1. Kafka入门教程与详解

    1 Kafka入门教程 1.1 消息队列(Message Queue) Message Queue消息传送系统提供传送服务.消息传送依赖于大量支持组件,这些组件负责处理连接服务.消息的路由和传送.持久 ...

  2. 【CV】Pytorch一小时入门教程-代码详解

    目录 一.关键部分代码分解 1.定义网络 2.损失函数(代价函数) 3.更新权值 二.训练完整的分类器 1.数据处理 2. 训练模型(代码详解) CPU训练 GPU训练 CPU版本与GPU版本代码区别 ...

  3. python tornado教程_Tornado 简单入门教程(零)——准备工作

    前言: 这两天在学着用Python + Tornado +MongoDB来做Web开发(哈哈哈这个词好高端).学的过程中查阅了无数资料,也收获了一些经验,所以希望总结出一份简易入门教程供初学者参考.完 ...

  4. python向量计算库教程_NumPy库入门教程:基础知识总结

    原标题:NumPy库入门教程:基础知识总结 视学算法 | 作者 知乎专栏 | 来源 numpy可以说是 Python运用于人工智能和科学计算的一个重要基础,近段时间恰好学习了numpy,pandas, ...

  5. mysql query browswer_MySQL数据库新特性之存储过程入门教程

    MySQL数据库新特性之存储过程入门教程 在MySQL 5中,终于引入了存储过程这一新特性,这将大大增强MYSQL的数据库处理能力.在本文中将指导读者快速掌握MySQL 5的存储过程的基本知识,带领用 ...

  6. python tensorflow教程_TensorFlow入门教程TensorFlow 基本使用T

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 TensorFlow入门教程 TensorFlow 基本使用 TensorFlow官方中文教程 TensorFlow 的特点: 使用图 (graph) 来 ...

  7. air调用java,AIR2.0入门教程:与Java应用交互

    在之前的一篇文章中,我介绍了如何使用AIR2.0新增的NativeProcess类与本地进程进行交互和通讯,在那个例子里面我们使用了C++ 的代码,实际上只要是基于命令行的标准输入输出,AIR2.0的 ...

  8. 【Arduino】开发入门教程【一】什么是Arduino

    Arduino Arduino 是一款便捷灵活.方便上手的开源电子原型平台,包含硬件(各种型号的arduino板)和软件(arduino IDE).它适用于艺术家.设计师.爱好者和对于"互动 ...

  9. python 三分钟入门_Cython 三分钟入门教程

    作者:perrygeo 译者:赖勇浩(http://laiyonghao.com) 原文:http://www.perrygeo.net/wordpress/?p=116 我最喜欢的是Python,它 ...

最新文章

  1. 如果不写Order By子句,会怎么样
  2. VC++ inline内联函数的作用解决方案
  3. 从Proxy到Vue3数据绑定
  4. Spring Session 的两种刷新模式-RedisFlushMode
  5. VS2008 安装盘的问题
  6. 基本概念—监督与非监督
  7. OkHttp实现分析之Websocket
  8. linux用if语句编程序,Shell 脚本基础 - 使用 if 语句进行条件检测
  9. LeetCode 1138. 字母板上的路径
  10. BI工具选型需考虑哪些问题
  11. IDEA 提示Unmapped Spring configuration files found的解决办法
  12. 四、降维——流形学习 (manifold learning)
  13. YOLOv3论文中英文对照翻译
  14. iPhone手机在Apple启动logo处卡住,无法开机该怎么办?
  15. 一周新论文 | 2020年第13周 | 自然语言处理相关
  16. 音乐音频 | openSMILE提取音频需要掌握的知识
  17. 不完美才美—少有人知道的幸福之路
  18. 清华计算机应用复试笔试,清华计算机系复试指南(下) - 清华大学 - 王道论坛,专注于计算机考研的点点滴滴! - Powered by Discuz!...
  19. android 3d魔方 代码,3D魔方 - android代码库 - 云代码
  20. 数据结构笔记(王道考研) 第一章:绪论

热门文章

  1. mac java模拟器_iOS学习——如何在mac上获取开发使用的模拟器的资源以及模拟器中每个应用的应用沙盒...
  2. Unity 3D 资源导入 监听导入事件
  3. 文本审核 API 收集
  4. js vue 前端代码混淆webpack-obfuscator
  5. 中国科学院大学21年计算机考研情况 信工所、成都计算所情况
  6. W801/W800/W806唯一ID/CPUID/FLASHID
  7. 新闻网站爬虫及一个简单爬取结果的查询网站的实现
  8. 基于Html+Bootstrap的高校智慧学习平台WEB界面设计
  9. 计算机自动维护有用吗,如何管理 Windows 10 自动维护功能
  10. Python课本第2章习题参考答案(第二版)(Python绘制蟒蛇,中美汇率转换,等边三角形,叠加等边三角形,无角正方形,六角形,正方形螺线)...