这篇文章将教你如果用PlantUML绘制流程图。

流程

1
2
3
4
5
6
7
{% plantuml %}
:Hello world;
:This is on defined on
several **lines**;
{% endplantuml %}

@startuml

条件语句

条件语句1

1
2
3
4
5
6
7
8
9
10
11
12
{% plantuml %}
start

if (Graphviz installed?) then (yes)
:process all\ndiagrams;
else (no)
:process only
__sequence__ and __activity__ diagrams;
endif

stop
{% endplantuml %}

条件语句2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{% plantuml %}
start
if (condition A) then (yes)
:Text 1;
elseif (condition B) then (yes)
:Text 2;
stop
elseif (condition C) then (yes)
:Text 3;
elseif (condition D) then (yes)
:Text 4;
else (nothing)
:Text else;
endif
stop
{% endplantuml %}

循环语句

循环语句1

1
2
3
4
5
6
7
8
9
10
{% plantuml %}
start

repeat
:read data;
:generate diagrams;
repeat while (more data?)

stop
{% endplantuml %}

循环语句2

1
2
3
4
5
6
7
8
9
10
{% plantuml %}
start

while (data available?)
:read data;
:generate diagrams;
endwhile

stop
{% endplantuml %}

循环语句3

1
2
3
4
5
6
{% plantuml %}
while (check filesize ?) is (not empty)
:read file;
endwhile (empty)
:close file;
{% endplantuml %}

循环语句4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{% plantuml %}
start

if (multiprocessor?) then (yes)
fork
:Treatment 1;
fork again
:Treatment 2;
end fork
else (monoproc)
:Treatment 1;
:Treatment 2;
endif
{% endplantuml %}

子程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{% plantuml %}
start
:foo1;
floating note left: This is a note
:foo2;
note right
This note is on several
//lines// and can
contain <b>HTML</b>
====
* Calling the method ""foo()"" is prohibited
end note
stop
{% endplantuml %}
1
2
3
4
5
6
7
{% plantuml %}
start
:starting progress;
#HotPink:reading configuration files
These files should edited at this point!;
#AAAAAA:ending of the process;
{% endplantuml %}

更改颜色

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{% plantuml %}
:foo1;
-> You can put text on arrows;
if (test) then
-[#blue]->
:foo2;
-[#green,dashed]-> The text can
also be on several lines
and **very** long...;
:foo3;
else
-[#black,dotted]->
:foo4;
endif
-[#gray,bold]->
:foo5;
{% endplantuml %}

组合

1
2
3
4
5
6
7
8
9
10
11
12
13
{% plantuml %}
start
partition Initialization {
:read config file;
:init internal variable;
}
partition Running {
:wait for user interaction;
:print information;
}

stop
{% endplantuml %}

泳道

1
2
3
4
5
6
7
8
9
10
11
12
13
{% plantuml %}
|Swimlane1|
start
:foo1;
|#AntiqueWhite|Swimlane2|
:foo2;
:foo3;
|Swimlane1|
:foo4;
|Swimlane2|
:foo5;
stop
{% endplantuml %}

1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{% plantuml %}
:start;
fork
:foo1;
:foo2;
fork again
:foo3;
detach
endfork
if (foo4) then
:foo5;
detach
endif
:foo6;
detach
:foo7;
stop
{% endplantuml %}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{% plantuml %}
:Ready;
:next(o)|
:Receiving;
split
:nak(i)<
:ack(o)>
split again
:ack(i)<
:next(o)
on several line|
:i := i + 1]
:ack(o)>
split again
:err(i)<
:nak(o)>
split again
:foo/
split again
:i > 5}
stop
end split
:finish;
{% endplantuml %}

SDL 例子

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
{% plantuml %}
start
:ClickServlet.handleRequest();
:new page;
if (Page.onSecurityCheck) then (true)
:Page.onInit();
if (isForward?) then (no)
:Process controls;
if (continue processing?) then (no)
stop
endif

if (isPost?) then (yes)
:Page.onPost();
else (no)
:Page.onGet();
endif
:Page.onRender();
endif
else (false)
endif

if (do redirect?) then (yes)
:redirect process;
else
if (do forward?) then (yes)
:Forward request;
else (no)
:Render page template;
endif
endif

stop
{% endplantuml %}

一个复杂的流程图

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
{% plantuml %}
start
:初始化;
:创建看门狗线程;
fork
#00FF00:while(1);
note right
看门狗线程
end note
repeat
if(>2min没喂狗) then (Y)
#8EE5EE:取消alive节点;
endif
:sleep(5);
repeat while(1)
fork again
#HotPink:while(1);
note left
agent线程
end note
repeat
if (注册标志==1) then (Y)
:喂狗;
else (N)
endif
:db_detect;
if(检测成功?) then (Y)
#A020F0:获取dead节点;
note left
根据dead节点中的DONE
关键字判断是否发生过回滚
end note
if(有dead节点? && 未回滚?) then (Y)
:db_clear_master;
note left
db_clear_master共干了4件事
====
* 1.kill session
* 2.set global rpl_semi_sync_master_enabled=off !!!
* 3.set global read_only=1
* 4.stop slave
end note
if(clear_mater成功?) then (Y)
:调mysql_master_clear脚本;
note left
回滚脚本在这里调用的
end note
if(调用成功?) then (Y)
#A020F0:修改dead节点DONE_SUCCESS;
else (N)
#A020F0:修改dead节点DONE_FAIL;
endif
else (N)
#HotPink:goto while(1);
detach
endif
else (N)
endif
if(注册标志==0 && >60s未注册) then(Y)
#8EE5EE:注册alive节点;
:注册标志=1;
else (N)
endif
:10min更新一次dbrole;
note left
为一键切机房保存master机器
否则需要一台台的检测机器主备浪费时间
end note
:10min运行一次赋权脚本;
else (N)
#A020F0:获取dead节点;
if(有dead节点?) then (Y)
if(未回滚?) then (Y)
:"db_clear_master";
if(clear_master成功) then (Y)
else (N)
#HotPink:goto while(1);
detach
endif
else (N)
endif
:重新检测db_detect;
if("检测成功?") then (N)
else (Y)
#HotPink:goto while(1);
detach
endif
else (N)
endif
if("可忽略err?") then (N)
#8EE5EE:取消alive节点;
:注册标志=0;
#0000FF:exit(0);
stop
else (Y)
endif
endif
:sleep(1);
#HotPink:goto while(1);
{% endplantuml %}