PlantUML 预处理指令与图标库

puml.online

写 PlantUML 时,10 张图共用同一套皮肤和图例?预处理指令能让你抽出共用代码。写文档配好看的图标?图标库让图更直观。两件事一起做效率最高。

预处理指令速查

指令 用途
!include <url> 引入外部 PlantUML 文件 / 文本
!includeurl <url> 从 URL 引入
!include_once include 但只在第一次生效
!define <VAR> <value> 定义预处理变量
!function <name>(args) 定义预处理函数
%variable_name 引用预处理变量
%date("format") 当前日期
%dirpath(...) / %filename(...) 文件名相关
!if / !else / !endif 预处理条件
!definelong 跨行定义
%load_json / %load_yaml 读外部 JSON / YAML

1. !include(最常用)

抽共用样式到一个文件:

1
2
3
4
5
6
# source/plantuml/_theme.puml
!define THEME_DARK
skinparam backgroundColor #FAFAFA
skinparam BorderColor #2F4858
skinparam ArrowColor #2F4858
skinparam FontColor #1F2328

主文件用它:

1
2
3
4
5
6
7
8
@startuml
!include /path/to/_theme.puml

class Order
class Product
Order --> Product

@enduml

每次渲染的时候,会自动把 _theme.puml 内容替换进去。

内网部署注意:企业内网访问 GitHub raw URL 会失败,要么本地 vendor,要么用 !include 本地路径。

!include_once vs !include

  • !include 每个 @startuml 段都会加载一次
  • !include_once 在 .puml 文件生命周期内只加载一次

大多数情况用 !include

!include 整段

1
2
3
4
5
6
7
8
9
10
@startuml
!include ../plantuml/c4/C4_Container.puml

Person(user, "用户")
Container(web, "Web", "React")
Container(api, "API", "Go")

Rel(user, web)
Rel(web, api)
@enduml

!include C4-PlantUML 标准库,实现标准化。

!include 文件路径分隔

1
2
!include ../shared/styles.puml
!include ../../c4/C4_Container.puml

2. !define / %variable

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@startuml
!define COLOR_PRIMARY #A31F34
!define COLOR_SUCCESS #20A464
!define COLOR_WARNING #F4B40A

skinparam class {
BackgroundColor %COLOR_PRIMARY
FontColor white
}

class A
class B
A -> B

@enduml

!define 定义一个预处理变量,%variable_name 使用。

多变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@startuml
!define COLOR_PRIMARY #A31F34
!define COLOR_BG #FAFAFA
!define ARROW_WIDTH 2
!define FONT_NAME "PingFang SC"

skinparam {
BackgroundColor %COLOR_BG
ArrowColor %COLOR_PRIMARY
FontName %FONT_NAME
}

class A
A -> B

@enduml

跨行定义 !definelong

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@startuml
!definelong STYLE_CLASS_PRIMARY
skinparam class {
BackgroundColor #A31F34
FontColor white
BorderColor white
}
!enddefinelong

STYLE_CLASS_PRIMARY

class A
class B

@enduml

3. !function(预处理函数)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@startuml
!function $accent($type)
!if ($type == "primary")
!return #A31F34
!else
!return #6B7280
!endif
!endfunction

class A
A -> B : %accent("primary")
A -> C : %accent("warning")

@enduml

!function + !return 创建函数。!if 写条件。

实际例子:状态颜色

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@startuml
!function $status_color($s)
!if ($s == "ok")
!return #20A464
!elseif ($s == "warn")
!return #F4B40A
!elseif ($s == "fail")
!return #DC2626
!else
!return #6B7280
!endif
!endfunction

skinparam class {
BackgroundColor $status_color("ok")
}

class Healthy
@enduml

4. %date / %time

1
2
3
@startuml
title 报告生成于 %date("yyyy-MM-dd HH:mm")
@enduml

%date("...") 用 Java SimpleDateFormat 模式:

模式 输出
yyyy-MM-dd 2026-07-29
yyyy 2026
MM/dd/yy 07/29/26
dd MMM yyyy 29 Jul 2026

标题加日期

1
2
3
4
5
6
7
8
@startuml
title 系统状态 - %date("yyyy-MM-dd")

class Service1
class Service2
class Service3

@enduml

文档每次生成时自动加日期。

5. !if / !endif

1
2
3
4
5
6
7
8
9
10
11
12
13
@startuml
!define DEBUG true

!if (DEBUG == true)
skinparam class {
BackgroundColor #F4B40A
BorderColor #DC2626
}
!endif

class Order

@enduml

!if / !else / !endif 控制哪些行被包含。

多分支

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@startuml
!define THEME "dark"

!if (THEME == "dark")
skinparam BackgroundColor #161B22
skinparam FontColor #E6EDF3
!elseif (THEME == "light")
skinparam BackgroundColor #FAFAFA
skinparam FontColor #1F2328
!else
skinparam BackgroundColor white
skinparam FontColor black
!endif

class Order
@enduml

实战:用命令行切换主题

1
2
3
# Bash 切换主题
plantuml -DTHEME=dark *.puml
plantuml -DTHEME=light *.puml

传给 plantuml.jar 的 -D 定义就会被 !define 读取。

6. %load_json / %load_yaml

读外部数据源:

1
2
3
@startjson
%load_json("data.json")
@endjson

读外部 JSON 文件当 PlantUML 输入。

实际工作流:

1
2
3
4
5
6
# scripts/render.sh
cat <<EOF | java -jar plantuml.jar -pipe >out.svg
@startjson
%load_json("$1")
@endjson
EOF
1
./render.sh config.json

输出的 SVG 把 JSON 渲染成树形图。

图标库(OpenIconic / FontAwesome)

PlantUML 支持工业标准的开源图标库,让类图 / 组件图 / 部署图更具表意力。

OpenIconic

1
2
3
4
5
6
@startuml

class Application <<&person>>
database Database <<&cylinder>>

@enduml

<&<icon_name>> 引用 OpenIconic 图标。常用:

代码 图标
<&person> 用户
<&cog> 齿轮 / 设置
<&lock-locked>
<&check>
<&x>
<&bell>
<&calendar> 日历
<&graph> 图表
<&database> 数据库
<&cloud>
<&bolt> 闪电

完整内置 stereotype

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

class Server <<&server>>
class Database <<&database>>
class Queue <<&queue>>
class Network <<&network>>
class Storage <<&storage>>
class User <<&user>>

@enduml

FontAwesome

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

!include <material/common>
!include <material/server>
!include <material/database>

node "API Gateway" as gw <<$material/server>>
database "Postgres" as db <<$material/database>>

gw --> db

@enduml

!include <material/...>!include <aws/...> 引入图标库。

Material Icon 库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@startuml
!include <material/common>
!include <material/server>
!include <material/database>
!include <material/globe_network>
!include <material/api>

class User <<$material/account>>
class API <<$material/api>>
class Server <<$material/server>>

User --> API
API --> Server

@enduml

<<$material/X>> 用具体的图标作为 stereotype。

AWS / Azure / GCP 图标

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@startuml
!include <aws/common>
!include <aws/Compute/EC2>
!include <aws/Database/RDS>
!include <aws/Networking/ELB>

class WebServer <<$aws_compute_ec2>>
class DB <<$aws_database_rds>>
class LoadBalancer <<$aws_networking_elb>>

WebServer --> DB
LoadBalancer --> WebServer

@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
!include <aws/common>
!include <aws/Compute/EC2>
!include <aws/Database/RDS>
!include <aws/Networking/ELB>
!include <aws/Storage/S3>
!include <aws/Security/Cognito>

actor 用户 <<$material/account>>

cloud "VPC" {
LoadBalancer <<$aws_networking_elb>>

EC2 <<$aws_compute_ec2>>

RDS <<$aws_database_rds>>
}

S3 <<$aws_storage_s3>>
Cognito <<$aws_security_cognito>>

用户 --> Cognito : 认证
用户 --> LoadBalancer : HTTPS
LoadBalancer --> EC2 : HTTP
EC2 --> RDS : SQL
EC2 --> S3 : Static assets

@enduml

自定义 stereotype

1
2
3
4
5
6
7
8
@startuml
skinparam stereotypeCBackgroundColor #FAFAFA

class OrderService <<(Q, #A31F34) Service>>
class PaymentService <<(P, #20A464) Service>>
class UserController <<(C, #F4B40A) Controller>>

@enduml

<<(X, #color) Label>> 自定义 stereotype 颜色。

完整实战:可复用的样式 + 数据驱动图

1
2
3
4
5
6
7
8
9
# _include/puml/style.puml
!define COLOR_PRIMARY #A31F34
!define COLOR_BG #FAFAFA

skinparam {
BackgroundColor %COLOR_BG
BorderColor %COLOR_PRIMARY
ArrowColor %COLOR_PRIMARY
}
1
2
# _include/puml/icons.puml
!include <material/common>
1
2
3
4
5
6
7
8
9
10
@startuml
!include _include/puml/style.puml
!include _include/puml/icons.puml

class OrderService <<$material/server>>
class PaymentService <<$material/server>>

OrderService --> PaymentService

@enduml

CI 渲染:

1
2
3
4
- name: Render diagrams
run: |
# !include 用的是相对路径时,cd 到 source/
find source -name '*.puml' | xargs -I {} java -jar plantuml.jar -tpng {}

反模式

1. 预处理函数逻辑复杂

1
2
3
4
5
6
7
8
9
!function $calc($a, $b)
!if ($a > 100 && $b > 50)
!return $a * $b + 100
!elseif ($a < 0)
!return 0
!else
!return $a + $b
!endif
!endfunction

预处理函数逻辑一长就难调试,简单的颜色选择 / 文本替换用 !define 就够。

2. !include 远程 URL

1
!includeurl https://raw.githubusercontent.com/.../C4_Container.puml

CI 一般会因网络问题失败。本地 vendor。

3. 滥用图标

1
2
3
4
5
6
7
8
9
10
11
class A
class B
class C
class D
class E
<<$material/server>>
<<$material/database>>
<<$material/api>>
<<$material/globe_network>>
<<$material/storage>>
@enduml

类多于图标库能覆盖的范围,图标就重复,反而看起来更乱。

评审 checklist

预处理

  • 复用样式抽到独立文件?
  • 变量命名带语义?COLOR_PRIMARY 而不是 A1
  • !include 用本地路径,避免外网 URL?
  • 条件分支只覆盖必需场景?

图标

  • 图标语义和类业务对得上?
  • 不要同一个图里混用 3 套图标库?
  • 图标风格统一?

一句话总结

预处理 + 图标库 = PlantUML 从「画一遍样式」升级到「模板驱动」。抽共用样式 + 选好图标库 + 写个 render 脚本,整套文档图就一气呵成。

  • 标题: PlantUML 预处理指令与图标库
  • 作者: puml.online
  • 创建于 : 2026-07-29 16:05:00
  • 更新于 : 2026-08-14 21:34:29
  • 链接: https://puml.online/blog/plantuml-preprocessing-icons/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。