PlantUML 时序图高级用法:fragment、step、ref

puml.online

时序图语法在面试的时候很喜欢问,但能在真实项目里画得让评审看懂——能用得相对少。这篇整理高级语法。

fragment 语法速查(重复一遍)

1
2
3
4
5
6
7
alt / else / end     — 分支
opt / end — 可选块
loop / end — 循环
par / else / end — 并行
critical / option / end — 关键段 + 异常
break / end — 跳出
note / end note — 注释

写「订单支付流程」必带的两三个:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@startuml
title 支付流程

用户 -> 网关: 发起支付
网关 -> 风控: 评估
alt 风险通过
网关 -> 银行: 扣款
critical 失败回滚
网关 -> 银行: 退款
option 退款失败
网关 -> 客服: 人工介入
end option
end critical
网关 --> 用户: 200
else 风险拒绝
网关 --> 用户: 403
end

@enduml

实际练习:时序图 + 类图 + 状态图组合

一个完整的「订单生命周期」用三张图表达:

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
@startuml
actor User
participant "Order Service" as Os
participant "Payment Service" as Ps
participant "Inventory Service" as Is
database "Order DB" as Odb

== 提交订单 ==
User -> Os: POST /orders
Os -> Is: 锁定库存
Is --> Os: ok
Os -> Odb: insert
Odb --> Os: order_id

== 支付 ==
Os -> Ps: pay(order_id)
group payment logic
alt success
Ps -> Odb: update status=paid
else fail
Ps -> Odb: update status=failed
Os -> Is: 解锁库存
end
end

== 通知 ==
Os --> User: 200 + order_id
@enduml

group / end 把一段动作归类,可在评审里被折叠。

ref 和 step

ref 引用别张图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@startuml
title 登录主流程
participant FE
participant API
participant Auth

== 注册 ==
User -> FE: 打开注册页
FE -> API: POST /signup
API -> Auth: 创建用户
Auth --> API: ok
API --> FE: 200

note right of User: 在主流程中已绘制

@enduml

ref over A, B : label 用于指向已经存在的描述:

1
2
3
4
5
6
7
8
9
10
11
@startuml

participant FE
participant API

FE -> API: POST /login
note right of FE: 已被 ref 覆盖
ref over FE : 登录页加载完成
FE -> API: 提交表单

@enduml

step(系统响应延迟)

step 500ms 让 PlantUML 渲染时将箭头延迟一段时间:

1
2
3
4
5
6
7
8
9
@startuml

Client -> Server: 请求
step 500ms
Server --> Client: 200
step 1000ms
Client -> Server: 下一个请求

@enduml

适合画「动画时序图」但博客静态截图看不到效果。

skinparam 在时序图

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
@startuml

skinparam sequence {
ArrowColor #2F4858
ArrowFontColor #1F2328
LifeLineBorderColor #A31F34
LifeLineBackgroundColor #FAFAFA
ParticipantBorderColor #2F4858
ParticipantBackgroundColor #FAFAFA
ActorBorderColor #A31F34
ActorBackgroundColor #FAFAFA
BoxBorderColor #2F4858
BoxBackgroundColor #FAFAFA
FontColor #1F2328
}

actor 用户
participant 网关
participant 后端
database 数据库

用户 -> 网关: 注册
网关 -> 后端: create_user
后端 -> 数据库: INSERT
数据库 --> 后端: ok
后端 --> 网关: 200
网关 --> 用户: 200

@enduml

调成 CRDT 风格:暗底白字 + 红色箭头。

group / box / partition

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@startuml
box "客户端"
participant FE
end box
box "服务端"
participant API
end box
box "数据层"
database DB
end box

FE -> API: HTTP
API -> DB: SQL

@enduml

box ... end box 框住一组对象,便于评审分清楚谁负责什么。

box 内的 partition

1
2
3
4
5
6
7
8
9
10
11
12
13
@startuml

box over 服务端 #FAFAFA
partition API层 {
participant 鉴权
participant 业务
}
partition 数据层 {
database DB
}
end box

@enduml

separator(箭头提示)

自消息(实线 + 空箭头)

1
2
3
4
5
6
7
8
9
10
11
@startuml

actor 用户
participant 浏览器
participant 后端

用户 -> 浏览器: 点击按钮
浏览器 -> 浏览器: 自己校验
浏览器 -> 后端: POST /submit

@enduml

自我调用(自消息)

1
2
3
4
5
6
7
@startuml

class OrderService

OrderService -> OrderService: 处理订单

@enduml

异步消息(虚线 + 实箭头)

1
2
3
4
5
6
7
@startuml

API ->> Queue: 发布事件
Queue ->> Worker: 异步消费
Worker -->> API: ACK

@enduml

->> 实线箭头表示异步发送。
-->> 虚线返回。

删除消息(叉号)

1
2
3
4
@startuml

API ->x Cache: 删除
@enduml

->x 表示消息被丢弃。

multiplicity

1
2
3
4
5
6
7
8
9
10
11
12
@startuml

"用户1" --> "请求1" : msg
"用户2" --> "请求2" : msg
"用户3" --> "请求3" : msg

note right of "请求1"
实际生产中每分钟上千条
多用户并发
end note

@enduml

时序图中其实没法直接表达「多」实例,但通过命名约定表达 multiplicity。

嵌套 alt / par

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@startuml

FE -> API: submit
alt 第一次提交
par
API -> DB: insert
else
API -> Cache: clear
end
else 重试
loop 重试 3 次
API -> DB: update
end
end
@enduml

alt / par / loop 可以嵌套。

实战略招:在文档中嵌入时序图

每篇文章放一段最关键的时序图:

1
2
3
4
5
6
7
8
## 登录接口时序

![login](login.puml)

源码(login.puml):
@startuml
...
@enduml

这样评审者看到渲染 SVG,debug 时能直接复制源文本改改再贴。

反模式

1. 时序图里有「每个人都打一行」

1
2
3
4
5
6
User -> Browser
Browser -> Backend
Backend -> Auth
Auth -> DB
DB -> Auth
@enduml

不写消息和返回的箭头,看起来像流程图,不是时序图。

2. 时序图混用活动图风格

1
2
3
4
if (...) then ...
-> ...
-> ...
@enduml

循环和分支不属于时序图范畴;用活动图。

3. 时序图拉太长

一张时序图最好 5-15 个步骤、3-5 个 lifeline。超过就拆。

4. 时序图没标注角色

1
2
A -> B
B --> C

不画 actor / participant、不用 database / queue,会丢失业务信息。

评审 checklist

  • 所有 lifeline 都命名?
  • 时序图每个调用有返回值?
  • 用了合适的 fragment(alt / par / loop)?
  • 没有用 fragment 表达不属于时序图范畴(活动图)的语义?
  • 总步骤不超过 15 步?
  • 配色跟主题一致(避免白底黑图在暗色主题)?

时序图最佳实践

  1. 每个时序图只回答一个问题:「登录」「支付」「下单」分别一张图。
  2. lifeline 数量 ≤ 5
  3. 消息有明确动词POST /loginlogin 好。
  4. 关键路径用普通箭头,异步用 ->>
  5. 异常路径标红或者注释:评审一眼能看到 error flow。
  6. 导出 SVG 给 PR:SVG 比 PNG 更清晰。
  • 标题: PlantUML 时序图高级用法:fragment、step、ref
  • 作者: puml.online
  • 创建于 : 2026-07-29 15:50:00
  • 更新于 : 2026-08-14 21:34:29
  • 链接: https://puml.online/blog/plantuml-ie-macro/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。