有上一章介绍了基本的数据结构,接下来我们以个人消费申请为例,介绍具体的开发步骤:
一、开发思路图
首先第一步画流程图,如下
PersonalConsumptionApplication.bpmn20.xml
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">
<process id="personalConsumptionApplication" name="个人消费申请" isExecutable="true">
<startEvent id="startevent1" name="Start"></startEvent>
<userTask id="usertask2" name="项目负责人审批" activiti:candidateGroups="group6"></userTask>
<sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask2"></sequenceFlow>
<exclusiveGateway id="exclusivegateway1" name="Exclusive Gateway"></exclusiveGateway>
<sequenceFlow id="flow2" sourceRef="usertask2" targetRef="exclusivegateway1"></sequenceFlow>
<userTask id="usertask3" name="财务审批" activiti:candidateGroups="group5"></userTask>
<sequenceFlow id="flow3" sourceRef="exclusivegateway1" targetRef="usertask3">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${approved}]]></conditionExpression>
</sequenceFlow>
<endEvent id="endevent1" name="End"></endEvent>
<sequenceFlow id="flow4" sourceRef="usertask3" targetRef="endevent1"></sequenceFlow>
<endEvent id="endevent2" name="End"></endEvent>
<sequenceFlow id="flow5" sourceRef="exclusivegateway1" targetRef="endevent2">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${!approved}]]></conditionExpression>
</sequenceFlow>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_personalConsumptionApplication">
<bpmndi:BPMNPlane bpmnElement="personalConsumptionApplication" id="BPMNPlane_personalConsumptionApplication">
<bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
<omgdc:Bounds height="35.0" width="35.0" x="140.0" y="150.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2">
<omgdc:Bounds height="55.0" width="105.0" x="220.0" y="140.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="exclusivegateway1" id="BPMNShape_exclusivegateway1">
<omgdc:Bounds height="40.0" width="40.0" x="370.0" y="148.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="usertask3" id="BPMNShape_usertask3">
<omgdc:Bounds height="55.0" width="105.0" x="455.0" y="141.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
<omgdc:Bounds height="35.0" width="35.0" x="605.0" y="151.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="endevent2" id="BPMNShape_endevent2">
<omgdc:Bounds height="35.0" width="35.0" x="373.0" y="260.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
<omgdi:waypoint x="175.0" y="167.0"></omgdi:waypoint>
<omgdi:waypoint x="220.0" y="167.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
<omgdi:waypoint x="325.0" y="167.0"></omgdi:waypoint>
<omgdi:waypoint x="370.0" y="168.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
<omgdi:waypoint x="410.0" y="168.0"></omgdi:waypoint>
<omgdi:waypoint x="455.0" y="168.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
<omgdi:waypoint x="560.0" y="168.0"></omgdi:waypoint>
<omgdi:waypoint x="605.0" y="168.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow5" id="BPMNEdge_flow5">
<omgdi:waypoint x="390.0" y="188.0"></omgdi:waypoint>
<omgdi:waypoint x="390.0" y="260.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
第二部权限配置(即代办人)
创建权限组:
//2、创建用户即用户组
@RequestMapping("/addUser")
public void addUser() {
//创建用户
User user1 = identityService.newUser("user1");
user1.setFirstName("张三");
user1.setLastName("张");
user1.setPassword("123456");
user1.setEmail("zhangsan@qq.com");
identityService.saveUser(user1);
User user2 = identityService.newUser("user2");
user2.setFirstName("李四");
user2.setLastName("李");
user2.setPassword("123456");
user2.setEmail("lisi@qq.com");
identityService.saveUser(user2);
User user3 = identityService.newUser("user3");
user3.setFirstName("王五");
user3.setLastName("王");
user3.setPassword("123456");
user3.setEmail("wangwu@qq.com");
identityService.saveUser(user3);
User user4 = identityService.newUser("user4");
user4.setFirstName("赵六");
user4.setLastName("赵");
user4.setPassword("123456");
user4.setEmail("wuliu@qq.com");
identityService.saveUser(user4);
User user5 = identityService.newUser("user5");
user5.setFirstName("田七");
user5.setLastName("田");
user5.setPassword("123456");
user5.setEmail("wuliu@qq.com");
identityService.saveUser(user5);
User user6 = identityService.newUser("user6");
user6.setFirstName("sa");
user6.setLastName("sa");
user6.setPassword("123456");
user6.setEmail("wuliu@qq.com");
identityService.saveUser(user6);
User admin = identityService.newUser("lm");
admin.setFirstName("lm");
admin.setLastName("lm");
admin.setPassword("123456");
admin.setEmail("wuliu@qq.com");
identityService.saveUser(admin);
//创建Activiti用户组
Group group1 = identityService.newGroup("group1");
group1.setName("员工组");
group1.setType("员工组");
identityService.saveGroup(group1);
Group group2 = identityService.newGroup("group2");
group2.setName("总监组");
group2.setType("总监阻");
identityService.saveGroup(group2);
Group group3 = identityService.newGroup("group3");
group3.setName("经理组");
group3.setType("经理组");
identityService.saveGroup(group3);
Group group4 = identityService.newGroup("group4");
group4.setName("人力资源组");
group4.setType("人力资源组");
identityService.saveGroup(group4);
Group group5 = identityService.newGroup("group5");
group5.setName("财务组");
group5.setType("财务组");
identityService.saveGroup(group5);
Group group6 = identityService.newGroup("group6");
group6.setName("项目组");
group6.setType("项目组");
identityService.saveGroup(group6);
//创建(用户-用户组)关系
identityService.createMembership("user1", "group1");//user1 在员工阻
identityService.createMembership("user2", "group2");//user2在总监组
identityService.createMembership("user3", "group3");//user3在经理组
identityService.createMembership("user4", "group4");//user4在人力资源组
identityService.createMembership("user5", "group5");//user5财务组
identityService.createMembership("user6", "group6");//user6项目组
}
好了创建玩用户组我们就可以给我们的流程图配置代办人了
下面我们就可以开发自己的业务代码了:
比如:
1、发起申请:
//申请
@RequestMapping("/getTaskList/{employee}/{description}")
public BaseResultModel submitApply(@PathVariable String employee, @PathVariable String description) {
// 流程引擎服务
RuntimeService runtimeService = processEngine.getRuntimeService();
Map<String, Object> variables = new HashMap<String, Object>();
variables.put("employee", employee);//申请人
variables.put("description", description);//申请描述
// 构建流程运行参数,启动流程
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("personalConsumptionApplication", variables);
String st = "流程id " + processInstance.getId() + " 发现审批的流程 : " + processInstance.getProcessDefinitionName();
return BaseResultModel.buildSuccess(st);
}
2、查看代办任务
//获取待办任务列表
@RequestMapping("/getTaskList/{userGroup}")
public String getTaskList(@PathVariable String userGroup) throws Exception {
// 获取待办任务列表
TaskService taskService = processEngine.getTaskService();
List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup(userGroup).list();
String st = "你有 " + tasks.size() + " 个待办任务:";
for (int i = 0; i < tasks.size(); i++) {
st += "<br/> 任务 " + (i + 1) + ") " + tasks.get(i);
}
return st;
}
3、审批
//审批
@RequestMapping("/submitApproval/{taskId}/{status}")
public BaseResultModel submitApproval(@PathVariable String taskId, @PathVariable Boolean status) throws Exception {
// 任务选择
System.out.println("请选择你要处理的任务ID?");
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
if (task == null) {
return BaseResultModel.buildFail("流程不存在");
}
String processInstanceId = task.getProcessInstanceId();
//通过审核
HashMap<String, Object> variables = new HashMap<>();
Map<String, Object> processVariables = taskService.getVariables(task.getId());
variables.put("approved", status);
taskService.complete(task.getId(), variables);
// 流程审批
String st = processVariables.get("employee") + " 申请 " + processVariables.get("description") + " 被任务的办理人: " + task.getAssignee()+(status ? " 同意" : " 拒绝");
return BaseResultModel.buildSuccess(st);
}
查看流程图进度
//查看流程图
@RequestMapping(value = "/image/{processInstanceId}", method = RequestMethod.GET)
public void image(HttpServletResponse response,
@PathVariable String processInstanceId) {
try {
InputStream is = 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) {
// lo.error("查看流程图失败", ex);
}
}
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);
}