概述

PlantUML 最擅长制作的就是时序图啦!
在本文中,我们将讲解如何使用 PlantUML 来演示时序图的制作。

简单示例

在时序图中,可以使用 -> 来绘制参与者之间传递的消息,而不必显示的声明具体的参与者。
一个简单的示例如下:

  1. 用户 -> 认证中心: 登录操作
  2. 认证中心 -> 缓存: 存放(key=token+ip,value=token)token
  3. 用户 <- 认证中心 : 认证成功返回token
  4. 用户 -> 认证中心: 下次访问头部携带token认证
  5. 认证中心 <- 缓存: key=token+ip获取token
  6. 其他服务 <- 认证中心: 存在且校验成功则跳转到用户请求的其他服务
  7. 其他服务 -> 用户: 信息

时序图 - 图1此外,我们可以使用 —> 来表示一个虚线剪头,此外,还可以是使用 <- 和 <— 来表示消息传递。

声明参与者

虽然在时序图中,我们可以直接使用 -> 来进行参与者之间的消息传递,无需一定要对参与者进行声明。
但是,实际上,PlantUML 中其实也可以对参与者进行显示声明并进行更多的控制。
在 PlantUML 中可以使用以下这些关键词来对参与者进行声明,不同的参与者显示的形状不同:

  • actor: 角色
  • boundary: 边界
  • control: 控制
  • entity: 实体
  • database: 数据库
  • collections: 集合
  • queue: 队列
  • participant: 普通参与者

我们来看一段示例代码:

  1. participant A as Foo
  2. actor B as Foo1
  3. boundary C as Foo2
  4. control D as Foo3 order 1
  5. entity E as Foo4 order 2
  6. database F as Foo5 order 4
  7. collections G as Foo6 order 3 #red
  8. queue H as Foo7 #99FF99
  9. Foo -> Foo1: To Actor
  10. Foo -> Foo2: To boundary
  11. Foo -> Foo3: To control
  12. Foo -> Foo4: To entity
  13. Foo -> Foo5: To database
  14. Foo -> Foo6: To collections
  15. Foo -> Foo7: To queue

时序图 - 图2可以看到:

  • 我们使用了 as 为 UML 显示中的实体设置别名,并在后续的消息传递中通过别名进行设置。
  • 同时,我们可以通过 order 来自定义参与者打印的顺序,即 order 顺序由小至大从左向右依次显示。
  • 此外,我们还可以对参与者通过 RGB 值或者颜色名称来声明实体的颜色。

    参与者中使用非字母符号

    在参与者中,如果包含一些特殊符号时,可以用 “” 进行包围,示例如下:

    1. Alice -> "Bob()" : Hello
    2. "Bob()" -> "This is very\nlong" as Long
    3. Long --> "Bob()" : ok

    时序图 - 图3

    给自己发消息

    在时序图中,参与者也可以给自己发送消息,示例如下:

    1. Alice->Alice: This is a signal to self.\nIt also demonstrates\nmultiline \ntext

    时序图 - 图4

    文本对齐

    默认情况下,消息都会在连接线的上方显示,当然,我们也可以通过一些方式来控制其行为,例如我们可以让响应信息显示在剪头的下方:

    1. skinparam responseMessageBelowArrow true
    2. Bob -> Alice : hello
    3. Alice -> Bob : ok

    时序图 - 图5

    消息样式

    在 PlantUML 中,我们对剪头的样式进行配置,具体来说,有如下几种不同的消息样式:

  • -> :普通的消息样式

  • —> :虚线消息样式
  • ->x:丢失的消息
  • ->o:箭头末尾加圈
  • -\,-/:剪头只有上半部分或者下半部分
  • ->>:细箭头
  • <->:双向箭头

示例代码如下:

  1. Bob ->x Alice
  2. Bob --> Alice
  3. Bob -> Alice
  4. Bob ->> Alice
  5. Bob -\ Alice
  6. Bob \\- Alice
  7. Bob //-- Alice
  8. Bob ->o Alice
  9. Bob o\\-- Alice
  10. Bob <-> Alice
  11. Bob <->o Alice

时序图 - 图6

箭头颜色调整

在 PlantUML 中可以对箭头的颜色进行调整:

  1. Bob -[#red]> Alice : hello
  2. Alice -[#0000FF]->Bob : ok

时序图 - 图7

消息序号编号

关键词 autonumber 可以自动在消息上增加编号:

  1. autonumber
  2. Bob -> Alice : Authentication Request
  3. Bob <- Alice : Authentication Response

时序图 - 图8

标题、页眉和页脚

在 PlantUML 中,可以对 UML 图配置标题、页眉和页脚,示例如下:

  1. header Page Header1
  2. footer Page %page% of %lastpage%
  3. title Example Title1
  4. Alice -> Bob : message 1
  5. Alice -> Bob : message 2

时序图 - 图9

时序图分页

在 PlantUML 中可以使用关键词 newpage 用于把一张图分成多张,即将多张图在同一个文件中进行管理。
在 newpage 之后添加文字可以作为新的示例图的标题,这样就可以方便的进行长图打印。

  1. Alice -> Bob : message 1
  2. Alice -> Bob : message 2
  3. newpage
  4. Alice -> Bob : message 3
  5. Alice -> Bob : message 4
  6. newpage A title for the\nlast page
  7. Alice -> Bob : message 5
  8. Alice -> Bob : message 6

组合消息

在 PlantUML 中,可以通过如下关键词来组合消息:

  • alt/else:条件控制
  • opt
  • loop:循环
  • par
  • break
  • critical
  • group:自定义分组,可以在其中通过 [] 的方式来增加次级标签
  • end:结束分组

Ps:分组可以嵌套使用。
我们先来看一个示例:

  1. Alice -> Bob: 认证请求
  2. alt 成功情况
  3. Bob -> Alice: 认证接受
  4. else 某种失败情况
  5. Bob -> Alice: 认证失败
  6. group 我自己的标签
  7. Alice -> Log : 开始记录攻击日志
  8. loop 1000
  9. Alice -> Bob: DNS 攻击
  10. end
  11. Alice -> Log : 结束记录攻击日志
  12. end
  13. else 另一种失败
  14. Bob -> Alice: 请重复
  15. end

时序图 - 图10

消息、节点注释

我们可以通过在消息后面添加 note left 或者 note right 关键词来给消息添加注释,也可以通过使用 end note 来添加多行注释。

  1. Alice->Bob : hello
  2. note left: this is a first note
  3. Bob->Alice : ok
  4. note right#aqua: this is another note
  5. Bob->Bob : I am thinking
  6. note left
  7. a note
  8. can also be defined
  9. on several lines
  10. end note

时序图 - 图11此外,我们还可以使用 note left of,note right of 或 note over 在节点 (participant) 的相对位置放置注释,还可以通过修改背景色来高亮显示注释。

  1. participant Alice
  2. participant Bob
  3. note left of Alice #aqua
  4. This is displayed
  5. left of Alice.
  6. end note
  7. note right of Alice: This is displayed right of Alice.
  8. note over Alice: This is displayed over Alice.
  9. note over Alice, Bob #FFAAAA: This is displayed\n over Bob and Alice.
  10. note over Bob, Alice
  11. This is yet another
  12. example of
  13. a long note.
  14. end note

时序图 - 图12此外,还可以使用 hnote 和 rnote 这两个关键字来修改备注框的形状:

  • hnote 代表六边形(hexagonal)的备注框;
  • rnote 代表正方形(rectangle)的备注框。

示例代码:

  1. caller -> server : conReq
  2. hnote over caller : 空闲
  3. caller <- server : conConf
  4. rnote over server
  5. "r"是正方形
  6. "h"是六边形
  7. endrnote
  8. note over server
  9. 文本
  10. end note
  11. hnote over caller
  12. 文本
  13. endhnote

时序图 - 图13此外,我们再增加备注消息注释时,还可以直接作用在全部的参与者上,示例如下:

  1. Alice->Bob:m1
  2. Bob->Charlie:m2
  3. note over Alice, Charlie: 创建跨越所有参与者的备注的旧方法:\n ""note over //FirstPart, LastPart//"".
  4. note across: 新方法:\n""note across""
  5. Bob->Alice
  6. hnote across: 跨越所有参与者的备注。

时序图 - 图14需要注意的是,在 UML 时序图中添加多个注释时,注释之间默认不是对齐的。
当然,我们可以通过 / 来在同一级对齐多个备注:

  1. note over Alice : Alice的初始状态
  2. / note over Bob : Bob的初始状态
  3. Bob -> Alice : hello

时序图 - 图15

Creole 和 HTML 格式

在 UML 图中,我们可以使用 Creole 格式:

  1. participant Alice
  2. participant "The **Famous** Bob" as Bob
  3. Alice -> Bob : hello --there--
  4. ... Some ~~long delay~~ ...
  5. Bob -> Alice : ok
  6. note left
  7. This is **bold**
  8. This is //italics//
  9. This is ""monospaced""
  10. This is --stroked--
  11. This is __underlined__
  12. This is ~~waved~~
  13. end note
  14. Alice -> Bob : A //well formatted// message
  15. note right of Alice
  16. This is <back:cadetblue><size:18>displayed</size></back>
  17. __left of__ Alice.
  18. end note
  19. note left of Bob
  20. <u:red>This</u> is <color #118888>displayed</color>
  21. **<color purple>left of</color> <s:red>Alice</strike> Bob**.
  22. end note
  23. note over Alice, Bob
  24. <w:#FF33FF>This is hosted</w> by sourceforge.jpg
  25. end note

时序图 - 图16

分隔符

在 UML 图中,可以通过 == 关键词来将时序图分割成为多个逻辑步骤:

  1. == 初始化 ==
  2. Alice -> Bob: 认证请求
  3. Bob --> Alice: 认证响应
  4. == 重复 ==
  5. Alice -> Bob: 认证请求
  6. Alice <-- Bob: 认证响应

时序图 - 图17

引用

可以在图中通过使用 ref over 关键词来实现引用:

  1. participant Alice
  2. actor Bob
  3. ref over Alice, Bob : init
  4. Alice -> Bob : hello
  5. ref over Bob
  6. This can be on
  7. several lines
  8. end ref

时序图 - 图18

延迟

在 UML 时序图中可以使用… 来表示延迟,并且还可以给延迟添加注释。

  1. Alice -> Bob: 认证请求
  2. ...
  3. Bob --> Alice: 认证响应
  4. ...5分钟后...
  5. Bob --> Alice: 再见!

时序图 - 图19

空间控制

在 UML 时序图中,我们可以通过 ||| 来增加调用链之间的空间,还可以使用数字指定增加空白空间的大小。

  1. Alice -> Bob: message 1
  2. Bob --> Alice: ok
  3. |||
  4. Alice -> Bob: message 2
  5. Bob --> Alice: ok
  6. ||100||
  7. Alice -> Bob: message 3
  8. Bob --> Alice: ok

时序图 - 图20

生命周期控制

关键字 activate 和 deactivate 用来表示参与者的生命周期。一旦参与者被激活,它的生命线就会显示出来。同时,destroy 表示一个参与者的生命线的终结。

  1. participant User
  2. User -> A: DoWork
  3. activate A
  4. A -> B: << createRequest >>
  5. activate B
  6. B -> C: DoWork
  7. activate C
  8. C --> B: WorkDone
  9. destroy C
  10. B --> A: RequestCreated
  11. deactivate B
  12. A -> User: Done
  13. deactivate A

时序图 - 图21此外,还可以使用嵌套的生命线,并且运行给生命线添加颜色。

  1. participant User
  2. User -> A: DoWork
  3. activate A #FFBBBB
  4. A -> A: Internal call
  5. activate A #DarkSalmon
  6. A -> B: << createRequest >>
  7. activate B
  8. B --> A: RequestCreated
  9. deactivate B
  10. deactivate A
  11. A -> User: Done
  12. deactivate A

时序图 - 图22此外,也可以使用自动激活关键字(autoactivate),这需要与 return 关键字配合:

  1. autoactivate on
  2. alice -> bob : hello
  3. bob -> bob : self call
  4. bill -> bob #005500 : hello from thread 2
  5. bob -> george ** : create
  6. return done in thread 2
  7. return rc
  8. bob -> george !! : delete
  9. return success

时序图 - 图23其中,新命令 return 可以用于生成一个带有本文标签的返回信息,返回的点是当前最近的生命周期线。

创建参与者

我们可以把关键词 create 放在第一次接收消息之前,来强调本次消息实际上是在创建新的对象。

  1. Bob -> Alice : hello
  2. create Other
  3. Alice -> Other : new
  4. create control String
  5. Alice -> String
  6. note right : You can also put notes!
  7. Alice --> Bob : ok

时序图 - 图24

激活、撤销和创建的快捷语法

在指定目标参与者之后,可以使用如下语法:

  • ++ 激活目标(可选择在后面增加 #color)
  • — 撤销激活源
  • ** 创建目标实例
  • !! 摧毁目标实例
    1. alice -> bob ++ : hello
    2. bob -> bob ++ : self call
    3. bob -> bib ++ #005500 : hello
    4. bob -> george ** : create
    5. return done
    6. return rc
    7. bob -> george !! : delete
    8. return success
    时序图 - 图25此外,我们还可以在同一行同时进行激活和撤销:
    1. alice -> bob ++ : hello1
    2. bob -> charlie --++ : hello2
    3. charlie --> alice -- : ok
    时序图 - 图26

    进入和发出消息

    如果只想关注部分图示,你可以使用进入和发出箭头。
    使用方括号 [和] 表示图示的左、右两侧。
    1. [-> A: DoWork
    2. activate A
    3. A -> A: Internal call
    4. activate A
    5. A ->] : << createRequest >>
    6. A<--] : RequestCreated
    7. deactivate A
    8. [<- A: Done
    9. deactivate A
    时序图 - 图27

    锚定和持续时间

    使用 teoz 可以在 UML 图表中添加锚定,从而指定持续时间。
    1. !pragma teoz true
    2. {start} Alice -> Bob : start doing things during duration
    3. Bob -> Max : something
    4. Max -> Bob : something else
    5. {end} Bob -> Alice : finish
    6. {start} <-> {end} : some time
    时序图 - 图28

    包裹参与者

    在 UML 流程图中,可以使用 box 和 end box 画一个框将相关的参与者包裹起来,此外,还可以针对 box 添加标题以及背景颜色。
    1. box "Internal Service" #LightBlue
    2. participant Bob
    3. participant Alice
    4. end box
    5. participant Other
    6. Bob -> Alice : hello
    7. Alice -> Other : hello
    时序图 - 图29

    移除参与者下方显示

    在 UML 图中,我们可以使用 hide footbox 关键词移除参与者在底部显示对应的信息:
    1. hide footbox
    2. box "Internal Service" #LightBlue
    3. participant Bob
    4. participant Alice
    5. end box
    6. participant Other
    7. Bob -> Alice : hello
    8. Alice -> Other : hello
    时序图 - 图30

    外观参数

    在 UML 图中,可以使用 skinparam 改变字体和颜色,示例如下:
    1. skinparam sequenceArrowThickness 2
    2. skinparam backgroundColor #EEEBDC
    3. skinparam handwritten true
    4. skinparam roundcorner 20
    5. skinparam maxmessagesize 60
    6. skinparam sequence {
    7. ArrowColor DeepSkyBlue
    8. ActorBorderColor DeepSkyBlue
    9. LifeLineBorderColor blue
    10. LifeLineBackgroundColor #A9DCDF
    11. ParticipantBorderColor DeepSkyBlue
    12. ParticipantBackgroundColor DodgerBlue
    13. ParticipantFontName Impact
    14. ParticipantFontSize 17
    15. ParticipantFontColor #A9DCDF
    16. Participant underline
    17. ActorBackgroundColor aqua
    18. ActorFontColor DeepSkyBlue
    19. ActorFontSize 17
    20. ActorFontName Aapex
    21. }
    22. actor User
    23. participant "First Class" as A
    24. participant "Second Class" as B
    25. participant "Last Class" as C
    26. User -> A: DoWork
    27. activate A
    28. A -> B: Create Request
    29. activate B
    30. B -> C: DoWork
    31. activate C
    32. C --> B: WorkDone
    33. destroy C
    34. B --> A: Request Created
    35. deactivate B
    36. A --> User: Done
    37. deactivate Askinparam sequenceArrowThickness 2
    38. skinparam roundcorner 20
    39. skinparam maxmessagesize 60
    40. skinparam sequenceParticipant underline
    41. actor User
    42. participant "First Class" as A
    43. participant "Second Class" as B
    44. participant "Last Class" as C
    45. User -> A: DoWork
    46. activate A
    47. A -> B: Create Request
    48. activate B
    49. B -> C: DoWork
    50. activate C
    51. C --> B: WorkDone
    52. destroy C
    53. B --> A: Request Created
    54. deactivate B
    55. A --> User: Done
    56. deactivate A
    时序图 - 图31

    完整示例

    ``` skinparam sequenceArrowThickness 2 skinparam backgroundColor #EEEBDE skinparam handwritten false skinparam roundcorner 20 skinparam maxmessagesize 60 skinparam sequence { ArrowColor DeepSkyBlue ActorBorderColor DeepSkyBlue LifeLineBorderColor blue LifeLineBackgroundColor #A9DCDF ParticipantBorderColor DeepSkyBlue ParticipantBackgroundColor DodgerBlue ParticipantFontName Impact ParticipantFontSize 17 ParticipantFontColor #A9DCDF Participant underline ActorBackgroundColor aqua ActorFontColor DeepSkyBlue ActorFontSize 17 ActorFontName Aapex }

actor 研发 as RD participant “使用入口” as Entry participant “接入层” as Web participant “底层测试能力服务\n用例执行平台” as Engine

== 测试能力选择 == RD -> Entry: 查询QA测试能力列表 activate Entry Entry -> Web: 查询QA测试能力列表 activate Web return 测试能力列表 return 测试能力列表

RD -> RD: 选择对应测试能力

RD -> Entry: 查询测试能力参数可选项 activate Entry Entry -> Web: 查询测试能力参数可选项 activate Web Web -> Engine: 查询测试能力参数可选项 activate Engine return 参数可选项 return 参数可选项 return 参数可选项

RD -> RD: 填写对应的测试任务执行参数

== 测试能力执行 == RD -> Entry: 发起测试任务 activate Entry Entry -> Web —: 发起测试任务 activate Web

group 执行测试任务 loop Web -> Engine: 发起任务并训轮查询测试任务结果 activate Engine return 任务结果

  1. Web -> Engine: 发起任务并训轮查询测试任务结果
  2. activate Engine
  3. return 任务结果
  4. end

end deactivate Web

RD -> Entry: 查询测试任务结果 activate Entry Entry -> Web: 查询测试任务结果 activate Web return 测试任务结果及详情链接 return 测试任务结果及详情链接

RD -> Engine: 查询测试过程详情日志与部分报告等 return ``` 时序图 - 图32