└── demo-act-boot
├── pom.xml
└── src
└── main
├── java
└── com
│ └── demo
│ ├── ActBootServer.java
│ ├── data
│ └── init
│ │ ├── CleanData.java
│ │ ├── DataInit.java
│ │ └── VacationDeploy.java
│ ├── util
│ ├── ActUtils.java
│ ├── CustomProcessDiagramCanvas.java
│ ├── CustomProcessDiagramGenerator.java
│ └── SpringContextUtils.java
│ ├── vo
│ └── ProcessVO.java
│ └── web
│ ├── ProcessController.java
│ └── UserController.java
├── resources
├── activiti.cfg.xml
├── application.yml
├── log4j.properties
└── processes
│ └── vacation.bpmn
└── webapp
├── WEB-INF
└── web.xml
├── commons
└── taglibs.jsp
├── css
├── jquery-ui.css
├── main.css
├── nav.css
├── style.css
├── top.css
└── turn_page1.css
├── images
├── admin_content_bg.gif
├── admin_footer_bg.gif
├── admin_menu_parent_bg.gif
├── admin_nav_l.gif
├── admin_nav_on_l.gif
├── admin_nav_on_r.gif
├── admin_nav_r.gif
├── ajax_waiting.gif
├── ajax_waiting2.gif
├── alt_star.gif
├── button1.gif
├── button2.gif
├── button3.gif
├── button4.gif
├── check_error.gif
├── check_error2.gif
├── check_right.gif
├── content_bg1.gif
├── content_bg1_l.gif
├── content_bg1_r.gif
├── content_bottom_bg1.gif
├── gray_line1.gif
├── gray_line2.gif
├── gray_line3.gif
├── header_bg.gif
├── ico_contact.gif
├── ico_money.gif
├── ico_notice.gif
├── icon_angle1.gif
├── icon_arrow1.gif
├── icon_arrow10.gif
├── icon_arrow11.gif
├── icon_arrow12.gif
├── icon_arrow13.gif
├── icon_arrow14.gif
├── icon_arrow15.gif
├── icon_arrow16.gif
├── icon_arrow17.gif
├── icon_arrow18.gif
├── icon_arrow19.gif
├── icon_arrow2.gif
├── icon_arrow20.gif
├── icon_arrow21.gif
├── icon_arrow22.gif
├── icon_arrow23.gif
├── icon_arrow24.gif
├── icon_arrow25.gif
├── icon_arrow26.gif
├── icon_arrow27.gif
├── icon_arrow29.gif
├── icon_arrow3.gif
├── icon_arrow30.gif
├── icon_arrow4.gif
├── icon_arrow5.gif
├── icon_arrow6.gif
├── icon_arrow7.gif
├── icon_arrow8.gif
├── icon_arrow9.gif
├── icon_clip_1.gif
├── icon_clip_2.gif
├── icon_clip_3.gif
├── icon_clip_none.gif
├── icon_close.gif
├── icon_close2.gif
├── icon_comma.gif
├── icon_edit.gif
├── icon_excl.gif
├── icon_fav.gif
├── icon_hand.gif
├── icon_hand2.gif
├── icon_loading.gif
├── icon_minus1.gif
├── icon_msg.gif
├── icon_msg2.gif
├── icon_must.gif
├── icon_negative.gif
├── icon_neutral.gif
├── icon_next.gif
├── icon_next2.gif
├── icon_offline.gif
├── icon_online.gif
├── icon_online_none.gif
├── icon_plus1.gif
├── icon_plus2.gif
├── icon_plus3.gif
├── icon_positive.gif
├── icon_previous.gif
├── icon_price.gif
├── icon_report.gif
├── icon_s_assistant.gif
├── input_button1.gif
├── input_button2.gif
├── input_button3.gif
├── input_button4.gif
├── input_button5.gif
├── list1.gif
├── list2.gif
├── list3.gif
├── list4.gif
├── list5.gif
├── list6.gif
├── list7.gif
├── list8.gif
├── logo.jpg
├── main_bg.gif
├── manage_content_bg.gif
├── noface_150.gif
├── noface_40.gif
├── noface_80.gif
├── or_star_0.gif
├── or_star_1.gif
├── or_star_2.gif
├── or_star_3.gif
├── or_star_4.gif
├── or_star_5.gif
├── page_button.gif
├── page_button2.gif
├── page_button3.gif
├── person_id.gif
├── res_info_title_bg.gif
├── s_fy.gif
├── s_guide.gif
├── s_swzl.gif
├── sort_switch_bg.gif
├── sort_switch_on_l.gif
├── sort_switch_on_r.gif
├── title_bg1.gif
├── title_bg2.gif
├── title_bg3_l.gif
├── title_bg3_r.gif
├── title_bg4.gif
├── title_bg5.gif
├── title_bg6.gif
├── title_bg7.gif
├── xing1.gif
├── xing2.gif
├── xing3.gif
├── xing4.gif
└── xing5.gif
├── js
├── jquery-1.4.2.min.js
└── jquery-ui.min.js
└── pages
├── login.jsp
├── main.jsp
├── nav.jsp
├── top.jsp
├── vac
├── list.jsp
└── vacation.jsp
└── welcome.jsp
/demo-act-boot/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 | com.demo.activti
4 | demo-act-boot
5 | 0.0.1-SNAPSHOT
6 | war
7 |
8 |
9 | org.springframework.boot
10 | spring-boot-starter-parent
11 | 1.5.12.RELEASE
12 |
13 |
14 |
15 | 6.0.0
16 |
17 |
18 |
19 |
20 | org.springframework.boot
21 | spring-boot-starter-web
22 |
23 |
24 | org.springframework.boot
25 | spring-boot-starter-tomcat
26 |
27 |
28 |
29 |
30 | javax.servlet
31 | jstl
32 |
33 |
34 | org.apache.tomcat.embed
35 | tomcat-embed-jasper
36 | provided
37 |
38 |
39 | javax.servlet
40 | javax.servlet-api
41 | provided
42 |
43 |
44 | org.springframework.boot
45 | spring-boot-devtools
46 |
47 |
48 |
49 |
50 | org.activiti
51 | activiti-spring-boot-starter-basic
52 | ${activiti.version}
53 |
54 |
55 | de.odysseus.juel
56 | juel-spi
57 |
58 |
59 |
60 |
61 | mysql
62 | mysql-connector-java
63 |
64 |
65 |
66 | org.apache.commons
67 | commons-lang3
68 | 3.6
69 |
70 |
71 | org.springframework.boot
72 | spring-boot-starter-test
73 |
74 |
75 |
76 |
77 |
78 |
79 | org.apache.maven.plugins
80 | maven-compiler-plugin
81 |
82 | 1.8
83 | 1.8
84 | UTF-8
85 |
86 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/demo-act-boot/src/main/java/com/demo/ActBootServer.java:
--------------------------------------------------------------------------------
1 |
2 | package com.demo;
3 |
4 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
5 | import org.springframework.boot.autoconfigure.SpringBootApplication;
6 | import org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration;
7 | import org.springframework.boot.builder.SpringApplicationBuilder;
8 | import org.springframework.boot.web.servlet.ServletComponentScan;
9 | import org.springframework.boot.web.support.SpringBootServletInitializer;
10 | import org.springframework.context.annotation.ComponentScan;
11 |
12 | @SpringBootApplication
13 | @EnableAutoConfiguration(exclude = { SecurityAutoConfiguration.class })
14 | @ServletComponentScan
15 | @ComponentScan(basePackages = { "com.demo", "org.activiti.engine.*" })
16 | public class ActBootServer extends SpringBootServletInitializer {
17 |
18 | @Override
19 | protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
20 | // TODO Auto-generated method stub
21 | return builder;
22 | }
23 |
24 | public static void main(String[] args) {
25 | new SpringApplicationBuilder(ActBootServer.class).run(args);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/demo-act-boot/src/main/java/com/demo/data/init/CleanData.java:
--------------------------------------------------------------------------------
1 |
2 | package com.demo.data.init;
3 |
4 | import org.activiti.engine.ProcessEngineConfiguration;
5 |
6 | public class CleanData {
7 |
8 | public static void main(String[] args) {
9 | ProcessEngineConfiguration config = ProcessEngineConfiguration.createProcessEngineConfigurationFromResourceDefault();
10 | config.setDatabaseSchemaUpdate("drop-create");
11 | config.buildProcessEngine();
12 |
13 | config.buildProcessEngine().close();
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/demo-act-boot/src/main/java/com/demo/data/init/DataInit.java:
--------------------------------------------------------------------------------
1 |
2 | package com.demo.data.init;
3 |
4 | import org.activiti.engine.IdentityService;
5 | import org.activiti.engine.ProcessEngine;
6 | import org.activiti.engine.ProcessEngines;
7 | import org.activiti.engine.identity.Group;
8 | import org.activiti.engine.identity.User;
9 |
10 | public class DataInit {
11 |
12 | public static void main(String[] args) {
13 | ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
14 | IdentityService is = engine.getIdentityService();
15 | // 添加用户组
16 | Group empGroup = saveGroup(is, "empGroup", "员工组");
17 | Group manageGroup = saveGroup(is, "manageGroup", "经理组");
18 | Group dirGroup = saveGroup(is, "dirGroup", "总监组");
19 | // 添加用户
20 | User empA = saveUser(is, "empa"); // 员工a
21 | User empB = saveUser(is, "empb"); // 员工b
22 | User managea = saveUser(is, "managea"); // 经理a
23 | User manageb = saveUser(is, "manageb"); // 经理b
24 | User dira = saveUser(is, "dira"); // 总监a
25 | // 绑定关系
26 | saveRel(is, empA, empGroup);
27 | saveRel(is, empB, empGroup);
28 | saveRel(is, managea, manageGroup);
29 | saveRel(is, manageb, manageGroup);
30 | saveRel(is, dira, dirGroup);
31 |
32 | engine.close();
33 | }
34 |
35 | static User saveUser(IdentityService is, String id) {
36 | User u = is.newUser(id);
37 | u.setPassword("123456");
38 | is.saveUser(u);
39 | return u;
40 | }
41 |
42 | static Group saveGroup(IdentityService is, String id, String name) {
43 | Group g = is.newGroup(id);
44 | g.setName(name);
45 | is.saveGroup(g);
46 | return g;
47 | }
48 |
49 | static void saveRel(IdentityService is, User u, Group g) {
50 | is.createMembership(u.getId(), g.getId());
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/demo-act-boot/src/main/java/com/demo/data/init/VacationDeploy.java:
--------------------------------------------------------------------------------
1 |
2 | package com.demo.data.init;
3 |
4 | import org.activiti.engine.ProcessEngine;
5 | import org.activiti.engine.ProcessEngines;
6 | import org.activiti.engine.RepositoryService;
7 | import org.activiti.engine.repository.Deployment;
8 | import org.activiti.engine.repository.ProcessDefinition;
9 |
10 | public class VacationDeploy {
11 |
12 | public static void main(String[] args) {
13 | ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
14 | // 存储服务
15 | RepositoryService rs = engine.getRepositoryService();
16 | Deployment dep = rs.createDeployment().addClasspathResource("processes/vacation.bpmn").deploy();
17 | ProcessDefinition pd = rs.createProcessDefinitionQuery().deploymentId(dep.getId()).singleResult();
18 | rs.addCandidateStarterGroup(pd.getId(), "empGroup");
19 |
20 | engine.close();
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/demo-act-boot/src/main/java/com/demo/util/ActUtils.java:
--------------------------------------------------------------------------------
1 |
2 | package com.demo.util;
3 |
4 | import java.io.InputStream;
5 | import java.io.OutputStream;
6 | import java.util.ArrayList;
7 | import java.util.HashMap;
8 | import java.util.List;
9 | import java.util.Map;
10 |
11 | import org.activiti.bpmn.model.BpmnModel;
12 | import org.activiti.bpmn.model.FlowNode;
13 | import org.activiti.bpmn.model.SequenceFlow;
14 | import org.activiti.engine.HistoryService;
15 | import org.activiti.engine.ProcessEngineConfiguration;
16 | import org.activiti.engine.RepositoryService;
17 | import org.activiti.engine.RuntimeService;
18 | import org.activiti.engine.TaskService;
19 | import org.activiti.engine.history.HistoricActivityInstance;
20 | import org.activiti.engine.history.HistoricProcessInstance;
21 | import org.activiti.image.ProcessDiagramGenerator;
22 | import org.apache.commons.lang3.StringUtils;
23 | import org.slf4j.Logger;
24 | import org.slf4j.LoggerFactory;
25 | import org.springframework.util.CollectionUtils;
26 |
27 | /**
28 | * 流程工具类
29 | *
30 | * @author linyb1
31 | */
32 | public class ActUtils {
33 |
34 | private static Logger logger = LoggerFactory.getLogger(ActUtils.class);
35 |
36 | private static RepositoryService repositoryService = SpringContextUtils.getBean(RepositoryService.class);
37 | private static HistoryService historyService = SpringContextUtils.getBean(HistoryService.class);
38 | private static RuntimeService runtimeService = SpringContextUtils.getBean(RuntimeService.class);
39 | private static TaskService taskService = SpringContextUtils.getBean(TaskService.class);
40 | private static ProcessEngineConfiguration processEngineConfiguration = SpringContextUtils.getBean(ProcessEngineConfiguration.class);
41 |
42 | /**
43 | * 根据流程实例Id,获取实时流程图片
44 | *
45 | * @param processInstanceId
46 | * @param outputStream
47 | * @return
48 | */
49 | public static void getFlowImgByInstanceId(String processInstanceId, OutputStream outputStream) {
50 | try {
51 | if (StringUtils.isEmpty(processInstanceId)) {
52 | logger.error("processInstanceId is null");
53 | return;
54 | }
55 | // 获取历史流程实例
56 | HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
57 | // 获取流程中已经执行的节点,按照执行先后顺序排序
58 | List historicActivityInstances = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId)
59 | .orderByHistoricActivityInstanceId().asc().list();
60 | // 高亮已经执行流程节点ID集合
61 | List highLightedActivitiIds = new ArrayList<>();
62 | for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) {
63 | highLightedActivitiIds.add(historicActivityInstance.getActivityId());
64 | }
65 |
66 | List historicFinishedProcessInstances = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).finished()
67 | .list();
68 | ProcessDiagramGenerator processDiagramGenerator = null;
69 | // 如果还没完成,流程图高亮颜色为绿色,如果已经完成为红色
70 | if (!CollectionUtils.isEmpty(historicFinishedProcessInstances)) {
71 | // 如果不为空,说明已经完成
72 | processDiagramGenerator = processEngineConfiguration.getProcessDiagramGenerator();
73 | } else {
74 | processDiagramGenerator = new CustomProcessDiagramGenerator();
75 | }
76 |
77 | BpmnModel bpmnModel = repositoryService.getBpmnModel(historicProcessInstance.getProcessDefinitionId());
78 | // 高亮流程已发生流转的线id集合
79 | List highLightedFlowIds = getHighLightedFlows(bpmnModel, historicActivityInstances);
80 |
81 | // 使用默认配置获得流程图表生成器,并生成追踪图片字符流
82 | InputStream imageStream = processDiagramGenerator.generateDiagram(bpmnModel, "png", highLightedActivitiIds, highLightedFlowIds, "宋体", "微软雅黑", "黑体", null, 2.0);
83 |
84 | // 输出图片内容
85 | byte[] b = new byte[1024];
86 | int len;
87 | while ((len = imageStream.read(b, 0, 1024)) != -1) {
88 | outputStream.write(b, 0, len);
89 | }
90 | } catch (Exception e) {
91 | logger.error("processInstanceId" + processInstanceId + "生成流程图失败,原因:" + e.getMessage(), e);
92 | }
93 |
94 | }
95 |
96 | /**
97 | * 获取已经流转的线
98 | *
99 | * @param bpmnModel
100 | * @param historicActivityInstances
101 | * @return
102 | */
103 | private static List getHighLightedFlows(BpmnModel bpmnModel, List historicActivityInstances) {
104 | // 高亮流程已发生流转的线id集合
105 | List highLightedFlowIds = new ArrayList<>();
106 | // 全部活动节点
107 | List historicActivityNodes = new ArrayList<>();
108 | // 已完成的历史活动节点
109 | List finishedActivityInstances = new ArrayList<>();
110 |
111 | for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) {
112 | FlowNode flowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(historicActivityInstance.getActivityId(), true);
113 | historicActivityNodes.add(flowNode);
114 | if (historicActivityInstance.getEndTime() != null) {
115 | finishedActivityInstances.add(historicActivityInstance);
116 | }
117 | }
118 |
119 | FlowNode currentFlowNode = null;
120 | FlowNode targetFlowNode = null;
121 | // 遍历已完成的活动实例,从每个实例的outgoingFlows中找到已执行的
122 | for (HistoricActivityInstance currentActivityInstance : finishedActivityInstances) {
123 | // 获得当前活动对应的节点信息及outgoingFlows信息
124 | currentFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(currentActivityInstance.getActivityId(), true);
125 | List sequenceFlows = currentFlowNode.getOutgoingFlows();
126 |
127 | /**
128 | * 遍历outgoingFlows并找到已已流转的 满足如下条件认为已已流转: 1.当前节点是并行网关或兼容网关,则通过outgoingFlows能够在历史活动中找到的全部节点均为已流转 2.当前节点是以上两种类型之外的,通过outgoingFlows查找到的时间最早的流转节点视为有效流转
129 | */
130 | if ("parallelGateway".equals(currentActivityInstance.getActivityType()) || "inclusiveGateway".equals(currentActivityInstance.getActivityType())) {
131 | // 遍历历史活动节点,找到匹配流程目标节点的
132 | for (SequenceFlow sequenceFlow : sequenceFlows) {
133 | targetFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(sequenceFlow.getTargetRef(), true);
134 | if (historicActivityNodes.contains(targetFlowNode)) {
135 | highLightedFlowIds.add(targetFlowNode.getId());
136 | }
137 | }
138 | } else {
139 | List