新建springBoot項目時勾選activiti,或者在已創建的springBoot項目添加如下依賴:html
<dependency> <groupId>org.activiti</groupId> <artifactId>activiti-spring-boot-starter-basic</artifactId> <version>6.0.0</version> </dependency>
數據源和activiti配置:前端
server: port: 8081 spring: datasource: url: jdbc:mysql://localhost:3306/act5?useSSL=true driver-class-name: com.mysql.jdbc.Driver username: root password: root # activiti default configuration activiti: database-schema-update: true check-process-definitions: true process-definition-location-prefix: classpath:/processes/ # process-definition-location-suffixes: # - **.bpmn # - **.bpmn20.xml history-level: full
在activiti的默認配置中,process-definition-location-prefix 是指定activiti流程描述文件的前綴(即路徑),啓動時,activiti就會去尋找此路徑下的流程描述文件,而且自動部署;suffix 是一個String數組,表示描述文件的默認後綴名,默認以上兩種。java
package com.yawn.config; import org.springframework.context.annotation.Configuration; import org.springframework.format.FormatterRegistry; import org.springframework.http.HttpStatus; import org.springframework.web.servlet.config.annotation.*; /** * Created by yawn on 2017/8/5. */ @EnableWebMvc @Configuration public class MvcConfig extends WebMvcConfigurerAdapter { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/"); registry.addResourceHandler("/templates/**").addResourceLocations("classpath:/templates/"); super.addResourceHandlers(registry); } @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/index"); registry.addViewController("/user"); registry.addRedirectViewController("/","/templates/login.html"); // registry.addStatusController("/403", HttpStatus.FORBIDDEN); super.addViewControllers(registry); } }
配置了數據源和activiti後,啓動項目,activiti 的各個服務組件就已經被加入到spring容器中了,因此就能夠直接注入使用了。若是在未自動配置的spring環境中,能夠使用經過指定bean的init-method來配置activiti的服務組件。mysql
以如下請假流程爲例:web
private static final String PROCESS_DEFINE_KEY = "vacationProcess"; public Object startVac(String userName, Vacation vac) { identityService.setAuthenticatedUserId(userName); // 開始流程 ProcessInstance vacationInstance = runtimeService.startProcessInstanceByKey(PROCESS_DEFINE_KEY); // 查詢當前任務 Task currentTask = taskService.createTaskQuery().processInstanceId(vacationInstance.getId()).singleResult(); // 申明任務 taskService.claim(currentTask.getId(), userName); Map<String, Object> vars = new HashMap<>(4); vars.put("applyUser", userName); vars.put("days", vac.getDays()); vars.put("reason", vac.getReason()); // 完成任務 taskService.complete(currentTask.getId(), vars); return true; }
public Object myAudit(String userName) { List<Task> taskList = taskService.createTaskQuery().taskCandidateUser(userName) .orderByTaskCreateTime().desc().list(); // / 畫蛇添足 taskList中包含了如下內容(用戶的任務中包含了所在用戶組的任務) // Group group = identityService.createGroupQuery().groupMember(userName).singleResult(); // List<Task> list = taskService.createTaskQuery().taskCandidateGroup(group.getId()).list(); // taskList.addAll(list); List<VacTask> vacTaskList = new ArrayList<>(); for (Task task : taskList) { VacTask vacTask = new VacTask(); vacTask.setId(task.getId()); vacTask.setName(task.getName()); vacTask.setCreateTime(task.getCreateTime()); String instanceId = task.getProcessInstanceId(); ProcessInstance instance = runtimeService.createProcessInstanceQuery().processInstanceId(instanceId).singleResult(); Vacation vac = getVac(instance); vacTask.setVac(vac); vacTaskList.add(vacTask); } return vacTaskList; } private Vacation getVac(ProcessInstance instance) { Integer days = runtimeService.getVariable(instance.getId(), "days", Integer.class); String reason = runtimeService.getVariable(instance.getId(), "reason", String.class); Vacation vac = new Vacation(); vac.setApplyUser(instance.getStartUserId()); vac.setDays(days); vac.setReason(reason); Date startTime = instance.getStartTime(); // activiti 6 纔有 vac.setApplyTime(startTime); vac.setApplyStatus(instance.isEnded() ? "申請結束" : "等待審批"); return vac; } package com.yawn.entity; import java.util.Date; /** * @author Created by yawn on 2018-01-09 14:31 */ public class VacTask { private String id; private String name; private Vacation vac; private Date createTime; // getter setter ... }
public Object passAudit(String userName, VacTask vacTask) { String taskId = vacTask.getId(); String result = vacTask.getVac().getResult(); Map<String, Object> vars = new HashMap<>(); vars.put("result", result); vars.put("auditor", userName); vars.put("auditTime", new Date()); taskService.claim(taskId, userName); taskService.complete(taskId, vars); return true; }
因爲已完成的請假在數據庫runtime表中查不到(runtime表只保存正在進行的流程示例信息),因此須要在history表中查詢。spring
public Object myVacRecord(String userName) { List<HistoricProcessInstance> hisProInstance = historyService.createHistoricProcessInstanceQuery() .processDefinitionKey(PROCESS_DEFINE_KEY).startedBy(userName).finished() .orderByProcessInstanceEndTime().desc().list(); List<Vacation> vacList = new ArrayList<>(); for (HistoricProcessInstance hisInstance : hisProInstance) { Vacation vacation = new Vacation(); vacation.setApplyUser(hisInstance.getStartUserId()); vacation.setApplyTime(hisInstance.getStartTime()); vacation.setApplyStatus("申請結束"); List<HistoricVariableInstance> varInstanceList = historyService.createHistoricVariableInstanceQuery() .processInstanceId(hisInstance.getId()).list(); ActivitiUtil.setVars(vacation, varInstanceList); vacList.add(vacation); } return vacList; }
package com.yawn.util; import org.activiti.engine.history.HistoricVariableInstance; import java.lang.reflect.Field; import java.util.List; /** * activiti中使用獲得的工具方法 * @author Created by yawn on 2018-01-10 16:32 */ public class ActivitiUtil { /** * 將歷史參數列表設置到實體中去 * @param entity 實體 * @param varInstanceList 歷史參數列表 */ public static <T> void setVars(T entity, List<HistoricVariableInstance> varInstanceList) { Class<?> tClass = entity.getClass(); try { for (HistoricVariableInstance varInstance : varInstanceList) { Field field = tClass.getDeclaredField(varInstance.getVariableName()); if (field == null) { continue; } field.setAccessible(true); field.set(entity, varInstance.getValue()); } } catch (Exception e) { e.printStackTrace(); } } }
<div ng-controller="myAudit"> <h2 ng-init="myAudit()">待我審覈的請假</h2> <table border="0"> <tr> <td>任務名稱</td> <td>任務時間</td> <td>申請人</td> <td>申請時間</td> <td>天數</td> <td>事由</td> <td>操做</td> </tr> <tr ng-repeat="vacTask in vacTaskList"> <td>{{vacTask.name}}</td> <td>{{vacTask.createTime | date:'yyyy-MM-dd HH:mm:ss'}}</td> <td>{{vacTask.vac.applyUser}}</td> <td>{{vacTask.vac.applyTime | date:'yyyy-MM-dd HH:mm:ss'}}</td> <td>{{vacTask.vac.days}}</td> <td>{{vacTask.vac.reason}}</td> <td> <button type="button" ng-click="passAudit(vacTask.id, 1)">審覈經過</button> <button type="button" ng-click="passAudit(vacTask.id, 0)">審覈拒絕</button> </td> </tr> </table> </div> app.controller("myAudit", function ($scope, $http, $window) { $scope.vacTaskList = []; $scope.myAudit = function () { $http.get( "/myAudit" ).then(function (response) { $scope.vacTaskList = response.data; }) }; $scope.passAudit = function (taskId, result) { $http.post( "/passAudit", { "id": taskId, "vac": { "result": result >= 1 ? "審覈經過" : "審覈拒絕" } } ).then(function (response) { if (response.data === true) { alert("操做成功!"); $window.location.reload(); } else { alert("操做失敗!"); } }) } });
本人免費整理了Java高級資料,涵蓋了Java、Redis、MongoDB、MySQL、Zookeeper、Spring Cloud、Dubbo高併發分佈式等教程,一共30G,須要本身領取。
傳送門:https://mp.weixin.qq.com/s/igMojff-bbmQ6irCGO3mqA