1、act_ge_ 通用数据表,ge是general的缩写
2、act_hi_ 历史数据表,hi是history的缩写,对应HistoryService接口
3、act_id_ 身份数据表,id是identity的缩写,对应IdentityService接口
4、act_re_ 流程存储表,re是repository的缩写,对应RepositoryService接口,存储流程部署和流程定义等静态数据
5、act_ru_ 运行时数据表,ru是runtime的缩写,对应RuntimeService接口和TaskService接口,存储流程实例和用户任务等动态数据
1.将Activiti提供的流程设计器应用activiti-app.war部署到Tomcat的webapps目录。
2.创建新的MySql数据库。修改activiti-app\WEB-INF\classes\META-INF\activiti-app目录下的activiti-app.properties配置文件,默认使用H2内存数据库,创建的模型重启后会丢失,改成使用MySql数据库。
3.浏览器访问http://localhost:8080/activiti-app,登录账户:admin:test
4.创建一个请假审批流程图
给每个用户任务指派候选组(有权限执行当前任务的角色)
排他网关设置条件分支表达式
5.导出流程图为.bpmn20.xml文件
1.在POM文件中添加依赖
<dependency>
<groupId>org.activitigroupId>
<artifactId>activiti-spring-boot-starter-basicartifactId>
<version>6.0.0version>
dependency>
2.将导出的.bpmn20.xml文件拷贝到项目文件夹/resources/processes下
3.application.properties文件添加配置项
spring.activiti.database-schema-update=true
databaseSchemaUpdate配置项可以设置流程引擎启动和关闭时数据库执行的策略。 databaseSchemaUpdate有以下四个值:
4.启动应用,会在数据库里创建28张表,表创建好之后停止应用。application.properties文件修改配置项
#每次应用启动不检查Activiti数据表是否存在及版本号是否匹配,提升应用启动速度
spring.activiti.database-schema-update=false
5.application.properties文件增加配置项
#保存历史数据级别设置为full最高级别,便于历史数据的追溯
spring.activiti.history-level=full
对于历史数据,保存到何种粒度,Activiti提供了history-level属性对其进行配置。history-level属性有点像log4j的日志输出级别,该属性有以下四个值:
@Autowired
private RuntimeService runtimeService;
private TaskService taskService;
private IdentityService identityService;
private RepositoryService repositoryService;
private ProcessEngine processEngine;
private HistoryService historyService;
每个项目都有自己的用户、角色表,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数据格式,文件存储在数据库里,数据库的数据文件会变得超大,不利于数据库备份和迁移。
请假申请表结构
请假审批表结构
//启动流程实例,字符串"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
.processDefinitionKey(“vacation”)
.taskCandidateGroupIn(groupNames)
.listPage(pageNum - 1, pageSize);
//根据流程实例ID查询请假申请表单数据
List
.map(task -> task.getProcessInstanceId())
.collect(Collectors.toList());
List
vacationRepository.getVacationApplyList(processInstanceIds);
4.请假审批功能
//查询当前审批节点
Task vacationAudit = 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();
ImageIO.write(image, "png", out);
is.close();
out.close();
} catch (Exception ex) {
logger.error("查看流程图失败", ex);
}
}
//service层代码
public InputStream getDiagram(String processInstanceId) {
//获得流程实例
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
.processInstanceId(processInstanceId).singleResult();
String processDefinitionId = StringUtils.EMPTY;
if (processInstance == null) {
//查询已经结束的流程实例
HistoricProcessInstance processInstanceHistory =
historyService.createHistoricProcessInstanceQuery()
.processInstanceId(processInstanceId).singleResult();
if (processInstanceHistory == null)
return null;
else
processDefinitionId = processInstanceHistory.getProcessDefinitionId();
} else {
processDefinitionId = processInstance.getProcessDefinitionId();
}
//使用宋体
String fontName = "宋体";
//获取BPMN模型对象
BpmnModel model = repositoryService.getBpmnModel(processDefinitionId);
//获取流程实例当前的节点,需要高亮显示
List<String> currentActs = Collections.EMPTY_LIST;
if (processInstance != null)
currentActs = runtimeService.getActiveActivityIds(processInstance.getId());
return processEngine.getProcessEngineConfiguration()
.getProcessDiagramGenerator()
.generateDiagram(model, "png", currentActs, new ArrayList<String>(),
fontName, fontName, fontName, null, 1.0);
}
最后,spring boot应用打成jar包部署的时候,需要注意:。