一、相关概念
-
工作流概念
工作流是指业务过程的部分或整体在计算机应用环境下的自动化。是对工作流程及其各操作步骤之间业务规则的抽象、概括描述。
-
activiti介绍
activiti是一个工作流引擎,可以将业务系统中复杂的业务流程抽取出来,使用专门的建模语言BPMN进行定义,业务流程按照预先定义的流程进行执行。实现了系统的流程由activiti进行管理,减少业务系统由于流程变更进行系统升级改造的工作流量,从而提高系统的健壮性,同时也减少了系统开发维护成本。
-
BPM(Business Process Management)
业务流程管理
-
BPM软件
通过BPM软件可以实现对业务流程的整个生命周期进行建模、自动化、管理监控和优化。
-
BPMN(Business Process MOdel And Notation 业务流程模型和符号)
业务流程模型和符号,是由BPMI开发的一套标准的业务流程建模符号,使用BPMN提供的符号可以创建业务流程。
-
ProcessDefinition:流程定义
-
ProcessInstance:流程实例
二、使用步骤
-
部署activiti
activiti是一个工作流程,业务系统访问activiti的接口,就可以方便操作流程间的相关数据,这样就可以把工作流环境和业务系统的环境集成在一起。
-
流程定义
使用activiti建模工具定义业务流程,生成.bpmn文件(通过xml定义业务流程)。
-
流程定义部署
使用activiti提供的api把流程定义的内容存储起来,再Activiti执行过中可以查询的内容。activiti执行把流程定内容存储在数据库中。
-
启动一个流程实例
流程实例也叫ProcessInstance
启动一个流程实例表示开始一次业务流程的执行
比如同一个流程,张三可以启动,李四也可以启动,但是两次流程实例是互不影响的。
-
用户查询待办任务
由于集成了activiti,所有的任务都可以直接通过activiti提供的api进行查询,不需要我们自己查库。
-
用户办理任务
流程办理等操作,也是可以直接使用activiti提供的api即可。
-
流程结束
当没有下一个需要办理的节点,说明任务就结束了。
三、activiti配置生成表
-
idea软件安装actiBPM插件,若idea找不到插件,可去官网下载,导入即可,可参考
https://blog.csdn.net/weixin_40496191/article/details/125097860
-
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>
-
配置文件配置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
-
启动项目,即可生成相关表
-
相关表关系
re表:流程定义和流程相关属性
ru表:运行时产生的数据
hi表:历史信息
ge表:通用信息
四、简单画一个流程
-
画图
创建demo.bpmn文件,简单实现流程图,id为“myLeave“,流程名称为“员工请假审批流程”,责任人从上往下依次为worker、manager、financer。
-
画完图后,可以将流程图导出来
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();
//获取流程部署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接口进阶(变量启动)
-
流程变量
Global变量:这个是流程变量的默认作用域,表示是一个完整的流程实例。Global变量名不能重复,如果重复则会被后面的覆盖。
Local变量:Local变量只针对一个任务或者一个执行实例,变量名可相同,互不影响。
ps1:如果设置了流程变量,就必须复制,否则将会报错导致流程结束。
ps2:如果连线分支不设置条件,默认走sequenceFlow id(可在xml查看)小的那条线。
-
画分支图,并且设置流程审批人变量,依次设置为 a s s i g n e e 0 、 {assignee0}、 assignee0、{assignee1}、 a s s i g n e e 2 、 {assignee2}、 assignee2、{assignee3}
-
启动流程,并且创建实例(带变量)
/** * 启动流程(创建新的申请流程实例列表) */ @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); }
-
依次调用solveTask方法,可以发现最终走的分支是num小于3的分支,即不经过总经理审批。
-
也可以在每次执行时,重新设置本地变量
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. 排他网关
-
概念:用来在流程中实现决策。 当流程执行到这个网关,所有分支都会判断是否为true,如果为ture则执行。如果多个为true,则执行id值小的。如果没 有位true的,则抛出异常
-
流程图
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() { @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(); } }
查找并且拾取任务文章来源:https://www.toymoban.com/news/detail-645863.html
/** * 根据流程的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模板网!