├── .gitignore
├── Chapter03
├── README.md
├── activiti6-helloworld
│ ├── pom.xml
│ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── coderdream
│ │ │ │ └── activiti
│ │ │ │ └── helloworld
│ │ │ │ └── DemoMain.java
│ │ └── resources
│ │ │ ├── logback.xml
│ │ │ └── second_approve.bpmn
│ │ └── test
│ │ ├── java
│ │ └── com
│ │ │ └── coderdream
│ │ │ └── MyUnitTest.java
│ │ └── resources
│ │ ├── activiti.cfg.xml
│ │ ├── log4j.properties
│ │ └── my-process.bpmn20.xml
└── images
│ ├── 0305_01_IDEA_Setting_Terminal.png
│ ├── 0307_01_Process.png
│ ├── 0307_02_Add_Form.png
│ ├── 0307_03_Form01.png
│ ├── 0307_04_Form02.png
│ └── 0307_05_Form03.png
├── Chapter04
├── Chapter0410.md
├── Chapter0412.md
├── README.md
├── activiti-archetype-unittest2
│ ├── pom.xml
│ └── src
│ │ └── main
│ │ └── resources
│ │ ├── META-INF
│ │ └── maven
│ │ │ └── archetype-metadata.xml
│ │ └── archetype-resources
│ │ ├── pom.xml
│ │ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── DemoMain.java
│ │ └── resources
│ │ │ ├── activiti.cfg.xml
│ │ │ ├── logback.xml
│ │ │ └── second_approve.bpmn
│ │ └── test
│ │ ├── java
│ │ └── MyUnitTest.java
│ │ └── resources
│ │ ├── activiti.cfg.xml
│ │ ├── log4j.properties
│ │ └── my-process.bpmn20.xml
├── activiti6-samples
│ ├── config
│ │ ├── pom.xml
│ │ └── src
│ │ │ ├── main
│ │ │ ├── java
│ │ │ │ └── com
│ │ │ │ │ └── coderdream
│ │ │ │ │ ├── DemoMain.java
│ │ │ │ │ ├── delegate
│ │ │ │ │ └── MDCErrorDelegate.java
│ │ │ │ │ ├── event
│ │ │ │ │ ├── CustomEventListener.java
│ │ │ │ │ └── ProcessEventListener.java
│ │ │ │ │ └── interceptor
│ │ │ │ │ └── MDCCommandInvoker.java
│ │ │ └── resources
│ │ │ │ ├── activiti.cfg.xml
│ │ │ │ ├── activiti_druid.cfg.xml
│ │ │ │ ├── activiti_eventListener.cfg.xml
│ │ │ │ ├── activiti_eventlog.cfg.xml
│ │ │ │ ├── activiti_history.cfg.xml
│ │ │ │ ├── activiti_mdc.cfg.xml
│ │ │ │ ├── logback.xml
│ │ │ │ └── second_approve.bpmn
│ │ │ └── test
│ │ │ ├── java
│ │ │ └── com
│ │ │ │ └── coderdream
│ │ │ │ ├── MyUnitTest.java
│ │ │ │ └── config
│ │ │ │ ├── ConfigEventListenerTest.java
│ │ │ │ ├── ConfigEventLogTest.java
│ │ │ │ ├── ConfigHistoryLevelTest.java
│ │ │ │ ├── ConfigMDCTest.java
│ │ │ │ ├── ConfigTest.java
│ │ │ │ └── ConfitDBTest.java
│ │ │ └── resources
│ │ │ ├── activiti.cfg.xml
│ │ │ ├── log4j.properties
│ │ │ ├── my-process.bpmn20.xml
│ │ │ └── my-process_mdcerror.bpmn20.xml
│ └── pom.xml
└── images
│ ├── 0401_Project_Structrue.png
│ ├── 0402_Add_Archetype.png
│ ├── 0403_Create_From_Archetype.png
│ ├── 0404_ProcessEngineConfiguration.png
│ ├── 0406_01.jpg
│ ├── 0406_02.jpg
│ ├── 0406_03.jpg
│ ├── 0406_04.jpg
│ ├── 0406_05.jpg
│ ├── 0406_06.jpg
│ ├── 041000_Result.png
│ ├── 041001_ProcessEngineConfigurationImpl.png
│ ├── 041002_initDatabaseEventLogging.png
│ ├── 041003_EventLogger.png
│ ├── 041004_addCloseListener.png
│ ├── 041005_insert.png
│ ├── 041101.jpg
│ ├── 041102.jpg
│ ├── 041103.jpg
│ ├── 041104.jpg
│ ├── 041105.jpg
│ ├── 041201_ActivitiEventListener.png
│ ├── 041202_BaseEntityEventListener.png
│ ├── 041203_ActivitiEvent.png
│ ├── 041204_ActivitiEntityEvent.png
│ └── 041205_ActivitiVariableEvent.png
├── LICENSE
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled class file
2 | *.class
3 |
4 | # Log file
5 | *.log
6 |
7 | # BlueJ files
8 | *.ctxt
9 |
10 | # Mobile Tools for Java (J2ME)
11 | .mtj.tmp/
12 |
13 | # Package Files #
14 | *.jar
15 | *.war
16 | *.nar
17 | *.ear
18 | *.zip
19 | *.tar.gz
20 | *.rar
21 |
22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
23 | hs_err_pid*
24 | /target/
25 | target/
26 | .idea/
27 | /.idea/
28 | .idea
29 | *.idea
30 | *.iml
--------------------------------------------------------------------------------
/Chapter03/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## 第3章 Activiti6.0源码初探
4 | ### 3-1 本章概述
5 | ### 3-2 Activiti6.0源码初探-概览与获取
6 | ### 3-3 Activiti6.0源码初探-engine
7 | ### 3-4 Activiti6.0源码初探-模块介绍
8 | ### 3-5 Activiti6.0源码初探-activiti-app运行
9 | - 设置IDEA控制台:
10 | 
11 | - 在控制台执行命令:
12 | ```
13 | D:\Java\GitHub\Activiti6>cd modules/activiti-ui/activiti-app
14 | D:\Java\GitHub\Activiti6\modules\activiti-ui\activiti-app>mvn clean tomcat7:run
15 | ```
16 | - 执行结果:
17 | ```
18 | $ mvn clean tomcat7:run
19 | [INFO] Scanning for projects...
20 | [INFO] ------------------------------------------------------------------------
21 | [INFO] Building activiti-app 6.0.0
22 | [INFO] ------------------------------------------------------------------------
23 | ...
24 | [INFO] --- tomcat7-maven-plugin:2.2:run (default-cli) @ activiti-app ---
25 | [INFO] Running war on http://localhost:9999/activiti-app
26 | ...
27 | 一月 10, 2019 11:34:30 上午 org.apache.catalina.core.ApplicationContext log
28 | 信息: Initializing Spring FrameworkServlet 'apiDispatcher'
29 | 一月 10, 2019 11:34:33 上午 org.apache.catalina.core.ApplicationContext log
30 | 信息: Initializing Spring FrameworkServlet 'appDispatcher'
31 | 一月 10, 2019 11:34:33 上午 org.apache.coyote.AbstractProtocol start
32 | 信息: Starting ProtocolHandler ["http-nio-9999"]
33 | ```
34 | ### 3-6 Activiti6.0源码初探-WebConfigurer
35 | ### 3-7 Activiti6.0源码初探-helloword-1
36 |
37 | - 完整流程图:
38 | 
39 |
40 | - 参考下图新增表单数据(注意类型、模式和是否必填):
41 | 
42 |
43 | - 【填写审批信息】表单数据:
44 | 
45 |
46 | - 【主管审批】表单数据:
47 | 
48 |
49 | - 【人事审批】表单数据:
50 | 
51 |
52 |
53 | ### 3-8 Activiti6.0源码初探-helloword-2
54 |
55 | - 代码清单:pom.xml
56 | ```xml
57 |
58 |
62 | 4.0.0
63 |
64 | com.coderdream.activiti
65 | activiti6-helloworld
66 | 1.0-SNAPSHOT
67 |
68 |
69 |
70 | org.activiti
71 | activiti-engine
72 | 6.0.0
73 |
74 |
75 | junit
76 | junit
77 | 4.12
78 | test
79 |
80 |
81 | ch.qos.logback
82 | logback-classic
83 | 1.1.11
84 |
85 |
86 | com.google.guava
87 | guava
88 | 23.0
89 |
90 |
91 | com.h2database
92 | h2
93 | 1.4.193
94 |
95 |
96 |
97 |
98 | ```
99 |
100 | ### 3-9 Activiti6.0源码初探-helloword_idea-1
101 |
102 | 1、先梳理流程
103 |
104 | - 代码清单:DemoMain.java
105 | ```java
106 | public class DemoMain {
107 |
108 | private static final Logger LOGGER = LoggerFactory.getLogger(DemoMain.class);
109 |
110 | public static void main(String[] args) {
111 | LOGGER.info("启动我们的程序");
112 | // 创建流程引擎
113 | // 部署流程定义文件
114 | // 启动运行流程
115 | // 处理流程任务
116 | LOGGER.info("结束我们的程序");
117 | }
118 |
119 | }
120 | ```
121 | 2、配置log,只打印简易信息:
122 |
123 | - 代码清单:logback.xml
124 | ```xml
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 | ${plain}
136 | ${encoding}
137 |
138 |
139 |
140 |
141 |
143 | ${log.dir}/file.log
144 |
145 | ${log.dir}/file.%d{yyyy-MM-dd}.log
146 | 30
147 |
148 |
149 | ${std}
150 | ${encoding}
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 | ```
165 | 3、将流程文件拷贝到 resources 文件夹下:
166 |
167 | 4、完成完整流程代码
168 | - 代码清单:DemoMain.java
169 | ```java
170 | LOGGER.info("启动我们的程序");
171 | // 创建流程引擎
172 | ProcessEngineConfiguration cfg = ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration();
173 | ProcessEngine processEngine = cfg.buildProcessEngine();
174 | String name = processEngine.getName();
175 | String version = ProcessEngine.VERSION;
176 | LOGGER.info("流程引擎名称{},版本{}", name, version);
177 | // 部署流程定义文件
178 | RepositoryService repositoryService = processEngine.getRepositoryService();
179 | DeploymentBuilder deploymentBuilder = repositoryService.createDeployment();
180 | deploymentBuilder.addClasspathResource("second_approve.bpmn");
181 | Deployment deployment = deploymentBuilder.deploy();
182 | String deploymentId = deployment.getId();
183 | ProcessDefinition processDefinition = repositoryService
184 | .createProcessDefinitionQuery()
185 | .deploymentId(deploymentId)
186 | .singleResult();
187 | LOGGER.info("流程定义文件 [{}],流程ID [{}]", processDefinition.getName(), processDefinition.getId());
188 | // 启动运行流程
189 | RuntimeService runtimeService = processEngine.getRuntimeService();
190 | ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinition.getId());
191 | LOGGER.info("启动流程 [{}]", processInstance.getProcessDefinitionKey());
192 | // 处理流程任务
193 | TaskService taskService = processEngine.getTaskService();
194 | List list = taskService.createTaskQuery().list();
195 | for (Task task : list) {
196 | LOGGER.info("待处理任务 [{}]", task.getName());
197 | }
198 | LOGGER.info("待处理任务数量 [{}]", list.size());
199 | LOGGER.info("结束我们的程序");
200 | ```
201 | 5、测试代码
202 | - 运行结果:
203 | ```
204 | 启动我们的程序
205 | 流程引擎名称default,版本6.0.0.4
206 | 流程定义文件 [二级审批],流程ID [second_approve:1:4]
207 | 启动流程 [second_approve]
208 | 待处理任务 [填写审批信息]
209 | 待处理任务数量 [1]
210 | 结束我们的程序
211 | ```
212 |
213 |
214 | ### 3-10 Activiti6.0源码初探-helloword_idea-2
215 | ### 3-11 Activiti6.0源码初探-helloword_idea-3
216 |
217 | pom.xml设置
218 |
219 |
220 | - 增加parent
221 | ```xml
222 |
223 | org.springframework.boot
224 | spring-boot-starter-parent
225 | 2.0.0.RELEASE
226 |
227 |
228 | ```
229 |
230 | - 新增依赖
231 | ```xml
232 |
233 | org.springframework.boot
234 | spring-boot-starter
235 |
236 | ```
237 |
238 | - 新增plugin
239 | ```xml
240 |
241 |
242 |
243 | org.springframework.boot
244 | spring-boot-maven-plugin
245 |
246 |
247 |
248 | ```
249 |
250 | - 命令行运行
251 | ```bash
252 | mvn spring-boot:run
253 | ```
254 | - 打包
255 | ```bash
256 | mvn package
257 | ```
258 | - 打包过程
259 | ```shell
260 | $ mvn package
261 | [INFO] Scanning for projects...
262 | [INFO]
263 | [INFO] ------------------------------------------------------------------------
264 | [INFO] Building activiti6-helloworld 1.0-SNAPSHOT
265 | [INFO] ------------------------------------------------------------------------
266 | [INFO]
267 | [INFO] --- maven-resources-plugin:3.0.1:resources (default-resources) @ activiti6-helloworld ---
268 | [INFO] Using 'UTF-8' encoding to copy filtered resources.
269 | [INFO] Copying 0 resource
270 | [INFO] Copying 2 resources
271 | [INFO]
272 | [INFO] --- maven-compiler-plugin:3.7.0:compile (default-compile) @ activiti6-helloworld ---
273 | [INFO] Nothing to compile - all classes are up to date
274 | [INFO]
275 | [INFO] --- maven-resources-plugin:3.0.1:testResources (default-testResources) @activiti6-helloworld ---
276 | [INFO] Using 'UTF-8' encoding to copy filtered resources.
277 | [INFO] skip non existing resourceDirectory D:\Java\GitHub\ActivitiInAction\Chapter03\activiti6-helloworld\src\test\resources
278 | [INFO]
279 | [INFO] --- maven-compiler-plugin:3.7.0:testCompile (default-testCompile) @ activiti6-helloworld ---
280 | [INFO] Nothing to compile - all classes are up to date
281 | [INFO]
282 | [INFO] --- maven-surefire-plugin:2.16:test (default-test) @ activiti6-helloworld ---
283 | [INFO] No tests to run.
284 | [INFO]
285 | [INFO] --- maven-jar-plugin:3.0.2:jar (default-jar) @ activiti6-helloworld ---
286 | [INFO] Building jar: D:\Java\GitHub\ActivitiInAction\Chapter03\activiti6-helloworld\target\activiti6-helloworld-1.0-SNAPSHOT.jar
287 | [INFO]
288 | [INFO] --- spring-boot-maven-plugin:2.0.0.RELEASE:repackage (default) @ activiti6-helloworld ---
289 | [INFO] ------------------------------------------------------------------------
290 | [INFO] BUILD SUCCESS
291 | [INFO] ------------------------------------------------------------------------
292 | [INFO] Total time: 7.046 s
293 | [INFO] Finished at: 2019-01-11T09:32:41+08:00
294 | [INFO] Final Memory: 22M/267M
295 | [INFO] ------------------------------------------------------------------------
296 | ```
297 |
298 | - 查看打包结果
299 | ```
300 | Admin@Admin-PC MINGW64 /d/Java/GitHub/ActivitiInAction/Chapter03/activiti6-helloworld (master)
301 | $ cd target
302 |
303 | Admin@Admin-PC MINGW64 /d/Java/GitHub/ActivitiInAction/Chapter03/activiti6-helloworld/target (master)
304 | $ ll
305 | total 18988
306 | -rw-r--r-- 1 Admin 197121 19429358 一月 11 09:32 activiti6-helloworld-1.0-SNAPSHOT.jar
307 | -rw-r--r-- 1 Admin 197121 8581 一月 11 09:32 activiti6-helloworld-1.0-SNAPSHOT.jar.original
308 | drwxr-xr-x 1 Admin 197121 0 一月 11 09:03 classes
309 | drwxr-xr-x 1 Admin 197121 0 一月 10 10:35 generated-sources
310 | drwxr-xr-x 1 Admin 197121 0 一月 11 08:54 logs
311 | drwxr-xr-x 1 Admin 197121 0 一月 11 09:32 maven-archiver
312 | drwxr-xr-x 1 Admin 197121 0 一月 10 17:09 maven-status
313 |
314 | ```
315 |
316 | - 通过Java命令执行
317 | ```bath
318 | java -jar activiti6-helloworld-1.0-SNAPSHOT.jar
319 | ```
--------------------------------------------------------------------------------
/Chapter03/activiti6-helloworld/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 | 4.0.0
7 |
8 |
9 | org.springframework.boot
10 | spring-boot-starter-parent
11 | 2.0.0.RELEASE
12 |
13 |
14 |
15 | com.coderdream.activiti
16 | activiti6-helloworld
17 | 1.0-SNAPSHOT
18 |
19 | -Dfile.encoding=UTF-8
20 |
21 |
22 |
23 | org.activiti
24 | activiti-engine
25 | 6.0.0
26 |
27 |
28 | junit
29 | junit
30 | 4.12
31 | test
32 |
33 |
34 | ch.qos.logback
35 | logback-classic
36 | 1.1.11
37 |
38 |
39 | com.google.guava
40 | guava
41 | 23.0
42 |
43 |
44 | com.h2database
45 | h2
46 | 1.3.176
47 |
48 |
49 | org.springframework.boot
50 | spring-boot-starter
51 |
52 |
53 |
54 |
55 |
56 |
57 | org.springframework.boot
58 | spring-boot-maven-plugin
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/Chapter03/activiti6-helloworld/src/main/java/com/coderdream/activiti/helloworld/DemoMain.java:
--------------------------------------------------------------------------------
1 | package com.coderdream.activiti.helloworld;
2 |
3 | import com.google.common.collect.Maps;
4 | import org.activiti.engine.*;
5 | import org.activiti.engine.form.FormProperty;
6 | import org.activiti.engine.form.TaskFormData;
7 | import org.activiti.engine.impl.form.DateFormType;
8 | import org.activiti.engine.impl.form.StringFormType;
9 | import org.activiti.engine.repository.Deployment;
10 | import org.activiti.engine.repository.DeploymentBuilder;
11 | import org.activiti.engine.repository.ProcessDefinition;
12 | import org.activiti.engine.runtime.ProcessInstance;
13 | import org.activiti.engine.task.Task;
14 | import org.slf4j.Logger;
15 | import org.slf4j.LoggerFactory;
16 |
17 | import java.text.ParseException;
18 | import java.text.SimpleDateFormat;
19 | import java.util.Date;
20 | import java.util.List;
21 | import java.util.Map;
22 | import java.util.Scanner;
23 |
24 | public class DemoMain {
25 |
26 | /**
27 | * logger
28 | */
29 | private static final Logger LOGGER = LoggerFactory.getLogger(DemoMain.class);
30 |
31 | public static void main(String[] args) throws ParseException {
32 | LOGGER.info("启动我们的程序");
33 | // 创建流程引擎
34 | ProcessEngine processEngine = getProcessEngine();
35 |
36 | // 部署流程定义文件
37 | ProcessDefinition processDefinition = getProcessDefinition(processEngine);
38 |
39 | // 启动运行流程
40 | ProcessInstance processInstance = getProcessInstance(processEngine, processDefinition);
41 |
42 | // 处理流程任务
43 | processTask(processEngine, processInstance);
44 |
45 | LOGGER.info("结束我们的程序");
46 | }
47 |
48 | private static void processTask(ProcessEngine processEngine, ProcessInstance processInstance) throws ParseException {
49 | Scanner scanner = new Scanner(System.in);
50 | while (processInstance != null && !processInstance.isEnded()) {
51 | TaskService taskService = processEngine.getTaskService();
52 | List list = taskService.createTaskQuery().list();
53 | LOGGER.info("待处理任务数量 [{}]", list.size());
54 | for (Task task : list) {
55 | LOGGER.info("待处理任务 [{}]", task.getName());
56 | Map variables = getMap(processEngine, scanner, task);
57 |
58 | // 提交工作
59 | taskService.complete(task.getId(), variables);
60 | // 同步流程状态
61 | processInstance = processEngine
62 | .getRuntimeService()
63 | .createProcessInstanceQuery()
64 | .processInstanceId(processInstance.getId())
65 | .singleResult();
66 | }
67 | }
68 | scanner.close();
69 | }
70 |
71 | private static Map getMap(ProcessEngine processEngine, Scanner scanner, Task task) throws ParseException {
72 | FormService formService = processEngine.getFormService();
73 | TaskFormData taskFormData = formService.getTaskFormData(task.getId());
74 | List formProperties = taskFormData.getFormProperties();
75 | Map variables = Maps.newHashMap();
76 | for (FormProperty property : formProperties) {
77 | String line = null;
78 | if (StringFormType.class.isInstance(property.getType())) {
79 | LOGGER.info("请输入 {} ?", property.getName());
80 | line = scanner.nextLine();
81 | variables.put(property.getId(), line);
82 | } else if (DateFormType.class.isInstance(property.getType())) {
83 | LOGGER.info("请输入 {} ? 格式 (yyyy-MM-dd)", property.getName());
84 | line = scanner.nextLine();
85 | SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
86 | Date date = dateFormat.parse(line);
87 | variables.put(property.getId(), date);
88 | } else {
89 | LOGGER.info("类型暂不支持 [{}] ", property.getType());
90 | }
91 | LOGGER.info("您输入的内容是 [{}] :", line);
92 | }
93 | return variables;
94 | }
95 |
96 | private static ProcessInstance getProcessInstance(ProcessEngine processEngine, ProcessDefinition processDefinition) {
97 | RuntimeService runtimeService = processEngine.getRuntimeService();
98 | ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinition.getId());
99 | LOGGER.info("启动流程 [{}]", processInstance.getProcessDefinitionKey());
100 | return processInstance;
101 | }
102 |
103 | private static ProcessDefinition getProcessDefinition(ProcessEngine processEngine) {
104 | RepositoryService repositoryService = processEngine.getRepositoryService();
105 | DeploymentBuilder deploymentBuilder = repositoryService.createDeployment();
106 | deploymentBuilder.addClasspathResource("second_approve.bpmn");
107 | Deployment deployment = deploymentBuilder.deploy();
108 | String deploymentId = deployment.getId();
109 | ProcessDefinition processDefinition = repositoryService
110 | .createProcessDefinitionQuery()
111 | .deploymentId(deploymentId)
112 | .singleResult();
113 | LOGGER.info("流程定义文件 [{}],流程ID [{}]", processDefinition.getName(), processDefinition.getId());
114 | return processDefinition;
115 | }
116 |
117 | private static ProcessEngine getProcessEngine() {
118 | ProcessEngineConfiguration cfg = ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration();
119 | ProcessEngine processEngine = cfg.buildProcessEngine();
120 | String name = processEngine.getName();
121 | String version = ProcessEngine.VERSION;
122 | LOGGER.info("流程引擎名称{},版本{}", name, version);
123 | return processEngine;
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/Chapter03/activiti6-helloworld/src/main/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | ${plain}
12 | ${encoding}
13 |
14 |
15 |
16 |
17 |
19 | ${log.dir}/file.log
20 |
21 | ${log.dir}/file.%d{yyyy-MM-dd}.log
22 | 30
23 |
24 |
25 | ${std}
26 | ${encoding}
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/Chapter03/activiti6-helloworld/src/main/resources/second_approve.bpmn:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
--------------------------------------------------------------------------------
/Chapter03/activiti6-helloworld/src/test/java/com/coderdream/MyUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.coderdream;
2 |
3 | import org.activiti.engine.runtime.ProcessInstance;
4 | import org.activiti.engine.task.Task;
5 | import org.activiti.engine.test.ActivitiRule;
6 | import org.activiti.engine.test.Deployment;
7 | import org.junit.Rule;
8 | import org.junit.Test;
9 |
10 | import static org.junit.Assert.assertEquals;
11 | import static org.junit.Assert.assertNotNull;
12 |
13 | public class MyUnitTest {
14 |
15 | @Rule
16 | public ActivitiRule activitiRule = new ActivitiRule();
17 |
18 | @Test
19 | @Deployment(resources = {"com/coderdream/my-process.bpmn20.xml"})
20 | public void test() {
21 | ProcessInstance processInstance = activitiRule.getRuntimeService().startProcessInstanceByKey("my-process");
22 | assertNotNull(processInstance);
23 |
24 | Task task = activitiRule.getTaskService().createTaskQuery().singleResult();
25 | assertEquals("Activiti is awesome!", task.getName());
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/Chapter03/activiti6-helloworld/src/test/resources/activiti.cfg.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Chapter03/activiti6-helloworld/src/test/resources/log4j.properties:
--------------------------------------------------------------------------------
1 | log4j.rootLogger=DEBUG, CA
2 |
3 | # ConsoleAppender
4 | log4j.appender.CA=org.apache.log4j.ConsoleAppender
5 | log4j.appender.CA.layout=org.apache.log4j.PatternLayout
6 | log4j.appender.CA.layout.ConversionPattern= %d{hh:mm:ss,SSS} [%t] %-5p %c %x - %m%n
7 |
8 |
9 | log4j.logger.org.apache.ibatis.level=INFO
10 | log4j.logger.javax.activation.level=INFO
11 |
--------------------------------------------------------------------------------
/Chapter03/activiti6-helloworld/src/test/resources/my-process.bpmn20.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/Chapter03/images/0305_01_IDEA_Setting_Terminal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoderDream/ActivitiInAction/97e80418cb1be68fcb7e522530dc96a02a6f2093/Chapter03/images/0305_01_IDEA_Setting_Terminal.png
--------------------------------------------------------------------------------
/Chapter03/images/0307_01_Process.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoderDream/ActivitiInAction/97e80418cb1be68fcb7e522530dc96a02a6f2093/Chapter03/images/0307_01_Process.png
--------------------------------------------------------------------------------
/Chapter03/images/0307_02_Add_Form.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoderDream/ActivitiInAction/97e80418cb1be68fcb7e522530dc96a02a6f2093/Chapter03/images/0307_02_Add_Form.png
--------------------------------------------------------------------------------
/Chapter03/images/0307_03_Form01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoderDream/ActivitiInAction/97e80418cb1be68fcb7e522530dc96a02a6f2093/Chapter03/images/0307_03_Form01.png
--------------------------------------------------------------------------------
/Chapter03/images/0307_04_Form02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoderDream/ActivitiInAction/97e80418cb1be68fcb7e522530dc96a02a6f2093/Chapter03/images/0307_04_Form02.png
--------------------------------------------------------------------------------
/Chapter03/images/0307_05_Form03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoderDream/ActivitiInAction/97e80418cb1be68fcb7e522530dc96a02a6f2093/Chapter03/images/0307_05_Form03.png
--------------------------------------------------------------------------------
/Chapter04/Chapter0410.md:
--------------------------------------------------------------------------------
1 |
2 | ## 4-10 事件处理及监听器配置-eventlog
3 |
4 | ### 最佳实践
5 |
6 | 1. 新建配置文件activiti_eventlog.cfg.xml,设置 enableDatabaseEventLogging 为 true;
7 | 2. 新增测试类 ConfigEventLogTest,打印事件日志
8 |
9 | - 代码清单1:activiti_eventlog.cfg.xml
10 | ```xml
11 |
12 |
16 |
17 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | ```
27 |
28 | - 代码清单2:ConfigEventLogTest.java
29 | ```java
30 | @Rule
31 | public ActivitiRule activitiRule = new ActivitiRule("activiti_eventlog.cfg.xml");
32 |
33 | @Test
34 | @Deployment(resources = {"my-process.bpmn20.xml"})
35 | public void test() {
36 | ProcessInstance processInstance = activitiRule.getRuntimeService()
37 | .startProcessInstanceByKey("my-process");
38 |
39 | Task task = activitiRule.getTaskService().createTaskQuery().singleResult();
40 |
41 | // 继续执行流程
42 | activitiRule.getTaskService().complete(task.getId());
43 |
44 |
45 | List eventLogEntries = activitiRule.getManagementService()
46 | .getEventLogEntriesByProcessInstanceId(processInstance.getProcessInstanceId());
47 | for (EventLogEntry eventLogEntry : eventLogEntries) {
48 | LOGGER.info("eventLogEntry = {}, eventLog.data = {}", eventLogEntry, new String(eventLogEntry.getData()));
49 | }
50 | LOGGER.info("eventLogEntries.size = {}", eventLogEntries.size());
51 | }
52 | ```
53 |
54 | - 结果分析(12条记录):
55 | 
56 |
57 | - 完整运行结果:
58 | ```
59 | 09:56:37.045 [main] [INFO] eventLogEntry = Fri Jan 18 09:56:36 CST 2019 : PROCESSINSTANCE_START, eventLog.data = {"timeStamp":1547776596844,"processDefinitionId":"my-process:1:3","createTime":1547776596844,"id":"4"} ProcessDefinitionId= executionId= mdcProcessInstanceId= mdcBusinessKey= c.c.c.ConfigEventLogTest.test:42
60 | 09:56:37.046 [main] [INFO] eventLogEntry = Fri Jan 18 09:56:36 CST 2019 : ACTIVITY_STARTED, eventLog.data = {"timeStamp":1547776596851,"activityId":"start","processDefinitionId":"my-process:1:3","processInstanceId":"4","executionId":"5","behaviorClass":"org.activiti.engine.impl.bpmn.behavior.NoneStartEventActivityBehavior","activityType":"startEvent"} ProcessDefinitionId= executionId= mdcProcessInstanceId= mdcBusinessKey= c.c.c.ConfigEventLogTest.test:42
61 | 09:56:37.046 [main] [INFO] eventLogEntry = Fri Jan 18 09:56:36 CST 2019 : ACTIVITY_COMPLETED, eventLog.data = {"timeStamp":1547776596853,"activityId":"start","processDefinitionId":"my-process:1:3","processInstanceId":"4","executionId":"5","behaviorClass":"org.activiti.engine.impl.bpmn.behavior.NoneStartEventActivityBehavior","activityType":"startEvent"} ProcessDefinitionId= executionId= mdcProcessInstanceId= mdcBusinessKey= c.c.c.ConfigEventLogTest.test:42
62 | 09:56:37.046 [main] [INFO] eventLogEntry = Fri Jan 18 09:56:36 CST 2019 : SEQUENCEFLOW_TAKEN, eventLog.data = {"targetActivityId":"someTask","timeStamp":1547776596856,"targetActivityBehaviorClass":"org.activiti.engine.impl.bpmn.behavior.UserTaskActivityBehavior","sourceActivityType":"org.activiti.bpmn.model.StartEvent","targetActivityName":"Activiti is awesome!","id":"flow1","sourceActivityBehaviorClass":"org.activiti.engine.impl.bpmn.behavior.NoneStartEventActivityBehavior","targetActivityType":"org.activiti.bpmn.model.UserTask","sourceActivityId":"start"} ProcessDefinitionId= executionId= mdcProcessInstanceId= mdcBusinessKey= c.c.c.ConfigEventLogTest.test:42
63 | 09:56:37.046 [main] [INFO] eventLogEntry = Fri Jan 18 09:56:36 CST 2019 : ACTIVITY_STARTED, eventLog.data = {"timeStamp":1547776596858,"activityId":"someTask","processDefinitionId":"my-process:1:3","processInstanceId":"4","executionId":"5","behaviorClass":"org.activiti.engine.impl.bpmn.behavior.UserTaskActivityBehavior","activityName":"Activiti is awesome!","activityType":"userTask"} ProcessDefinitionId= executionId= mdcProcessInstanceId= mdcBusinessKey= c.c.c.ConfigEventLogTest.test:42
64 | 09:56:37.046 [main] [INFO] eventLogEntry = Fri Jan 18 09:56:36 CST 2019 : TASK_CREATED, eventLog.data = {"timeStamp":1547776596873,"taskDefinitionKey":"someTask","processDefinitionId":"my-process:1:3","processInstanceId":"4","executionId":"5","createTime":1547776596858,"name":"Activiti is awesome!","id":"8","priority":50} ProcessDefinitionId= executionId= mdcProcessInstanceId= mdcBusinessKey= c.c.c.ConfigEventLogTest.test:42
65 | 09:56:37.047 [main] [INFO] eventLogEntry = Fri Jan 18 09:56:36 CST 2019 : TASK_COMPLETED, eventLog.data = {"duration":141,"timeStamp":1547776596999,"taskDefinitionKey":"someTask","processDefinitionId":"my-process:1:3","processInstanceId":"4","executionId":"5","createTime":1547776596858,"name":"Activiti is awesome!","id":"8","priority":50} ProcessDefinitionId= executionId= mdcProcessInstanceId= mdcBusinessKey= c.c.c.ConfigEventLogTest.test:42
66 | 09:56:37.047 [main] [INFO] eventLogEntry = Fri Jan 18 09:56:37 CST 2019 : ACTIVITY_COMPLETED, eventLog.data = {"timeStamp":1547776597011,"activityId":"someTask","processDefinitionId":"my-process:1:3","processInstanceId":"4","executionId":"5","behaviorClass":"org.activiti.engine.impl.bpmn.behavior.UserTaskActivityBehavior","activityName":"Activiti is awesome!","activityType":"userTask"} ProcessDefinitionId= executionId= mdcProcessInstanceId= mdcBusinessKey= c.c.c.ConfigEventLogTest.test:42
67 | 09:56:37.047 [main] [INFO] eventLogEntry = Fri Jan 18 09:56:37 CST 2019 : SEQUENCEFLOW_TAKEN, eventLog.data = {"targetActivityId":"end","timeStamp":1547776597012,"sourceActivityName":"Activiti is awesome!","targetActivityBehaviorClass":"org.activiti.engine.impl.bpmn.behavior.NoneEndEventActivityBehavior","sourceActivityType":"org.activiti.bpmn.model.UserTask","id":"flow2","sourceActivityBehaviorClass":"org.activiti.engine.impl.bpmn.behavior.UserTaskActivityBehavior","targetActivityType":"org.activiti.bpmn.model.EndEvent","sourceActivityId":"someTask"} ProcessDefinitionId= executionId= mdcProcessInstanceId= mdcBusinessKey= c.c.c.ConfigEventLogTest.test:42
68 | 09:56:37.048 [main] [INFO] eventLogEntry = Fri Jan 18 09:56:37 CST 2019 : ACTIVITY_STARTED, eventLog.data = {"timeStamp":1547776597013,"activityId":"end","processDefinitionId":"my-process:1:3","processInstanceId":"4","executionId":"5","behaviorClass":"org.activiti.engine.impl.bpmn.behavior.NoneEndEventActivityBehavior","activityType":"endEvent"} ProcessDefinitionId= executionId= mdcProcessInstanceId= mdcBusinessKey= c.c.c.ConfigEventLogTest.test:42
69 | 09:56:37.048 [main] [INFO] eventLogEntry = Fri Jan 18 09:56:37 CST 2019 : ACTIVITY_COMPLETED, eventLog.data = {"timeStamp":1547776597013,"activityId":"end","processDefinitionId":"my-process:1:3","processInstanceId":"4","executionId":"5","behaviorClass":"org.activiti.engine.impl.bpmn.behavior.NoneEndEventActivityBehavior","activityType":"endEvent"} ProcessDefinitionId= executionId= mdcProcessInstanceId= mdcBusinessKey= c.c.c.ConfigEventLogTest.test:42
70 | 09:56:37.048 [main] [INFO] eventLogEntry = Fri Jan 18 09:56:37 CST 2019 : PROCESSINSTANCE_END, eventLog.data = {"timeStamp":1547776597028,"processDefinitionId":"my-process:1:3","id":"4","endTime":1547776597028} ProcessDefinitionId= executionId= mdcProcessInstanceId= mdcBusinessKey= c.c.c.ConfigEventLogTest.test:42
71 | 09:56:37.048 [main] [INFO] eventLogEntries.size = 12 ProcessDefinitionId= executionId= mdcProcessInstanceId= mdcBusinessKey= c.c.c.ConfigEventLogTest.test:44
72 |
73 | Process finished with exit code 0
74 | ```
75 |
76 | ### 代码分析
77 |
78 | 1. 在配置文件中设置的值,会在 ProcessEngineConfigurationImpl 的 setEnableDatabaseEventLogging 方法中生效:
79 | 
80 |
81 | 2. 如果设置为true,则在 initDatabaseEventLogging 方法中会新建一个 EventLogger 对象:
82 | 
83 |
84 | 3. EventLogger 的初始化动作:
85 | 
86 |
87 | 4. EventLogger 会新增 EventFlusher(DatabaseEventFlusher) 对象到 Close 监听器:
88 | 
89 |
90 | 5. 在 DatabaseEventFlusher 的 close 方法中将记录插入数据库:
91 | 
92 |
--------------------------------------------------------------------------------
/Chapter04/Chapter0412.md:
--------------------------------------------------------------------------------
1 |
2 | ## 4-12 事件处理及监听器配置-eventLinstener
3 |
4 |
5 | ###
6 |
7 | - 主要内容
8 | 
9 | - 事件及监听器原理
10 | 
11 | - 监听器配置方式
12 | 
13 | - Activiti事件监听
14 | 
15 | - 相关API
16 | 
17 |
18 | ## 最佳实践
19 |
20 | 1. 新建流程事件监听器 ProcessEventListener 和自定义事件监听器 CustomEventListener
21 | 2. 新建配置文件 activiti_eventListener.cfg.xml,设置监听类;
22 | 3. 新增测试类 ConfigEventListenerTest,查看执行结果
23 |
24 | ### 情形一:配置监听类
25 |
26 | - 代码清单1:activiti_eventListener.cfg.xml
27 | ```xml
28 |
29 |
33 |
34 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | ```
48 |
49 | - 代码清单2:ConfigEventListenerTest.java
50 | ```java
51 | public class ConfigEventListenerTest {
52 |
53 | /** logger */
54 | private static final Logger LOGGER = LoggerFactory.getLogger(ConfigEventListenerTest.class);
55 |
56 | @Rule
57 | public ActivitiRule activitiRule = new ActivitiRule("activiti_eventListener.cfg.xml");
58 |
59 | @Test
60 | @Deployment(resources = {"my-process.bpmn20.xml"})
61 | public void test() {
62 | ProcessInstance processInstance = activitiRule.getRuntimeService()
63 | .startProcessInstanceByKey("my-process");
64 | Task task = activitiRule.getTaskService().createTaskQuery().singleResult();
65 | // 继续执行流程
66 | activitiRule.getTaskService().complete(task.getId());
67 | }
68 |
69 | }
70 | ```
71 |
72 | - 运行结果:
73 | ```
74 | 14:26:36.770 [main] [INFO] 流程启动 PROCESS_STARTED 4 ProcessDefinitionId= executionId= mdcProcessInstanceId= mdcBusinessKey= c.c.e.ProcessEventListener.onEvent:19
75 | 14:26:36.966 [main] [INFO] 流程结束 PROCESS_COMPLETED 4 ProcessDefinitionId= executionId= mdcProcessInstanceId= mdcBusinessKey= c.c.e.ProcessEventListener.onEvent:21
76 | ```
77 |
78 | ### 情形二:配置特定监听类型
79 |
80 | ```xml
81 |
82 |
83 |
90 |
91 | ```
92 |
93 | - 运行结果:
94 | ```
95 | 14:29:41.461 [main] [INFO] ProcessEngine default created ProcessDefinitionId= executionId= mdcProcessInstanceId= mdcBusinessKey= o.a.e.i.ProcessEngineImpl.:87
96 | 14:29:41.661 [main] [INFO] 流程启动 PROCESS_STARTED 4 ProcessDefinitionId= executionId= mdcProcessInstanceId= mdcBusinessKey= c.c.e.ProcessEventListener.onEvent:19
97 |
98 | ```
99 | ### 情形三:配置自定义监听
100 |
101 | ```xml
102 |
103 |
104 |
105 |
106 |
107 |
108 | ```
109 |
110 | - 运行结果
111 | ```
112 | 14:35:17.609 [main] [INFO] ProcessEngine default created ProcessDefinitionId= executionId= mdcProcessInstanceId= mdcBusinessKey= o.a.e.i.ProcessEngineImpl.:87
113 | 14:35:17.928 [main] [INFO] 监听到自定义事件 CUSTOM null ProcessDefinitionId= executionId= mdcProcessInstanceId= mdcBusinessKey= c.c.e.CustomEventListener.onEvent:19
114 |
115 | Process finished with exit code 0
116 | ```
117 |
118 | ### 情形四:在源代码中配置自定义监听
119 |
120 | - 代码清单:
121 | ```java
122 | @Test
123 | @Deployment(resources = {"my-process.bpmn20.xml"})
124 | public void test() {
125 | ProcessInstance processInstance = activitiRule.getRuntimeService()
126 | .startProcessInstanceByKey("my-process");
127 | Task task = activitiRule.getTaskService().createTaskQuery().singleResult();
128 | // 继续执行流程
129 | activitiRule.getTaskService().complete(task.getId());
130 | // 通过代码添加监听器(非配置文件方式)
131 | activitiRule.getRuntimeService().addEventListener(new CustomEventListener());
132 | // 添加一个自定义事件
133 | activitiRule.getRuntimeService().dispatchEvent(new ActivitiEventImpl(ActivitiEventType.CUSTOM));
134 | }
135 | ```
136 |
137 | - 运行结果
138 | ```
139 | 14:35:17.609 [main] [INFO] ProcessEngine default created ProcessDefinitionId= executionId= mdcProcessInstanceId= mdcBusinessKey= o.a.e.i.ProcessEngineImpl.:87
140 | 14:35:17.928 [main] [INFO] 监听到自定义事件 CUSTOM null ProcessDefinitionId= executionId= mdcProcessInstanceId= mdcBusinessKey= c.c.e.CustomEventListener.onEvent:19
141 |
142 | Process finished with exit code 0
143 | ```
144 |
145 | ### 代码分析
146 |
147 | 1. ActivitiEventListener 继承关系:
148 | 
149 |
150 | 2. BaseEntityEventListener:
151 | 
152 |
153 | 3. ActivitiEvent:
154 | 
155 |
156 | 4. ActivitiEntityEvent:
157 | 
158 |
159 | 5. ActivitiVariableEvent:
160 | 
161 |
--------------------------------------------------------------------------------
/Chapter04/README.md:
--------------------------------------------------------------------------------
1 |
2 | ## 第4章 Activiti6.0引擎配置
3 | ### 4-1 本章概述
4 | ### 4-2 创建流程引擎配置-config_samples
5 |
6 | 1. 新建Maven空项目activiti-samples
7 | 2. 给项目新增Module,名称为config
8 | 3. 新增自定义脚手架
9 | 
10 | 4. 根据脚手架创建模块
11 | 
12 | 5. 新建测试文件,路径 activiti6-samples\config\src\test\java\com\coderdream\config,名称 ConfigTest.java:
13 | 
14 | - 代码清单:ConfigTest.java
15 | ```java
16 | @Test
17 | public void testConfig1() {
18 | ProcessEngineConfiguration configuration = ProcessEngineConfiguration
19 | .createProcessEngineConfigurationFromResourceDefault();
20 |
21 | LOGGER.info("configuration = {}", configuration);
22 | }
23 |
24 | @Test
25 | public void testConfig2() {
26 | ProcessEngineConfiguration configuration = ProcessEngineConfiguration
27 | .createStandaloneProcessEngineConfiguration();
28 |
29 | LOGGER.info("configuration = {}", configuration);
30 | }
31 | ```
32 |
33 | - 输出结果:
34 | ```
35 | configuration = org.activiti.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration@2beee7ff
36 | configuration = org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration@366647c2
37 | ```
38 | - 流程引擎配置的继承关系
39 | 
40 |
41 | ### 4-3 创建流程引擎配置-archetype
42 | ### 4-4 数据库配置-dbconfig
43 | ### 4-5 数据库配置-dbconfig_code
44 |
45 | ```java
46 | @Test
47 | public void testConfig1() {
48 | ProcessEngineConfiguration configuration = ProcessEngineConfiguration
49 | .createProcessEngineConfigurationFromResourceDefault();
50 |
51 | LOGGER.info("configuration = {}", configuration);
52 | ProcessEngine processEngine = configuration.buildProcessEngine();
53 | LOGGER.info("获取流程引擎 {}", processEngine.getName());
54 | processEngine.close();
55 | }
56 | ```
57 |
58 |
59 | ```
60 | Loading XML bean definitions from class path resource [activiti.cfg.xml]
61 | configuration = org.activiti.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration@6a6afff2
62 | Activiti 5 compatibility handler implementation not found or error during instantiation : org.activiti.compatibility.DefaultActiviti5CompatibilityHandler. Activiti 5 backwards compatibility disabled.
63 | performing create on engine with resource org/activiti/db/create/activiti.h2.create.engine.sql
64 | performing create on history with resource org/activiti/db/create/activiti.h2.create.history.sql
65 | performing create on identity with resource org/activiti/db/create/activiti.h2.create.identity.sql
66 | ProcessEngine default created
67 | 获取流程引擎 default
68 | performing drop on engine with resource org/activiti/db/drop/activiti.h2.drop.engine.sql
69 | performing drop on history with resource org/activiti/db/drop/activiti.h2.drop.history.sql
70 | performing drop on identity with resource org/activiti/db/drop/activiti.h2.drop.identity.sql
71 |
72 | Process finished with exit code 0
73 | ```
74 |
75 |
76 | ### 4-6 日志记录配置-logging
77 |
78 | 
79 |
80 | 
81 |
82 | 
83 |
84 | 
85 |
86 | 
87 |
88 | 
89 |
90 | ### 4-7 日志记录配置-logging_mdc
91 |
92 | 步骤:
93 | 1. 创建代理;
94 | 2. 修改流程文件;
95 | 3. 修改logback文件
96 | 3. 打开MDC
97 |
98 |
99 | - 代码清单:MDCErrorDelegate.java
100 | ```java
101 | public class MDCErrorDelegate implements JavaDelegate {
102 |
103 | /** logger */
104 | private static final Logger LOGGER = LoggerFactory.getLogger(MDCErrorDelegate.class);
105 |
106 | @Override
107 | public void execute(DelegateExecution execution) {
108 | LOGGER.info("run MDCErrorDelegate");
109 | throw new RuntimeException("only test");
110 | }
111 | }
112 |
113 | ```
114 | - 代码清单:my-process.bpmn20.xml
115 | ```xml
116 |
117 |
118 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 | ```
140 |
141 | - 代码清单(片段):logback.xml
142 | ```xml
143 |
150 |
156 |
157 |
158 |
159 |
160 | ${mdc}
161 | ${encoding}
162 |
163 |
164 | ```
165 |
166 |
167 | - 代码清单:ConfigMDCTest.java
168 | ```java
169 | public class ConfigMDCTest {
170 |
171 | /** logger */
172 | private static final Logger LOGGER = LoggerFactory.getLogger(ConfigMDCTest.class);
173 |
174 | @Rule
175 | public ActivitiRule activitiRule = new ActivitiRule();
176 |
177 | @Test
178 | @Deployment(resources = {"my-process.bpmn20.xml"})
179 | public void test() {
180 | // 打开MDC开关
181 | LogMDC.setMDCEnabled(true);
182 | ProcessInstance processInstance = activitiRule.getRuntimeService()
183 | .startProcessInstanceByKey("my-process");
184 | assertNotNull(processInstance);
185 |
186 | Task task = activitiRule.getTaskService().createTaskQuery().singleResult();
187 | assertEquals("Activiti is awesome!", task.getName());
188 |
189 | // 继续执行流程
190 | activitiRule.getTaskService().complete(task.getId());
191 | }
192 |
193 | }
194 | ```
195 |
196 | - 执行结果
197 | ```
198 | 15:32:05.953 [main] [ERROR] Error while closing command context ProcessDefinitionId=my-process:1:3
199 | executionId=5 mdcProcessInstanceId= mdcBusinessKey= o.a.e.i.i.CommandContext.logException:122
200 | java.lang.RuntimeException: only test
201 | at com.coderdream.delegate.MDCErrorDelegate.execute(MDCErrorDelegate.java:16)
202 | ```
203 |
204 | **拦截器方式**
205 |
206 | 1. 新增拦截器
207 | 2. 新增配置文件
208 | 3. 新增测试方法及相关配置
209 |
210 | - 代码清单1:MDCCommandInvoker.java
211 | ```java
212 | public class MDCCommandInvoker extends DebugCommandInvoker {
213 |
214 | // 参考DebugCommandInvoker代码
215 | @Override
216 | public void executeOperation(Runnable runnable) {
217 | // 保存默认状态
218 | boolean mdcEnabled = LogMDC.isMDCEnabled();
219 | // 修改状态
220 | LogMDC.setMDCEnabled(true);
221 | if (runnable instanceof AbstractOperation) {
222 | AbstractOperation operation = (AbstractOperation) runnable;
223 |
224 | if (operation.getExecution() != null) {
225 | // 记录日志
226 | LogMDC.putMDCExecution(operation.getExecution());
227 | }
228 |
229 | }
230 |
231 | super.executeOperation(runnable);
232 | // 清理上下文信息
233 | LogMDC.clear();
234 | // 还原为默认状态
235 | if (!mdcEnabled) {
236 | LogMDC.setMDCEnabled(false);
237 | }
238 | }
239 | }
240 | ```
241 |
242 | - 代码清单2:activiti_mdc.cfg.xml
243 | ```xml
244 |
245 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 | ```
259 |
260 | - 代码清单3:my-process_mdcerror.bpmn20.xml
261 | ```xml
262 |
263 |
264 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 | ```
285 |
286 | - 代码清单4:ConfigMDCTest.java
287 | ```java
288 | @Rule
289 | public ActivitiRule activitiRule = new ActivitiRule("activiti_mdc.cfg.xml");
290 |
291 | @Test
292 | @Deployment(resources = {"my-process_mdcerror.bpmn20.xml"})
293 | public void test2() {
294 | ProcessInstance processInstance = activitiRule.getRuntimeService()
295 | .startProcessInstanceByKey("my-process");
296 | assertNotNull(processInstance);
297 |
298 | Task task = activitiRule.getTaskService().createTaskQuery().singleResult();
299 | assertEquals("Activiti is awesome!", task.getName());
300 |
301 | // 继续执行流程
302 | activitiRule.getTaskService().complete(task.getId());
303 | }
304 | ```
305 |
306 |
307 | - 运行结果
308 | ```
309 | 15:54:38.046 [main] [INFO] performing create on engine with resource org/activiti/db/create/activiti.h2.create.engine.sql
310 | ProcessDefinitionId= executionId= mdcProcessInstanceId= mdcBusinessKey= o.a.e.i.d.DbSqlSession.executeSchemaResource:1147
311 | 15:54:38.100 [main] [INFO] performing create on history with resource org/activiti/db/create/activiti.h2.create.history.sql
312 | ProcessDefinitionId= executionId= mdcProcessInstanceId= mdcBusinessKey= o.a.e.i.d.DbSqlSession.executeSchemaResource:1147
313 | 15:54:38.104 [main] [INFO] performing create on identity with resource org/activiti/db/create/activiti.h2.create.identity.sql
314 | ProcessDefinitionId= executionId= mdcProcessInstanceId= mdcBusinessKey= o.a.e.i.d.DbSqlSession.executeSchemaResource:1147
315 | 15:54:38.108 [main] [INFO] ProcessEngine default created ProcessDefinitionId=
316 | executionId= mdcProcessInstanceId= mdcBusinessKey= o.a.e.i.ProcessEngineImpl.:87
317 | 15:54:38.303 [main] [INFO] Execution tree while executing operation class org.activiti.engine.impl.agenda.ContinueProcessOperation :
318 | ProcessDefinitionId=my-process:1:3 executionId=5 mdcProcessInstanceId= mdcBusinessKey= o.a.e.i.i.DebugCommandInvoker.executeOperation:33
319 | 15:54:38.307 [main] [INFO]
320 | 4 (process instance)
321 | └── 5 : start (StartEvent, parent id 4 (active)
322 | ProcessDefinitionId=my-process:1:3 executionId=5 mdcProcessInstanceId= mdcBusinessKey= o.a.e.i.i.DebugCommandInvoker.executeOperation:34
323 | 15:54:38.310 [main] [INFO] Execution tree while executing operation class org.activiti.engine.impl.agenda.TakeOutgoingSequenceFlowsOperation :
324 | ProcessDefinitionId=my-process:1:3 executionId=5 mdcProcessInstanceId= mdcBusinessKey= o.a.e.i.i.DebugCommandInvoker.executeOperation:33
325 | 15:54:38.311 [main] [INFO]
326 | 4 (process instance)
327 | └── 5 : start (StartEvent, parent id 4 (active)
328 | ProcessDefinitionId=my-process:1:3 executionId=5 mdcProcessInstanceId= mdcBusinessKey= o.a.e.i.i.DebugCommandInvoker.executeOperation:34
329 | 15:54:38.312 [main] [INFO] Execution tree while executing operation class org.activiti.engine.impl.agenda.ContinueProcessOperation :
330 | ProcessDefinitionId=my-process:1:3 executionId=5 mdcProcessInstanceId= mdcBusinessKey= o.a.e.i.i.DebugCommandInvoker.executeOperation:33
331 | 15:54:38.312 [main] [INFO]
332 | 4 (process instance)
333 | └── 5 : start -> someTask, parent id 4 (active)
334 | ProcessDefinitionId=my-process:1:3 executionId=5 mdcProcessInstanceId= mdcBusinessKey= o.a.e.i.i.DebugCommandInvoker.executeOperation:34
335 | 15:54:38.313 [main] [INFO] Execution tree while executing operation class org.activiti.engine.impl.agenda.ContinueProcessOperation :
336 | ProcessDefinitionId=my-process:1:3 executionId=5 mdcProcessInstanceId= mdcBusinessKey= o.a.e.i.i.DebugCommandInvoker.executeOperation:33
337 | 15:54:38.313 [main] [INFO]
338 | 4 (process instance)
339 | └── 5 : someTask (UserTask, parent id 4 (active)
340 | ProcessDefinitionId=my-process:1:3 executionId=5 mdcProcessInstanceId= mdcBusinessKey= o.a.e.i.i.DebugCommandInvoker.executeOperation:34
341 | 15:54:38.389 [main] [INFO] Execution tree while executing operation class org.activiti.engine.impl.agenda.TriggerExecutionOperation :
342 | ProcessDefinitionId=my-process:1:3 executionId=5 mdcProcessInstanceId= mdcBusinessKey= o.a.e.i.i.DebugCommandInvoker.executeOperation:33
343 | 15:54:38.391 [main] [INFO]
344 | 4 (process instance)
345 | └── 5 : someTask (UserTask, parent id 4 (active)
346 | ProcessDefinitionId=my-process:1:3 executionId=5 mdcProcessInstanceId= mdcBusinessKey= o.a.e.i.i.DebugCommandInvoker.executeOperation:34
347 | 15:54:38.392 [main] [INFO] Execution tree while executing operation class org.activiti.engine.impl.agenda.TakeOutgoingSequenceFlowsOperation :
348 | ProcessDefinitionId=my-process:1:3 executionId=5 mdcProcessInstanceId= mdcBusinessKey= o.a.e.i.i.DebugCommandInvoker.executeOperation:33
349 | 15:54:38.392 [main] [INFO]
350 | 4 (process instance)
351 | └── 5 : someTask (UserTask, parent id 4 (active)
352 | ProcessDefinitionId=my-process:1:3 executionId=5 mdcProcessInstanceId= mdcBusinessKey= o.a.e.i.i.DebugCommandInvoker.executeOperation:34
353 | 15:54:38.393 [main] [INFO] Execution tree while executing operation class org.activiti.engine.impl.agenda.ContinueProcessOperation :
354 | ProcessDefinitionId=my-process:1:3 executionId=5 mdcProcessInstanceId= mdcBusinessKey= o.a.e.i.i.DebugCommandInvoker.executeOperation:33
355 | 15:54:38.394 [main] [INFO]
356 | 4 (process instance)
357 | └── 5 : someTask -> end, parent id 4 (active)
358 | ProcessDefinitionId=my-process:1:3 executionId=5 mdcProcessInstanceId= mdcBusinessKey= o.a.e.i.i.DebugCommandInvoker.executeOperation:34
359 | 15:54:38.394 [main] [INFO] Execution tree while executing operation class org.activiti.engine.impl.agenda.ContinueProcessOperation :
360 | ProcessDefinitionId=my-process:1:3 executionId=5 mdcProcessInstanceId= mdcBusinessKey= o.a.e.i.i.DebugCommandInvoker.executeOperation:33
361 | 15:54:38.394 [main] [INFO]
362 | 4 (process instance)
363 | └── 5 : end (EndEvent, parent id 4 (active)
364 | ProcessDefinitionId=my-process:1:3 executionId=5 mdcProcessInstanceId= mdcBusinessKey= o.a.e.i.i.DebugCommandInvoker.executeOperation:34
365 | 15:54:38.394 [main] [INFO] Execution tree while executing operation class org.activiti.engine.impl.agenda.TakeOutgoingSequenceFlowsOperation :
366 | ProcessDefinitionId=my-process:1:3 executionId=5 mdcProcessInstanceId= mdcBusinessKey= o.a.e.i.i.DebugCommandInvoker.executeOperation:33
367 | 15:54:38.395 [main] [INFO]
368 | 4 (process instance)
369 | └── 5 : end (EndEvent, parent id 4 (active)
370 | ProcessDefinitionId=my-process:1:3 executionId=5 mdcProcessInstanceId= mdcBusinessKey= o.a.e.i.i.DebugCommandInvoker.executeOperation:34
371 | 15:54:38.396 [main] [INFO] Execution tree while executing operation class org.activiti.engine.impl.agenda.EndExecutionOperation :
372 | ProcessDefinitionId=my-process:1:3 executionId=5 mdcProcessInstanceId= mdcBusinessKey= o.a.e.i.i.DebugCommandInvoker.executeOperation:33
373 | 15:54:38.396 [main] [INFO]
374 | 4 (process instance)
375 | └── 5 : end (EndEvent, parent id 4 (active)
376 | ProcessDefinitionId=my-process:1:3 executionId=5 mdcProcessInstanceId= mdcBusinessKey= o.a.e.i.i.DebugCommandInvoker.executeOperation:34
377 |
378 | Process finished with exit code 0
379 |
380 | ```
381 |
382 |
383 | ### 4-8 历史记录配置-history-1
384 | ### 4-9 历史记录配置-history-2
385 | ### 4-10 事件处理及监听器配置-eventlog
386 | ### 4-11 事件处理及监听器配置-eventLinstener-1
387 | ### 4-12 事件处理及监听器配置-eventLinstener-2
388 | ### 4-13 命令拦截器配置-command-1
389 | ### 4-14 命令拦截器配置-command-2
390 | ### 4-15 作业执行器配置-job-1
391 | ### 4-16 作业执行器配置-job-2
392 | ### 4-17 Activiti与spring集成-1
393 | ### 4-18 Activiti与spring集成-2
394 | ### 4-19 Activiti与spring集成-3
395 |
396 | ## 参考网站:
397 |
398 | 1. [fhqscfss/activiti-test](https://github.com/fhqscfss/activiti-test)
399 | 2. [chandler1142/activiti-study](https://github.com/chandler1142/activiti-study)
400 | 3. [shengjie8329/activiti-helloword](https://github.com/shengjie8329/activiti-helloword)
401 | 4. [DestinyWang/activiti-sample](https://github.com/DestinyWang/activiti-sample)
--------------------------------------------------------------------------------
/Chapter04/activiti-archetype-unittest2/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | org.activiti
5 | activiti-archetype-unittest2
6 | 6.0.0
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Chapter04/activiti-archetype-unittest2/src/main/resources/META-INF/maven/archetype-metadata.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | src/main/java
7 |
8 | **/*.java
9 |
10 |
11 |
12 | src/main/resources
13 |
14 | activiti.cfg.xml
15 | logback.xml
16 | second_approve.bpmn
17 |
18 |
19 |
20 | src/test/java
21 |
22 | **/*.java
23 |
24 |
25 |
26 | src/test/resources
27 |
28 | activiti.cfg.xml
29 | log4j.properties
30 | my-process.bpmn20.xml
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/Chapter04/activiti-archetype-unittest2/src/main/resources/archetype-resources/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | ${groupId}
5 | ${artifactId}
6 | ${version}
7 | jar
8 | ${artifactId}
9 |
10 |
11 | org.activiti
12 | activiti-engine
13 | 6.0.0
14 |
15 |
16 | junit
17 | junit
18 | 4.12
19 | test
20 |
21 |
22 | ch.qos.logback
23 | logback-classic
24 | 1.1.11
25 |
26 |
27 | com.google.guava
28 | guava
29 | 23.0
30 |
31 |
32 | com.h2database
33 | h2
34 | 1.3.176
35 |
36 |
37 |
38 |
39 |
40 |
41 | org.apache.maven.plugins
42 | maven-compiler-plugin
43 | 3.6.1
44 |
45 | 1.8
46 | 1.8
47 |
48 |
49 |
50 | org.apache.maven.plugins
51 | maven-resources-plugin
52 | 2.6
53 |
54 | UTF-8
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/Chapter04/activiti-archetype-unittest2/src/main/resources/archetype-resources/src/main/java/DemoMain.java:
--------------------------------------------------------------------------------
1 | package ${package};
2 |
3 | import com.google.common.collect.Maps;
4 | import org.activiti.engine.*;
5 | import org.activiti.engine.form.FormProperty;
6 | import org.activiti.engine.form.TaskFormData;
7 | import org.activiti.engine.impl.form.DateFormType;
8 | import org.activiti.engine.impl.form.StringFormType;
9 | import org.activiti.engine.repository.Deployment;
10 | import org.activiti.engine.repository.DeploymentBuilder;
11 | import org.activiti.engine.repository.ProcessDefinition;
12 | import org.activiti.engine.runtime.ProcessInstance;
13 | import org.activiti.engine.task.Task;
14 | import org.slf4j.Logger;
15 | import org.slf4j.LoggerFactory;
16 |
17 | import java.text.ParseException;
18 | import java.text.SimpleDateFormat;
19 | import java.util.Date;
20 | import java.util.List;
21 | import java.util.Map;
22 | import java.util.Scanner;
23 |
24 | public class DemoMain {
25 |
26 | /**
27 | * logger
28 | */
29 | private static final Logger LOGGER = LoggerFactory.getLogger(DemoMain.class);
30 |
31 | public static void main(String[] args) throws ParseException {
32 | LOGGER.info("启动我们的程序");
33 | // 创建流程引擎
34 | ProcessEngine processEngine = getProcessEngine();
35 |
36 | // 部署流程定义文件
37 | ProcessDefinition processDefinition = getProcessDefinition(processEngine);
38 |
39 | // 启动运行流程
40 | ProcessInstance processInstance = getProcessInstance(processEngine, processDefinition);
41 |
42 | // 处理流程任务
43 | processTask(processEngine, processInstance);
44 |
45 | LOGGER.info("结束我们的程序");
46 | }
47 |
48 | private static void processTask(ProcessEngine processEngine, ProcessInstance processInstance) throws ParseException {
49 | Scanner scanner = new Scanner(System.in);
50 | while (processInstance != null && !processInstance.isEnded()) {
51 | TaskService taskService = processEngine.getTaskService();
52 | List list = taskService.createTaskQuery().list();
53 | LOGGER.info("待处理任务数量 [{}]", list.size());
54 | for (Task task : list) {
55 | LOGGER.info("待处理任务 [{}]", task.getName());
56 | Map variables = getMap(processEngine, scanner, task);
57 |
58 | // 提交工作
59 | taskService.complete(task.getId(), variables);
60 | // 同步流程状态
61 | processInstance = processEngine
62 | .getRuntimeService()
63 | .createProcessInstanceQuery()
64 | .processInstanceId(processInstance.getId())
65 | .singleResult();
66 | }
67 | }
68 | scanner.close();
69 | }
70 |
71 | private static Map getMap(ProcessEngine processEngine, Scanner scanner, Task task) throws ParseException {
72 | FormService formService = processEngine.getFormService();
73 | TaskFormData taskFormData = formService.getTaskFormData(task.getId());
74 | List formProperties = taskFormData.getFormProperties();
75 | Map variables = Maps.newHashMap();
76 | for (FormProperty property : formProperties) {
77 | String line = null;
78 | if (StringFormType.class.isInstance(property.getType())) {
79 | LOGGER.info("请输入 {} ?", property.getName());
80 | line = scanner.nextLine();
81 | variables.put(property.getId(), line);
82 | } else if (DateFormType.class.isInstance(property.getType())) {
83 | LOGGER.info("请输入 {} ? 格式 (yyyy-MM-dd)", property.getName());
84 | line = scanner.nextLine();
85 | SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
86 | Date date = dateFormat.parse(line);
87 | variables.put(property.getId(), date);
88 | } else {
89 | LOGGER.info("类型暂不支持 [{}] ", property.getType());
90 | }
91 | LOGGER.info("您输入的内容是 [{}] :", line);
92 | }
93 | return variables;
94 | }
95 |
96 | private static ProcessInstance getProcessInstance(ProcessEngine processEngine, ProcessDefinition processDefinition) {
97 | RuntimeService runtimeService = processEngine.getRuntimeService();
98 | ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinition.getId());
99 | LOGGER.info("启动流程 [{}]", processInstance.getProcessDefinitionKey());
100 | return processInstance;
101 | }
102 |
103 | private static ProcessDefinition getProcessDefinition(ProcessEngine processEngine) {
104 | RepositoryService repositoryService = processEngine.getRepositoryService();
105 | DeploymentBuilder deploymentBuilder = repositoryService.createDeployment();
106 | deploymentBuilder.addClasspathResource("second_approve.bpmn");
107 | Deployment deployment = deploymentBuilder.deploy();
108 | String deploymentId = deployment.getId();
109 | ProcessDefinition processDefinition = repositoryService
110 | .createProcessDefinitionQuery()
111 | .deploymentId(deploymentId)
112 | .singleResult();
113 | LOGGER.info("流程定义文件 [{}],流程ID [{}]", processDefinition.getName(), processDefinition.getId());
114 | return processDefinition;
115 | }
116 |
117 | private static ProcessEngine getProcessEngine() {
118 | ProcessEngineConfiguration cfg = ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration();
119 | ProcessEngine processEngine = cfg.buildProcessEngine();
120 | String name = processEngine.getName();
121 | String version = ProcessEngine.VERSION;
122 | LOGGER.info("流程引擎名称{},版本{}", name, version);
123 | return processEngine;
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/Chapter04/activiti-archetype-unittest2/src/main/resources/archetype-resources/src/main/resources/activiti.cfg.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Chapter04/activiti-archetype-unittest2/src/main/resources/archetype-resources/src/main/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | ${plain}
12 | ${encoding}
13 |
14 |
15 |
16 |
17 |
19 | ${log.dir}/file.log
20 |
21 | ${log.dir}/file.%d{yyyy-MM-dd}.log
22 | 30
23 |
24 |
25 | ${std}
26 | ${encoding}
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/Chapter04/activiti-archetype-unittest2/src/main/resources/archetype-resources/src/main/resources/second_approve.bpmn:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
--------------------------------------------------------------------------------
/Chapter04/activiti-archetype-unittest2/src/main/resources/archetype-resources/src/test/java/MyUnitTest.java:
--------------------------------------------------------------------------------
1 | package ${package};
2 | import org.activiti.engine.runtime.ProcessInstance;
3 | import org.activiti.engine.task.Task;
4 | import org.activiti.engine.test.ActivitiRule;
5 | import org.activiti.engine.test.Deployment;
6 | import org.junit.Rule;
7 | import org.junit.Test;
8 |
9 | import static org.junit.Assert.*;
10 |
11 | public class MyUnitTest {
12 |
13 | @Rule
14 | public ActivitiRule activitiRule = new ActivitiRule();
15 |
16 | @Test
17 | @Deployment(resources = {"my-process.bpmn20.xml"})
18 | public void test() {
19 | ProcessInstance processInstance = activitiRule.getRuntimeService().startProcessInstanceByKey("my-process");
20 | assertNotNull(processInstance);
21 |
22 | Task task = activitiRule.getTaskService().createTaskQuery().singleResult();
23 | assertEquals("Activiti is awesome!", task.getName());
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/Chapter04/activiti-archetype-unittest2/src/main/resources/archetype-resources/src/test/resources/activiti.cfg.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Chapter04/activiti-archetype-unittest2/src/main/resources/archetype-resources/src/test/resources/log4j.properties:
--------------------------------------------------------------------------------
1 | log4j.rootLogger=DEBUG, CA
2 |
3 | # ConsoleAppender
4 | log4j.appender.CA=org.apache.log4j.ConsoleAppender
5 | log4j.appender.CA.layout=org.apache.log4j.PatternLayout
6 | log4j.appender.CA.layout.ConversionPattern= %d{hh:mm:ss,SSS} [%t] %-5p %c %x - %m%n
7 |
8 |
9 | log4j.logger.org.apache.ibatis.level=INFO
10 | log4j.logger.javax.activation.level=INFO
11 |
--------------------------------------------------------------------------------
/Chapter04/activiti-archetype-unittest2/src/main/resources/archetype-resources/src/test/resources/my-process.bpmn20.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/Chapter04/activiti6-samples/config/pom.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 | activiti6-samples
5 | com.coderdream
6 | 1.0-SNAPSHOT
7 |
8 | 4.0.0
9 | config
10 | jar
11 | config
12 |
13 |
14 | org.activiti
15 | activiti-engine
16 | 6.0.0
17 |
18 |
19 | junit
20 | junit
21 | 4.12
22 | test
23 |
24 |
25 | ch.qos.logback
26 | logback-classic
27 | 1.1.11
28 |
29 |
30 | com.google.guava
31 | guava
32 | 23.0
33 |
34 |
35 | com.h2database
36 | h2
37 | 1.3.176
38 |
39 |
40 | org.activiti
41 | activiti-spring
42 | 6.0.0
43 |
44 |
45 | mysql
46 | mysql-connector-java
47 | 5.1.47
48 |
49 |
50 | com.alibaba
51 | druid
52 | 1.1.6
53 |
54 |
55 |
56 |
57 |
58 |
59 | org.apache.maven.plugins
60 | maven-compiler-plugin
61 | 3.6.1
62 |
63 | 1.8
64 | 1.8
65 |
66 |
67 |
68 | org.apache.maven.plugins
69 | maven-resources-plugin
70 | 2.6
71 |
72 | UTF-8
73 |
74 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/Chapter04/activiti6-samples/config/src/main/java/com/coderdream/DemoMain.java:
--------------------------------------------------------------------------------
1 | package com.coderdream;
2 |
3 | import com.google.common.collect.Maps;
4 | import org.activiti.engine.*;
5 | import org.activiti.engine.form.FormProperty;
6 | import org.activiti.engine.form.TaskFormData;
7 | import org.activiti.engine.impl.form.DateFormType;
8 | import org.activiti.engine.impl.form.StringFormType;
9 | import org.activiti.engine.repository.Deployment;
10 | import org.activiti.engine.repository.DeploymentBuilder;
11 | import org.activiti.engine.repository.ProcessDefinition;
12 | import org.activiti.engine.runtime.ProcessInstance;
13 | import org.activiti.engine.task.Task;
14 | import org.slf4j.Logger;
15 | import org.slf4j.LoggerFactory;
16 |
17 | import java.text.ParseException;
18 | import java.text.SimpleDateFormat;
19 | import java.util.Date;
20 | import java.util.List;
21 | import java.util.Map;
22 | import java.util.Scanner;
23 |
24 | public class DemoMain {
25 |
26 | /**
27 | * logger
28 | */
29 | private static final Logger LOGGER = LoggerFactory.getLogger(DemoMain.class);
30 |
31 | public static void main(String[] args) throws ParseException {
32 | LOGGER.info("启动我们的程序");
33 | // 创建流程引擎
34 | ProcessEngine processEngine = getProcessEngine();
35 |
36 | // 部署流程定义文件
37 | ProcessDefinition processDefinition = getProcessDefinition(processEngine);
38 |
39 | // 启动运行流程
40 | ProcessInstance processInstance = getProcessInstance(processEngine, processDefinition);
41 |
42 | // 处理流程任务
43 | processTask(processEngine, processInstance);
44 |
45 | LOGGER.info("结束我们的程序");
46 | }
47 |
48 | private static void processTask(ProcessEngine processEngine, ProcessInstance processInstance) throws ParseException {
49 | Scanner scanner = new Scanner(System.in);
50 | while (processInstance != null && !processInstance.isEnded()) {
51 | TaskService taskService = processEngine.getTaskService();
52 | List list = taskService.createTaskQuery().list();
53 | LOGGER.info("待处理任务数量 [{}]", list.size());
54 | for (Task task : list) {
55 | LOGGER.info("待处理任务 [{}]", task.getName());
56 | Map variables = getMap(processEngine, scanner, task);
57 |
58 | // 提交工作
59 | taskService.complete(task.getId(), variables);
60 | // 同步流程状态
61 | processInstance = processEngine
62 | .getRuntimeService()
63 | .createProcessInstanceQuery()
64 | .processInstanceId(processInstance.getId())
65 | .singleResult();
66 | }
67 | }
68 | scanner.close();
69 | }
70 |
71 | private static Map getMap(ProcessEngine processEngine, Scanner scanner, Task task) throws ParseException {
72 | FormService formService = processEngine.getFormService();
73 | TaskFormData taskFormData = formService.getTaskFormData(task.getId());
74 | List formProperties = taskFormData.getFormProperties();
75 | Map variables = Maps.newHashMap();
76 | for (FormProperty property : formProperties) {
77 | String line = null;
78 | if (StringFormType.class.isInstance(property.getType())) {
79 | LOGGER.info("请输入 {} ?", property.getName());
80 | line = scanner.nextLine();
81 | variables.put(property.getId(), line);
82 | } else if (DateFormType.class.isInstance(property.getType())) {
83 | LOGGER.info("请输入 {} ? 格式 (yyyy-MM-dd)", property.getName());
84 | line = scanner.nextLine();
85 | SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
86 | Date date = dateFormat.parse(line);
87 | variables.put(property.getId(), date);
88 | } else {
89 | LOGGER.info("类型暂不支持 [{}] ", property.getType());
90 | }
91 | LOGGER.info("您输入的内容是 [{}] :", line);
92 | }
93 | return variables;
94 | }
95 |
96 | private static ProcessInstance getProcessInstance(ProcessEngine processEngine, ProcessDefinition processDefinition) {
97 | RuntimeService runtimeService = processEngine.getRuntimeService();
98 | ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinition.getId());
99 | LOGGER.info("启动流程 [{}]", processInstance.getProcessDefinitionKey());
100 | return processInstance;
101 | }
102 |
103 | private static ProcessDefinition getProcessDefinition(ProcessEngine processEngine) {
104 | RepositoryService repositoryService = processEngine.getRepositoryService();
105 | DeploymentBuilder deploymentBuilder = repositoryService.createDeployment();
106 | deploymentBuilder.addClasspathResource("second_approve.bpmn");
107 | Deployment deployment = deploymentBuilder.deploy();
108 | String deploymentId = deployment.getId();
109 | ProcessDefinition processDefinition = repositoryService
110 | .createProcessDefinitionQuery()
111 | .deploymentId(deploymentId)
112 | .singleResult();
113 | LOGGER.info("流程定义文件 [{}],流程ID [{}]", processDefinition.getName(), processDefinition.getId());
114 | return processDefinition;
115 | }
116 |
117 | private static ProcessEngine getProcessEngine() {
118 | ProcessEngineConfiguration cfg = ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration();
119 | ProcessEngine processEngine = cfg.buildProcessEngine();
120 | String name = processEngine.getName();
121 | String version = ProcessEngine.VERSION;
122 | LOGGER.info("流程引擎名称{},版本{}", name, version);
123 | return processEngine;
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/Chapter04/activiti6-samples/config/src/main/java/com/coderdream/delegate/MDCErrorDelegate.java:
--------------------------------------------------------------------------------
1 | package com.coderdream.delegate;
2 |
3 | import org.activiti.engine.delegate.DelegateExecution;
4 | import org.activiti.engine.delegate.JavaDelegate;
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 |
8 | public class MDCErrorDelegate implements JavaDelegate {
9 |
10 | /** logger */
11 | private static final Logger LOGGER = LoggerFactory.getLogger(MDCErrorDelegate.class);
12 |
13 | @Override
14 | public void execute(DelegateExecution execution) {
15 | LOGGER.info("run MDCErrorDelegate");
16 | throw new RuntimeException("only test");
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Chapter04/activiti6-samples/config/src/main/java/com/coderdream/event/CustomEventListener.java:
--------------------------------------------------------------------------------
1 | package com.coderdream.event;
2 |
3 | import org.activiti.engine.delegate.event.ActivitiEvent;
4 | import org.activiti.engine.delegate.event.ActivitiEventListener;
5 | import org.activiti.engine.delegate.event.ActivitiEventType;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 |
9 | public class CustomEventListener implements ActivitiEventListener {
10 |
11 | /** logger */
12 | private static final Logger LOGGER = LoggerFactory.getLogger(CustomEventListener.class);
13 |
14 | @Override
15 | public void onEvent(ActivitiEvent event) {
16 | ActivitiEventType eventType = event.getType();
17 |
18 | if(ActivitiEventType.CUSTOM.equals(eventType)) {
19 | LOGGER.info("监听到自定义事件 {} \t {}", eventType, event.getProcessInstanceId());
20 | }
21 | }
22 |
23 | @Override
24 | public boolean isFailOnException() {
25 | return false;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Chapter04/activiti6-samples/config/src/main/java/com/coderdream/event/ProcessEventListener.java:
--------------------------------------------------------------------------------
1 | package com.coderdream.event;
2 |
3 | import org.activiti.engine.delegate.event.ActivitiEvent;
4 | import org.activiti.engine.delegate.event.ActivitiEventListener;
5 | import org.activiti.engine.delegate.event.ActivitiEventType;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 |
9 | public class ProcessEventListener implements ActivitiEventListener {
10 |
11 | /** logger */
12 | private static final Logger LOGGER = LoggerFactory.getLogger(ProcessEventListener.class);
13 |
14 | @Override
15 | public void onEvent(ActivitiEvent event) {
16 | ActivitiEventType eventType = event.getType();
17 |
18 | if(ActivitiEventType.PROCESS_STARTED.equals(eventType)) {
19 | LOGGER.info("流程启动 {} \t {}", eventType, event.getProcessInstanceId());
20 | } else if(ActivitiEventType.PROCESS_COMPLETED.equals(eventType)) {
21 | LOGGER.info("流程结束 {} \t {}", eventType, event.getProcessInstanceId());
22 | }
23 | }
24 |
25 | @Override
26 | public boolean isFailOnException() {
27 | return false;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Chapter04/activiti6-samples/config/src/main/java/com/coderdream/interceptor/MDCCommandInvoker.java:
--------------------------------------------------------------------------------
1 | package com.coderdream.interceptor;
2 |
3 | import org.activiti.engine.impl.agenda.AbstractOperation;
4 | import org.activiti.engine.impl.interceptor.DebugCommandInvoker;
5 | import org.activiti.engine.logging.LogMDC;
6 |
7 | public class MDCCommandInvoker extends DebugCommandInvoker {
8 |
9 | // 参考DebugCommandInvoker代码
10 | @Override
11 | public void executeOperation(Runnable runnable) {
12 | // 保存默认状态
13 | boolean mdcEnabled = LogMDC.isMDCEnabled();
14 | // 修改状态
15 | LogMDC.setMDCEnabled(true);
16 | if (runnable instanceof AbstractOperation) {
17 | AbstractOperation operation = (AbstractOperation) runnable;
18 |
19 | if (operation.getExecution() != null) {
20 | // 记录日志
21 | LogMDC.putMDCExecution(operation.getExecution());
22 | }
23 |
24 | }
25 |
26 | super.executeOperation(runnable);
27 | // 清理上下文信息
28 | LogMDC.clear();
29 | // 还原为默认状态
30 | if (!mdcEnabled) {
31 | LogMDC.setMDCEnabled(false);
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Chapter04/activiti6-samples/config/src/main/resources/activiti.cfg.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/Chapter04/activiti6-samples/config/src/main/resources/activiti_druid.cfg.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/Chapter04/activiti6-samples/config/src/main/resources/activiti_eventListener.cfg.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/Chapter04/activiti6-samples/config/src/main/resources/activiti_eventlog.cfg.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/Chapter04/activiti6-samples/config/src/main/resources/activiti_history.cfg.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/Chapter04/activiti6-samples/config/src/main/resources/activiti_mdc.cfg.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Chapter04/activiti6-samples/config/src/main/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
16 |
18 |
19 |
20 |
21 |
22 | ${mdc}
23 | ${encoding}
24 |
25 |
26 |
27 |
28 |
30 | ${log.dir}/file.log
31 |
32 | ${log.dir}/file.%d{yyyy-MM-dd}.log
33 | 30
34 |
35 |
36 | ${std}
37 | ${encoding}
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/Chapter04/activiti6-samples/config/src/main/resources/second_approve.bpmn:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
--------------------------------------------------------------------------------
/Chapter04/activiti6-samples/config/src/test/java/com/coderdream/MyUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.coderdream;
2 | import org.activiti.engine.runtime.ProcessInstance;
3 | import org.activiti.engine.task.Task;
4 | import org.activiti.engine.test.ActivitiRule;
5 | import org.activiti.engine.test.Deployment;
6 | import org.junit.Rule;
7 | import org.junit.Test;
8 |
9 | import static org.junit.Assert.*;
10 |
11 | public class MyUnitTest {
12 |
13 | @Rule
14 | public ActivitiRule activitiRule = new ActivitiRule();
15 |
16 | @Test
17 | @Deployment(resources = {"my-process.bpmn20.xml"})
18 | public void test() {
19 | ProcessInstance processInstance = activitiRule.getRuntimeService().startProcessInstanceByKey("my-process");
20 | assertNotNull(processInstance);
21 |
22 | Task task = activitiRule.getTaskService().createTaskQuery().singleResult();
23 | assertEquals("Activiti is awesome!", task.getName());
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/Chapter04/activiti6-samples/config/src/test/java/com/coderdream/config/ConfigEventListenerTest.java:
--------------------------------------------------------------------------------
1 | package com.coderdream.config;
2 |
3 | import com.coderdream.event.CustomEventListener;
4 | import org.activiti.engine.delegate.event.ActivitiEventType;
5 | import org.activiti.engine.delegate.event.impl.ActivitiEventImpl;
6 | import org.activiti.engine.event.EventLogEntry;
7 | import org.activiti.engine.runtime.ProcessInstance;
8 | import org.activiti.engine.task.Task;
9 | import org.activiti.engine.test.ActivitiRule;
10 | import org.activiti.engine.test.Deployment;
11 | import org.junit.Rule;
12 | import org.junit.Test;
13 | import org.slf4j.Logger;
14 | import org.slf4j.LoggerFactory;
15 |
16 | import java.util.List;
17 |
18 | public class ConfigEventListenerTest {
19 |
20 | /** logger */
21 | private static final Logger LOGGER = LoggerFactory.getLogger(ConfigEventListenerTest.class);
22 |
23 | @Rule
24 | public ActivitiRule activitiRule = new ActivitiRule("activiti_eventListener.cfg.xml");
25 |
26 | @Test
27 | @Deployment(resources = {"my-process.bpmn20.xml"})
28 | public void test() {
29 | ProcessInstance processInstance = activitiRule.getRuntimeService()
30 | .startProcessInstanceByKey("my-process");
31 | Task task = activitiRule.getTaskService().createTaskQuery().singleResult();
32 | // 继续执行流程
33 | activitiRule.getTaskService().complete(task.getId());
34 | // 通过代码添加监听器(非配置文件方式)
35 | activitiRule.getRuntimeService().addEventListener(new CustomEventListener());
36 | // 添加一个自定义事件
37 | activitiRule.getRuntimeService().dispatchEvent(new ActivitiEventImpl(ActivitiEventType.CUSTOM));
38 | }
39 |
40 | }
--------------------------------------------------------------------------------
/Chapter04/activiti6-samples/config/src/test/java/com/coderdream/config/ConfigEventLogTest.java:
--------------------------------------------------------------------------------
1 | package com.coderdream.config;
2 |
3 | import org.activiti.engine.event.EventLogEntry;
4 | import org.activiti.engine.logging.LogMDC;
5 | import org.activiti.engine.runtime.ProcessInstance;
6 | import org.activiti.engine.task.Task;
7 | import org.activiti.engine.test.ActivitiRule;
8 | import org.activiti.engine.test.Deployment;
9 | import org.junit.Rule;
10 | import org.junit.Test;
11 | import org.slf4j.Logger;
12 | import org.slf4j.LoggerFactory;
13 |
14 | import java.util.List;
15 |
16 | import static org.junit.Assert.assertEquals;
17 | import static org.junit.Assert.assertNotNull;
18 |
19 | public class ConfigEventLogTest {
20 |
21 | /** logger */
22 | private static final Logger LOGGER = LoggerFactory.getLogger(ConfigEventLogTest.class);
23 |
24 | @Rule
25 | public ActivitiRule activitiRule = new ActivitiRule("activiti_eventlog.cfg.xml");
26 |
27 | @Test
28 | @Deployment(resources = {"my-process.bpmn20.xml"})
29 | public void test() {
30 | ProcessInstance processInstance = activitiRule.getRuntimeService()
31 | .startProcessInstanceByKey("my-process");
32 |
33 | Task task = activitiRule.getTaskService().createTaskQuery().singleResult();
34 |
35 | // 继续执行流程
36 | activitiRule.getTaskService().complete(task.getId());
37 |
38 |
39 | List eventLogEntries = activitiRule.getManagementService()
40 | .getEventLogEntriesByProcessInstanceId(processInstance.getProcessInstanceId());
41 | for (EventLogEntry eventLogEntry : eventLogEntries) {
42 | LOGGER.info("eventLogEntry = {}, eventLog.data = {}", eventLogEntry, new String(eventLogEntry.getData()));
43 | }
44 | LOGGER.info("eventLogEntries.size = {}", eventLogEntries.size());
45 | }
46 |
47 | }
--------------------------------------------------------------------------------
/Chapter04/activiti6-samples/config/src/test/java/com/coderdream/config/ConfigHistoryLevelTest.java:
--------------------------------------------------------------------------------
1 | package com.coderdream.config;
2 |
3 | import com.google.common.collect.Maps;
4 | import org.activiti.engine.history.HistoricActivityInstance;
5 | import org.activiti.engine.history.HistoricDetail;
6 | import org.activiti.engine.history.HistoricTaskInstance;
7 | import org.activiti.engine.history.HistoricVariableInstance;
8 | import org.activiti.engine.logging.LogMDC;
9 | import org.activiti.engine.runtime.Execution;
10 | import org.activiti.engine.runtime.ProcessInstance;
11 | import org.activiti.engine.task.Task;
12 | import org.activiti.engine.test.ActivitiRule;
13 | import org.activiti.engine.test.Deployment;
14 | import org.apache.commons.lang3.builder.ToStringBuilder;
15 | import org.apache.commons.lang3.builder.ToStringStyle;
16 | import org.junit.Rule;
17 | import org.junit.Test;
18 | import org.slf4j.Logger;
19 | import org.slf4j.LoggerFactory;
20 |
21 | import java.util.List;
22 | import java.util.Map;
23 |
24 | import static org.junit.Assert.assertEquals;
25 | import static org.junit.Assert.assertNotNull;
26 |
27 | public class ConfigHistoryLevelTest {
28 |
29 | /** logger */
30 | private static final Logger LOGGER = LoggerFactory.getLogger(ConfigHistoryLevelTest.class);
31 |
32 | @Rule
33 | public ActivitiRule activitiRule = new ActivitiRule("activiti_history.cfg.xml");
34 |
35 | @Test
36 | @Deployment(resources = {"my-process.bpmn20.xml"})
37 | public void test() {
38 | // 1. 启动流程
39 | Map params = Maps.newHashMap();
40 | params.put("keyStart1", "value1");
41 | params.put("keyStart2", "value2");
42 | ProcessInstance processInstance = activitiRule.getRuntimeService()
43 | .startProcessInstanceByKey("my-process", params);
44 |
45 | // 2. 修改变量
46 | List executions = activitiRule.getRuntimeService()
47 | .createExecutionQuery().listPage(0, 100);
48 |
49 | for (Execution execution : executions) {
50 | LOGGER.info("execution = {}", execution);
51 | }
52 | LOGGER.info("executions.size = {}", executions.size());
53 |
54 | // 取第一条记录
55 | String id = executions.iterator().next().getId();
56 | activitiRule.getRuntimeService().setVariable(id, "keyStart1", "value1_");
57 |
58 | // 3. 提交表单 task
59 | Task task = activitiRule.getTaskService().createTaskQuery().singleResult();
60 | Map properties = Maps.newHashMap();
61 | properties.put("formKey1", "valuef1");
62 | properties.put("formKey2", "valuef2");
63 | activitiRule.getFormService().submitTaskFormData(task.getId(), properties);
64 | assertEquals("Activiti is awesome!", task.getName());
65 |
66 | // 4. 输出历史内容
67 | // 4.1. 输出历史活动
68 | List historicActivityInstances = activitiRule.getHistoryService().
69 | createHistoricActivityInstanceQuery().listPage(0,100);
70 | for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) {
71 | LOGGER.info("historicActivityInstance = {}", historicActivityInstance);
72 | }
73 | LOGGER.info("historicActivityInstances.size = {}", historicActivityInstances.size());
74 |
75 | // 4.2 输出历史变量
76 | List historicVariableInstances = activitiRule.getHistoryService()
77 | .createHistoricVariableInstanceQuery().listPage(0, 100);
78 | for (HistoricVariableInstance historicVariableInstance : historicVariableInstances) {
79 | LOGGER.info("historicVariableInstance = {}", historicVariableInstance);
80 | }
81 | LOGGER.info("historicVariableInstances.size = {}", historicVariableInstances.size());
82 |
83 | // 4.3. 输出历史表单
84 | List historicTaskInstances = activitiRule.getHistoryService()
85 | .createHistoricTaskInstanceQuery().listPage(0,100);
86 | for (HistoricTaskInstance historicTaskInstance : historicTaskInstances) {
87 | LOGGER.info("historicTaskInstance = {}", historicTaskInstance);
88 | }
89 | LOGGER.info("historicTaskInstances.size = {}", historicTaskInstances.size());
90 |
91 | // 4.4. 输出历史表单详情
92 | List historicDetailsForm = activitiRule.getHistoryService().
93 | createHistoricDetailQuery().formProperties().listPage(0,100);
94 |
95 | for (HistoricDetail historicDetail : historicDetailsForm) {
96 | LOGGER.info("historicDetail = {}", historicDetail);
97 | }
98 | LOGGER.info("historicDetailsForm.size = {}", historicDetailsForm.size());
99 |
100 | // 4.5. 输出历史详情
101 | List historicDetails = activitiRule.getHistoryService().
102 | createHistoricDetailQuery().listPage(0,100);
103 |
104 | for (HistoricDetail historicDetail : historicDetails) {
105 | LOGGER.info("historicDetail = {}", toString(historicDetail));
106 | }
107 | LOGGER.info("historicDetails.size = {}", historicDetails.size());
108 | }
109 |
110 | static String toString(HistoricDetail historicDetail) {
111 | return ToStringBuilder.reflectionToString(historicDetail, ToStringStyle.SHORT_PREFIX_STYLE);
112 | }
113 |
114 | }
115 |
--------------------------------------------------------------------------------
/Chapter04/activiti6-samples/config/src/test/java/com/coderdream/config/ConfigMDCTest.java:
--------------------------------------------------------------------------------
1 | package com.coderdream.config;
2 |
3 | import org.activiti.engine.logging.LogMDC;
4 | import org.activiti.engine.runtime.ProcessInstance;
5 | import org.activiti.engine.task.Task;
6 | import org.activiti.engine.test.ActivitiRule;
7 | import org.activiti.engine.test.Deployment;
8 | import org.junit.Rule;
9 | import org.junit.Test;
10 | import org.slf4j.Logger;
11 | import org.slf4j.LoggerFactory;
12 |
13 | import static org.junit.Assert.assertEquals;
14 | import static org.junit.Assert.assertNotNull;
15 |
16 | public class ConfigMDCTest {
17 |
18 | /** logger */
19 | private static final Logger LOGGER = LoggerFactory.getLogger(ConfigMDCTest.class);
20 |
21 | @Rule
22 | public ActivitiRule activitiRule = new ActivitiRule("activiti_mdc.cfg.xml");
23 |
24 | @Test
25 | @Deployment(resources = {"my-process.bpmn20.xml"})
26 | public void test() {
27 | // 打开MDC开关
28 | LogMDC.setMDCEnabled(true);
29 | ProcessInstance processInstance = activitiRule.getRuntimeService()
30 | .startProcessInstanceByKey("my-process");
31 | assertNotNull(processInstance);
32 |
33 | Task task = activitiRule.getTaskService().createTaskQuery().singleResult();
34 | assertEquals("Activiti is awesome!", task.getName());
35 |
36 | // 继续执行流程
37 | activitiRule.getTaskService().complete(task.getId());
38 | }
39 |
40 | @Test
41 | @Deployment(resources = {"my-process_mdcerror.bpmn20.xml"})
42 | public void test2() {
43 | ProcessInstance processInstance = activitiRule.getRuntimeService()
44 | .startProcessInstanceByKey("my-process");
45 | assertNotNull(processInstance);
46 |
47 | Task task = activitiRule.getTaskService().createTaskQuery().singleResult();
48 | assertEquals("Activiti is awesome!", task.getName());
49 |
50 | // 继续执行流程
51 | activitiRule.getTaskService().complete(task.getId());
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/Chapter04/activiti6-samples/config/src/test/java/com/coderdream/config/ConfigTest.java:
--------------------------------------------------------------------------------
1 | package com.coderdream.config;
2 |
3 |
4 | import org.activiti.engine.ProcessEngineConfiguration;
5 | import org.junit.Test;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 |
9 | public class ConfigTest {
10 |
11 | /**
12 | * logger
13 | */
14 | private static final Logger LOGGER = LoggerFactory.getLogger(ConfigTest.class);
15 |
16 | @Test
17 | public void testConfig1() {
18 | ProcessEngineConfiguration configuration = ProcessEngineConfiguration
19 | .createProcessEngineConfigurationFromResourceDefault();
20 |
21 | LOGGER.info("configuration = {}", configuration);
22 | }
23 |
24 | @Test
25 | public void testConfig2() {
26 | ProcessEngineConfiguration configuration = ProcessEngineConfiguration
27 | .createStandaloneProcessEngineConfiguration();
28 |
29 | LOGGER.info("configuration = {}", configuration);
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/Chapter04/activiti6-samples/config/src/test/java/com/coderdream/config/ConfitDBTest.java:
--------------------------------------------------------------------------------
1 | package com.coderdream.config;
2 |
3 | import org.activiti.engine.ProcessEngine;
4 | import org.activiti.engine.ProcessEngineConfiguration;
5 | import org.junit.Test;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 |
9 | public class ConfitDBTest {
10 |
11 | /** logger */
12 | private static final Logger LOGGER = LoggerFactory.getLogger(ConfitDBTest.class);
13 |
14 | @Test
15 | public void testConfig1() {
16 | ProcessEngineConfiguration configuration = ProcessEngineConfiguration
17 | .createProcessEngineConfigurationFromResourceDefault();
18 |
19 | LOGGER.info("configuration = {}", configuration);
20 | ProcessEngine processEngine = configuration.buildProcessEngine();
21 | LOGGER.info("获取流程引擎 {}", processEngine.getName());
22 | processEngine.close();
23 | }
24 |
25 | @Test
26 | public void testConfig2() {
27 | ProcessEngineConfiguration configuration = ProcessEngineConfiguration
28 | .createProcessEngineConfigurationFromResource("activiti_druid.cfg.xml");
29 |
30 | LOGGER.info("configuration = {}", configuration);
31 | ProcessEngine processEngine = configuration.buildProcessEngine();
32 | LOGGER.info("获取流程引擎 {}", processEngine.getName());
33 | processEngine.close();
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Chapter04/activiti6-samples/config/src/test/resources/activiti.cfg.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Chapter04/activiti6-samples/config/src/test/resources/log4j.properties:
--------------------------------------------------------------------------------
1 | log4j.rootLogger=DEBUG, CA
2 |
3 | # ConsoleAppender
4 | log4j.appender.CA=org.apache.log4j.ConsoleAppender
5 | log4j.appender.CA.layout=org.apache.log4j.PatternLayout
6 | log4j.appender.CA.layout.ConversionPattern= %d{hh:mm:ss,SSS} [%t] %-5p %c %x - %m%n
7 |
8 |
9 | log4j.logger.org.apache.ibatis.level=INFO
10 | log4j.logger.javax.activation.level=INFO
11 |
--------------------------------------------------------------------------------
/Chapter04/activiti6-samples/config/src/test/resources/my-process.bpmn20.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Chapter04/activiti6-samples/config/src/test/resources/my-process_mdcerror.bpmn20.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/Chapter04/activiti6-samples/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.coderdream
8 | activiti6-samples
9 | pom
10 | 1.0-SNAPSHOT
11 |
12 | config
13 |
14 |
15 |
16 | org.springframework.boot
17 | spring-boot-starter-parent
18 | 2.0.0.RELEASE
19 |
20 |
21 |
--------------------------------------------------------------------------------
/Chapter04/images/0401_Project_Structrue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoderDream/ActivitiInAction/97e80418cb1be68fcb7e522530dc96a02a6f2093/Chapter04/images/0401_Project_Structrue.png
--------------------------------------------------------------------------------
/Chapter04/images/0402_Add_Archetype.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoderDream/ActivitiInAction/97e80418cb1be68fcb7e522530dc96a02a6f2093/Chapter04/images/0402_Add_Archetype.png
--------------------------------------------------------------------------------
/Chapter04/images/0403_Create_From_Archetype.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoderDream/ActivitiInAction/97e80418cb1be68fcb7e522530dc96a02a6f2093/Chapter04/images/0403_Create_From_Archetype.png
--------------------------------------------------------------------------------
/Chapter04/images/0404_ProcessEngineConfiguration.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoderDream/ActivitiInAction/97e80418cb1be68fcb7e522530dc96a02a6f2093/Chapter04/images/0404_ProcessEngineConfiguration.png
--------------------------------------------------------------------------------
/Chapter04/images/0406_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoderDream/ActivitiInAction/97e80418cb1be68fcb7e522530dc96a02a6f2093/Chapter04/images/0406_01.jpg
--------------------------------------------------------------------------------
/Chapter04/images/0406_02.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoderDream/ActivitiInAction/97e80418cb1be68fcb7e522530dc96a02a6f2093/Chapter04/images/0406_02.jpg
--------------------------------------------------------------------------------
/Chapter04/images/0406_03.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoderDream/ActivitiInAction/97e80418cb1be68fcb7e522530dc96a02a6f2093/Chapter04/images/0406_03.jpg
--------------------------------------------------------------------------------
/Chapter04/images/0406_04.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoderDream/ActivitiInAction/97e80418cb1be68fcb7e522530dc96a02a6f2093/Chapter04/images/0406_04.jpg
--------------------------------------------------------------------------------
/Chapter04/images/0406_05.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoderDream/ActivitiInAction/97e80418cb1be68fcb7e522530dc96a02a6f2093/Chapter04/images/0406_05.jpg
--------------------------------------------------------------------------------
/Chapter04/images/0406_06.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoderDream/ActivitiInAction/97e80418cb1be68fcb7e522530dc96a02a6f2093/Chapter04/images/0406_06.jpg
--------------------------------------------------------------------------------
/Chapter04/images/041000_Result.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoderDream/ActivitiInAction/97e80418cb1be68fcb7e522530dc96a02a6f2093/Chapter04/images/041000_Result.png
--------------------------------------------------------------------------------
/Chapter04/images/041001_ProcessEngineConfigurationImpl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoderDream/ActivitiInAction/97e80418cb1be68fcb7e522530dc96a02a6f2093/Chapter04/images/041001_ProcessEngineConfigurationImpl.png
--------------------------------------------------------------------------------
/Chapter04/images/041002_initDatabaseEventLogging.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoderDream/ActivitiInAction/97e80418cb1be68fcb7e522530dc96a02a6f2093/Chapter04/images/041002_initDatabaseEventLogging.png
--------------------------------------------------------------------------------
/Chapter04/images/041003_EventLogger.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoderDream/ActivitiInAction/97e80418cb1be68fcb7e522530dc96a02a6f2093/Chapter04/images/041003_EventLogger.png
--------------------------------------------------------------------------------
/Chapter04/images/041004_addCloseListener.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoderDream/ActivitiInAction/97e80418cb1be68fcb7e522530dc96a02a6f2093/Chapter04/images/041004_addCloseListener.png
--------------------------------------------------------------------------------
/Chapter04/images/041005_insert.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoderDream/ActivitiInAction/97e80418cb1be68fcb7e522530dc96a02a6f2093/Chapter04/images/041005_insert.png
--------------------------------------------------------------------------------
/Chapter04/images/041101.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoderDream/ActivitiInAction/97e80418cb1be68fcb7e522530dc96a02a6f2093/Chapter04/images/041101.jpg
--------------------------------------------------------------------------------
/Chapter04/images/041102.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoderDream/ActivitiInAction/97e80418cb1be68fcb7e522530dc96a02a6f2093/Chapter04/images/041102.jpg
--------------------------------------------------------------------------------
/Chapter04/images/041103.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoderDream/ActivitiInAction/97e80418cb1be68fcb7e522530dc96a02a6f2093/Chapter04/images/041103.jpg
--------------------------------------------------------------------------------
/Chapter04/images/041104.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoderDream/ActivitiInAction/97e80418cb1be68fcb7e522530dc96a02a6f2093/Chapter04/images/041104.jpg
--------------------------------------------------------------------------------
/Chapter04/images/041105.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoderDream/ActivitiInAction/97e80418cb1be68fcb7e522530dc96a02a6f2093/Chapter04/images/041105.jpg
--------------------------------------------------------------------------------
/Chapter04/images/041201_ActivitiEventListener.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoderDream/ActivitiInAction/97e80418cb1be68fcb7e522530dc96a02a6f2093/Chapter04/images/041201_ActivitiEventListener.png
--------------------------------------------------------------------------------
/Chapter04/images/041202_BaseEntityEventListener.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoderDream/ActivitiInAction/97e80418cb1be68fcb7e522530dc96a02a6f2093/Chapter04/images/041202_BaseEntityEventListener.png
--------------------------------------------------------------------------------
/Chapter04/images/041203_ActivitiEvent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoderDream/ActivitiInAction/97e80418cb1be68fcb7e522530dc96a02a6f2093/Chapter04/images/041203_ActivitiEvent.png
--------------------------------------------------------------------------------
/Chapter04/images/041204_ActivitiEntityEvent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoderDream/ActivitiInAction/97e80418cb1be68fcb7e522530dc96a02a6f2093/Chapter04/images/041204_ActivitiEntityEvent.png
--------------------------------------------------------------------------------
/Chapter04/images/041205_ActivitiVariableEvent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CoderDream/ActivitiInAction/97e80418cb1be68fcb7e522530dc96a02a6f2093/Chapter04/images/041205_ActivitiVariableEvent.png
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 CoderDream
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ActivitiInAction
2 | Activiti6.0工作流引擎深度解析与实战
3 | 章节
4 | ### 第1章 课程介绍
5 | - 1-1 课程导学
6 | ### 第2章 工作流入门
7 | - 2-1 本章概述
8 | - 2-2 工作流介绍
9 | - 2-3 工作流引擎技术选型
10 | - 2-4 Activiti6.0快速体验-部署环境介绍
11 | - 2-5 Activiti6.0快速体验-部署环境实操
12 | - 2-6 Activiti6.0快速体验-流程体验
13 | ### 第3章 Activiti6.0源码初探
14 | - 3-1 本章概述
15 | - 3-2 Activiti6.0源码初探-概览与获取
16 | - 3-3 Activiti6.0源码初探-engine
17 | - 3-4 Activiti6.0源码初探-模块介绍
18 | - 3-5 Activiti6.0源码初探-activiti-app运行
19 | - 3-6 Activiti6.0源码初探-WebConfigurer
20 | - 3-7 Activiti6.0源码初探-helloword-1
21 | - 3-8 Activiti6.0源码初探-helloword-2
22 | - 3-9 Activiti6.0源码初探-helloword_idea-1
23 | - 3-10 Activiti6.0源码初探-helloword_idea-2
24 | - 3-11 Activiti6.0源码初探-helloword_idea-3
25 | ### 第4章 Activiti6.0引擎配置
26 | - 4-1 本章概述
27 | - 4-2 创建流程引擎配置-config_samples
28 | - 4-3 创建流程引擎配置-archetype
29 | - 4-4 数据库配置-dbconfig
30 | - 4-5 数据库配置-dbconfig_code
31 | - 4-6 日志记录配置-logging
32 | - 4-7 日志记录配置-logging_mdc
33 | - 4-8 历史记录配置-history-1
34 | - [4-9 历史记录配置-history-2](/Chapter04/Chapter0410.md)
35 | - 4-10 事件处理及监听器配置-eventlog
36 | - 4-11 事件处理及监听器配置-eventLinstener-1
37 | - [4-12 事件处理及监听器配置-eventLinstener-2](/Chapter04/Chapter0410.md)
38 | - 4-13 命令拦截器配置-command-1
39 | - 4-14 命令拦截器配置-command-2
40 | - 4-15 作业执行器配置-job-1
41 | - 4-16 作业执行器配置-job-2
42 | - 4-17 Activiti与spring集成-1
43 | - 4-18 Activiti与spring集成-2
44 | - 4-19 Activiti与spring集成-3
45 | ### 第5章 Activiti核心API
46 | - 5-1 本章概述
47 | - 5-2 流程存储服务-RepositoryService-1
48 | - 5-3 流程存储服务-RepositoryService-2
49 | - 5-4 流程运行 控制服务-RuntimeService-1
50 | - 5-5 流程运行 控制服务-RuntimeService-2
51 | - 5-6 流程运行 控制服务-RuntimeService-3
52 | - 5-7 任务管理服务-TaskService-1
53 | - 5-8 任务管理服务-TaskService-2
54 | - 5-9 任务管理服务-TaskService-3
55 | - 5-10 用户和用户组管理服务-IdentityService
56 | - 5-11 表单管理服务- formeService
57 | - 5-12 历史数据管理服务-HistoryService-1
58 | - 5-13 历史数据管理服务-HistoryService-2
59 | - 5-14 其它管理服务-OtherService
60 | - 5-15 异常策略
61 | ### 第6章 数据库设计与模型映射
62 | - 6-1 通用数据表设计
63 | - 6-2 流程定义存储表设计
64 | - 6-3 身份数据表设计
65 | - 6-4 运行时流程数据表设计-1
66 | - 6-5 运行时流程数据表设计-2
67 | - 6-6 历史流程数据表设计-1
68 | - 6-7 历史流程数据表设计-2
69 | ### 第7章 BPMN2.0规范
70 | - 7-1 本章概述
71 | - 7-2 BPMN2.0流程事件-事件分类
72 | - 7-3 BPMN2.0流程事件-错误事件
73 | - 7-4 BPMN2.0流程事件-信号消息事件
74 | - 7-5 BPMN2.0流程任务-用户任务-1
75 | - 7-6 BPMN2.0流程任务-用户任务-2
76 | - 7-7 BPMN2.0脚本任务
77 | - 7-8 BPMN2.0服务任务-1
78 | - 7-9 BPMN2.0服务任务-2
79 | - 7-10 BPMN2.0顺序流和网关-1
80 | - 7-11 BPMN2.0顺序流和网关-2
81 | - 7-12 BPMN2.0顺序流和网关-3
82 | - 7-13 BPMN2.0子流程-1
83 | - 7-14 BPMN2.0子流程-2
84 | - 7-15 BPMN2.0子流程-3
85 | - 7-16 BPMN2.0子流程-4
86 | ### 第8章 Activiti6.0集成Spring Boot2.0
87 | - 8-1 本章概述
88 | - 8-2 Spring Boot2.0入门实例-1
89 | - 8-3 Spring Boot2.0入门实例-2
90 | - 8-4 Spring Boot2.0启动依赖和自动装配-1
91 | - 8-5 Spring Boot2.0启动依赖和自动装配-2
92 | - 8-6 Activiti6.0与Spring Boot2.0集成-1
93 | - 8-7 Activiti6.0与Spring Boot2.0集成-2
94 | ### 第9章 工作流平台搭建
95 | - 9-1 工作流平台搭建-需求分析
96 | - 9-2 工作流平台搭建集成spring boot1-1
97 | - 9-3 工作流平台搭建集成spring boot1-2
98 | - 9-4 工作流平台搭建集成spring boot1-3
99 | - 9-5 工作流平台搭建集成spring boot1-4
100 | - 9-6 工作流平台升级spring boot2-1
101 | - 9-7 工作流平台升级spring boot2-2
102 | - 9-8 工作流平台升级spring boot2-3
103 | - 9-9 工作流平台升级spring boot2-4
104 | - 9-10 工作流平台搭建-workflow-1
105 | - 9-11 工作流平台搭建-workflow-2
106 | - 9-12 工作流平台搭建-购物流程-1
107 | - 9-13 工作流平台搭建-购物流程-2
108 | - 9-14 工作流平台搭建-购物流程-3
109 | ### 第10章 工作流平台部署和运维
110 | - 10-1 工作流平台部署-1
111 | - 10-2 工作流平台部署-2
112 | ### 第11章 课程总结
113 | - 11-1 课程总结
114 |
115 | 课程介绍:[链接](https://blog.csdn.net/weixin_43121468/article/details/82347026)
116 | 网盘链接:https://pan.baidu.com/s/1fYddxHp94g12fMBu4I__Ww 提取码:aaaz
117 |
118 | ### 参考
119 |
120 | 1. [fhqscfss/activiti-test](https://github.com/fhqscfss/activiti-test)
121 | 2. [chandler1142/activiti-study](https://github.com/chandler1142/activiti-study)
122 | 3. [shengjie8329/activiti-helloword](https://github.com/shengjie8329/activiti-helloword)
--------------------------------------------------------------------------------