Activiti 用户绑定申请审批全流程演示

将导出的.bpmn20.xml文件拷贝到项目文件夹/resources/processes下,application.properties文件添加配置项

spring.activiti.database-schema-update=true

databaseSchemaUpdate配置项可以设置流程引擎启动和关闭时数据库执行的策略。 databaseSchemaUpdate有以下四个值:

  • false:false为默认值,设置为该值后,Activiti在启动时,会对比数据库表中保存的版本,如果没有表或者版本不匹配时,将在启动时抛出异常。

  • true:设置为该值后,Activiti会对数据库中所有的表进行更新,如果表不存在,则Activiti会自动创建。

  • create-drop:Activiti启动时,会执行数据库表的创建操作,在Activiti关闭时,执行数据库表的删除操作。

  • drop-create:Activiti启动时,执行数据库表的删除操作在Activiti关闭时,会执行数据库表的创建操作。

启动应用,会在数据库里创建28张表,表创建好之后停止应用。application.properties文件修改配置项

#每次应用启动不检查Activiti数据表是否存在及版本号是否匹配,提升应用启动速度

spring.activiti.database-schema-update=false

2、application.properties文件增加配置项

#保存历史数据级别设置为full最高级别,便于历史数据的追溯

spring.activiti.history-level=full

对于历史数据,保存到何种粒度,Activiti提供了history-level属性对其进行配置。history-level属性有点像log4j的日志输出级别,该属性有以下四个值:

  • none:不保存任何的历史数据,因此,在流程执行过程中,这是最高效的。

  • activity:级别高于none,保存流程实例与流程行为,其他数据不保存。

  • audit:除activity级别会保存的数据外,还会保存全部的流程任务及其属性。audit为history的默认值。

  • full:保存历史数据的最高级别,除了会保存audit级别的数据外,还会保存其他全部流程相关的细节数据,包括一些流程参数等。

3、Activiti的7大接口

完成以上步骤,就可以在程序中使用自动注入的方式,使用

@Autowired

private RuntimeService runtimeService;

@Autowired

private TaskService taskService;

@Autowired

private IdentityService identityService;

@Autowired

private RepositoryService repositoryService;

@Autowired

private ProcessEngine processEngine;

@Autowired

private HistoryService historyService;

三、项目中的用户、角色与Activiti中的用户、用户组整合


每个项目都有自己的用户、角色表,Activiti也有自己的用户、用户组表。因此项目中的用户、角色与Activiti中的用户、用户组要做整合。

//项目中每创建一个新用户,对应的要创建一个Activiti用户

//两者的userId和userName一致

User admin=identityService.newUser(“1”);

admin.setLastName(“admin”);

identityService.saveUser(admin);

//项目中每创建一个角色,对应的要创建一个Activiti用户组

Group adminGroup=identityService.newGroup(“1”);

adminGroup.setName(“admin”);

identityService.saveGroup(adminGroup);

//用户与用户组关系绑定

identityService.createMembership(“1”,“1”);

四、请假审批流程


1、请假申请和请假审批数据库表设计

表设计原则:流程数据和业务数据相分离。Activiti相关表只负责流程的跳转、走向等。流程中产生的业务表单数据、审批意见、附件等存储在开发人员定义的业务表中。流程数据和业务数据之间通过processInstanceId(流程实例ID)和业务数据主键相互关联。

为什么不使用Activiti相关表来存储表单数据和附件?

Activiti为了应用的灵活性和通用性采用了纵表的方式存储表单数据。假设一条请假申请表单数据有10个字段,那就需要10条记录存储原本横表只需要一条记录存储的数据。采用纵表的方式会有如下问题:

  • 会有大量的冗余数据并且数据量会急剧的增长

  • 查询语句复杂,查询效率低

  • 尤其不适合做后期的统计报表分析

Activiti存储附件使用Blob数据格式,文件存储在数据库里,数据库的数据文件会变得超大,不利于数据库备份和迁移。

请假申请表结构

2、填写请假申请表单,启动流程实例

//启动流程实例,字符串"vacation"是BPMN模型文件里process元素的id

ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(“vacation”);

//流程实例启动后,流程会跳转到请假申请节点

Task vacationApply = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();

//设置请假申请任务的执行人

taskService.setAssignee(vacationApply.getId(), req.getUserId().toString());

//设置流程参数:请假天数和表单ID

//流程引擎会根据请假天数days>3判断流程走向

//formId是用来将流程数据和表单数据关联起来

Map<String, Object> args = new HashMap<>();

args.put(“days”, req.getDays());

args.put(“formId”, formId);

//完成请假申请任务

taskService.complete(vacationApply.getId(), args);

3、待审批列表

//查出当前登录用户所在的用户组

List groups = identityService.createGroupQuery()

.groupMember(String.valueOf(userId)).list();

List groupNames = groups.stream()

.map(group -> group.getName()).collect(Collectors.toList());

//查询用户组的待审批请假流程列表

List tasks = taskService.createTaskQuery()

.processDefinitionKey(“vacation”)

.taskCandidateGroupIn(groupNames)

.listPage(pageNum - 1, pageSize);

//根据流程实例ID查询请假申请表单数据

List processInstanceIds = tasks.stream()

.map(task -> task.getProcessInstanceId())

.collect(Collectors.toList());

List vacationApplyList =

vacationRepository.getVacationApplyList(processInstanceIds);

4、请假审批功能

//查询当前审批节点

Task vacationA

必看视频!获取2024年最新Java开发全套学习资料 备注Java

udit = taskService.createTaskQuery()

.taskId(req.getTaskId()).singleResult();

if (req.getAuditResult() == 1) {//审批通过

//设置流程参数:审批ID

Map<String, Object> args = new HashMap<>();

args.put(“auditId”, auditId);

//设置审批任务的执行人

taskService.claim(vacationAudit.getId(), req.getUserId().toString());

//完成审批任务

taskService.complete(vacationAudit.getId(), args);

} else {

//审批不通过,结束流程

runtimeService.deleteProcessInstance(vacationAudit.getProcessInstanceId(), auditId);

}

5、查看流程图功能

//controller层代码

@RequestMapping(value = “/image”, method = RequestMethod.GET)

public void image(HttpServletResponse response,

@RequestParam String processInstanceId) {

try {

InputStream is = vacationService.getDiagram(processInstanceId);

if (is == null)

return;

response.setContentType(“image/png”);

BufferedImage image = ImageIO.read(is);

OutputStream out = response.getOutputStream();

总结

我们总是喜欢瞻仰大厂的大神们,但实际上大神也不过凡人,与菜鸟程序员相比,也就多花了几分心思,如果你再不努力,差距也只会越来越大。

面试题多多少少对于你接下来所要做的事肯定有点帮助,但我更希望你能透过面试题去总结自己的不足,以提高自己核心技术竞争力。每一次面试经历都是对你技术的扫盲,面试后的复盘总结效果是极好的!

iagram(processInstanceId);

if (is == null)

return;

response.setContentType(“image/png”);

BufferedImage image = ImageIO.read(is);

OutputStream out = response.getOutputStream();

总结

我们总是喜欢瞻仰大厂的大神们,但实际上大神也不过凡人,与菜鸟程序员相比,也就多花了几分心思,如果你再不努力,差距也只会越来越大。

面试题多多少少对于你接下来所要做的事肯定有点帮助,但我更希望你能透过面试题去总结自己的不足,以提高自己核心技术竞争力。每一次面试经历都是对你技术的扫盲,面试后的复盘总结效果是极好的!

[外链图片转存中…(img-lOrxPgfE-1716435594542)]

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值