【技术讲堂】
Sublime + PlantUML
程序猿专属画图工具
什么是 PlantUML
PlantUML 是一个画图脚本语言,用它可以快速地画出:
-
时序图
-
用例图
-
类图
-
活动图
-
对象图
-
状态图
-
组件图
简单地讲,我们使用画图工具时需要一个一个图去画,但使用 PlantUML 只需要用简洁直观的文字表达出图的内容,然后就可以直接生成图片。看一个最简单的例子:
@startuml
业务Service -> 权限Sevice: 调用用户登录接口
业务Service <- 权限Sevice: 返回用户登录令牌
@enduml
效果如下:
简单的时序图例子
软件安装与配置(下面例子以MacOS为例说明)
Sublime
Sublime 是个强大的可扩展的文本编辑器。进入官网下载对应操作系统下的版本安装即可。这个过程及其简单,并且教程网上一搜一大把,不进一步说明。
graphviz
graphviz 是个开源的图片渲染库。安装了这个库才能在操作系统下实现把 PlantUML脚本转换为图片。使用以下命令安装命令:
brew install graphviz
如果mac系统还没有安装homebrew,需要先安装homebrew,安装homebrew方法:
/usr/bin/ruby -e "$(curl -fsSLhttps://raw.githubusercontent.com/Homebrew/install/master/install)"
PlantUML for Sublime 插件
有了PlantUML for Sublime 插件后,我们就可以在 Sublime 里写PlantUML 脚本,然后直接通过一个快捷键生成图片。安装步骤如下:
-
下载插件,并解压;
-
通过 Preferences -> Browse Packages … 打开 sublime 的 Packages 目录,解压后的插件放在 Packages 目录下;
-
重启 Sublime。
为了简化使用,可以在 Sublime 里配置个快捷键。打开 Preferences -> Key Binding - User,添加一个快捷键:
{ "keys": ["alt+d"],"command": "display_diagrams"}
上面的代码配置成按住 Option + d 来生成 PlantUML 图片,你可以修改成你自己喜欢的按键。
查看效果
打开sublime,新建一个空的文件,加入以下内容:
@startuml
业务Service -> 权限Sevice: 调用用户登录接口
业务Service <- 权限Sevice: 返回用户登录令牌
@enduml
在sublime窗口中按下快捷键[Option + d],应该就能够看到生成的时序图。效果如下图所示:
PlantULM 快速入门
plantUML的官方网址提供了我们需要的所有资料。大家可以看看官网的样子。
特地给官网截个图放在这儿,是想告诉大家进入这个网站后请不要怀疑是否进了钓鱼网站。虽然这个网站看上去有着浓浓的山寨风和厚重的历史感,但是的确是我们需要的plantUML的官网。这儿提供了权威的官方文档,这个文档不仅仅是入门指南,里面更是详细描述了plantUML的语法,提供了丰富的例子,我们在日常画图时肯定会需要随时查阅。
时序图举例
最简单的时序图例子前面已经已经看过了,下面举一个实际情况中更有意义的例子。
样例代码
这个例子假想了用户通过app挂号的场景。
-
用户:代表使用app挂号的人
-
APP:代表手机端应用或者微信小程序
-
业务Service:代表我们业务服务,这里包含了挂号业务的最基本逻辑
-
HIS:医院信息系统,是实际执行医院挂号的操作,我们的业务服务需要调用HIS来执行真正的挂号
-
基础服务:是我们这个假想场景的一系列微服务中的一个环节,在我们的假想场景中,基础服务为各个业务服务提供基础的支撑功能
-
统一支付中心:可以立即为封装了支付宝支付、微信支付、银联支付的一个微服务节点
@startuml skinparam dpi 300 title 支付、挂号正常流时序图 actor 用户 activate APP 用户 -> APP : 用户挂号 activate 业务Service APP -> 业务Service : 挂号申请(token, 诊所,科室,医生,号段,身份证) activate HIS 业务Service -> HIS : 获取病人信息 业务Service <- HIS : 返回病人信息 业务Service -> 业务Service : 生成挂号记录即社康订单(保存患者ID,诊所,科室,医生,号段,患者身份证, 挂号费用等信息) deactivate HIS activate 基础服务 业务Service -> 基础服务 : 创建订单(参数:挂号记录完整信息)
基础服务 -> 基础服务 : 新建订单, 生成订单号 activate 统一支付中心 基础服务 -> 统一支付中心 : 支付下单(b2c/pay/consume/order/pay) 基础服务 <- 统一支付中心 : 下单成功,返回收银台URL
基础服务 -> 基础服务 : 订单置为待支付,记录统一支付中心订单号 业务Service <- 基础服务 : 返回收银台URL和基础服务订单号 APP <- 业务Service : 返回收银台URL和挂号记录ID deactivate 业务Service APP -> APP : 跳转到收银台URL 用户 -> APP : 用户选择支付方式,输入密码支付 ...等待统一支付中心的异步支付结果通知... 基础服务 <- 统一支付中心 : 支付成功通知 基础服务 -> 基础服务 : 订单置为支付成功 基础服务 -> 基础服务 : MQ中放置消息 activate 业务Service alt 检测到支付成功的消息 业务Service -> 业务Service : MQ合法性检查(挂号记录是否是等待支付状态等) activate HIS 业务Service -> HIS : 挂号(患者ID,身份证,日期,号源编码,挂号费,诊疗费,其他费,支付方式,交易流水号即基础服务生成的订单ID等参数) 业务Service <- HIS : 挂号结果(结果,科室,医生,就诊地点,候诊编码,医院交易流水号,就诊序号等) deactivate HIS 业务Service -> 基础服务 : 更新医院交易流水号 业务Service <- 基础服务 : 返回更新医院交易流水号结果 end alt APP -> 业务Service : 根据挂号记录ID查询挂号结果 APP <- 业务Service : 返回挂号结果 deactivate 基础服务 用户 <- APP : 挂号完成 deactivate APP @enduml
效果预览
时序图关键元素说明
时序图标题
title定义时序图的标题,
title 支付、挂号正常流时序图
对象(Object)
对象表示的是时序图中的参与者,我们的例子中,APP,业务Service,HIS都是时序图中的对象。在plantUML中,时序图最基础的语法就是:
对象A -> 对象B : 消息
符合上述语法的plantUML代码便隐式的定义了对象A、对象B和从对象A到对象B的消息(方法调用), 不需要任何额外的工作。
时序图中Actor(角色)元素
系统角色,可以是人、机器、其他系统、子系统;在时序图中用一个小人来表示。我们的例子中,就是【用户】。
生命线(Lifeline)
在时序图中表示为从对象图标向下延伸的一条虚线,表示对象存在的时间。
控制焦点或者生命线激活(Focus of Control or Activation)
又称为激活期,表示时间段的符号,在这个时间段内对象将执行相应的操作,用小矩形表示。使用plantUML语言,就是对生命线进行激活:
activate 业务Service
激活期结束后,使用deactivate结束控制焦点:
deactivate 业务Service
消息(Message)
消息一般分为同步消息(Synchronous Message),异步消息(AsynchronousMessage)和返回消息(Return Message)。
-
消息的发送者把控制传递给消息的接收者,然后停止活动,等待消息的接收者放弃或者返回控制。用来表示同步的意义;
-
消息发送者通过消息把信号传递给消息的接收者,然后继续自己的活动,不等待接受者返回消息或者控制。异步消息的接收者和发送者是并发工作的。
-
返回消息表示从过程调用返回。
在plantUML中,消息调用的例子如下:
-
对象A向对象B发送消息M:
对象A -> 对象B :消息M
-
对象B向对象A发送消息M(等价于对象B向对象A返回消息M):
对象A <- 对象B :消息M
-
对象A调用自己:
对象A -> 对象A :消息M
用例图举例
样例代码
@startuml skinparam dpi 300 left to right direction skinparam packageStyle rectangle actor customer actor clerk rectangle checkout { customer -- (checkout) (checkout) .> (payment) : include (help) .> (checkout) : extends (checkout) -- clerk } @enduml
这段样例代码的展示效果如下:
简单解释
用例
使用括号 (xxx) 来表示用例,用例用椭圆形表达。
角色
两种方式定义角色:
-
使用 actor 来定义参与者
-
两个冒号包围的对象作为角色
角色定义的例子:
@startuml
:First Actor:
:Another\nactor: as Men2
actor Men3
actor :Last actor: as Men4
@enduml
效果如下:
用例描述
用例描述使用双引号(“”)括起来,这几种符号用于分割换行:–.. == __.。不废话,上代码:
@startuml
usecase UC1 as "You can use
several lines to define your usecase.
You can also use separators.
--
Several separators are possible.
==
And you can add titles:
..Conclusion..
This allows large description."
@enduml
效果:
扩展
使用符号(<|–)来表示用例或者角色的扩展或者继承。代码如下:
@startuml
:Main Admin: as Admin
(Use the application) as (Use)
User <|-- Admin
(Start) <|-- (Use)
@enduml
效果如下:
使用注释
可以使用(note left of , note right of , note top of , note bottom of)这些关键字来定义注释或者标注。代码如下:
@startuml
:Main Admin: as Admin
(Use the application) as (Use)
User -> (Start)
User --> (Use)
Admin ---> (Use)
note right of Admin : This is an example.
note right of (Use)
A note can also
be on several lines
end note
note "This note is connected\ntoseveral objects." as N2
(Start) .. N2
N2 .. (Use)
@enduml
效果如下:
使用皮肤参数
skinparam命令能够改变绘画的颜色,字体等信息。代码如下:
@startuml
skinparam handwritten true
skinparam actor {
BorderColorblack
FontNameCourier
BackgroundColor<< Human >> Gold
}
skinparam usecase {
BackgroundColorDarkSeaGreen
BorderColorDarkSlateGray
BackgroundColor<<Main >> YellowGreen
BorderColor<<Main >> YellowGreen
ArrowColorOlive
}
User << Human >>
:Main Database: as MySql <<Application >>
(Start) << One Shot >>
(Use the application) as (Use) <<Main >>
User -> (Start)
User --> (Use)
MySql --> (Use)
@enduml
效果如下:
关于skinparam,完整的信息请参考官方网址。
活动图(流程图)举例
plantUML支持两种语法来描述活动图,旧的方式(官方手册第4章 Activity Diagram)更传统,更稳定,已经使用了好久了,但是描述不直观,语法稍显复杂,生成的图不够漂亮。鉴于此,只推荐新的方式,就是官方手册中第5章(Activity Diagram (beta)),尽管写着beta版,我使用新版本时还没有碰到任何问题,实际表现相当稳定,强烈推荐新的活动图描述语法。
基础
活动标签以冒号(:)开始,分号(;)结尾。
开始/结束
关键字start表示活动图开始,关键字stop表示活动图停止,关键字end表示活动图结束。
例子:
@startuml
start
:Hello world;
:This is on defined on
several **lines**;
stop
@enduml
效果:
条件与循环
活动图表示条件的几个关键字:if, then, else, elseif, endif。条件需要使用()括起来。例子:
@startuml
start
if (condition A) then (yes)
:Text1;
elseif (condition B) then (yes)
:Text2;
end
elseif (condition C) then (yes)
:Text3;
elseif (condition D) then (yes)
:Text4;
else (nothing)
:Textelse;
endif
stop
@enduml
效果:
while循环的例子:
@startuml
while (check filesize ?) is (not empty)
:readfile;
endwhile (empty)
:close file;
@enduml
效果:
常用的设置选项
更改图片的清晰度
默认的dpi非常低,导致图片很模糊,通过设置dpi可以大幅度提高图片清晰度。
@startuml
skinparam dpi 300
while (check filesize ?) is (not empty)
:readfile;
endwhile (empty)
:close file;
@enduml
同样是上面循环的例子,感受一下效果:
plantUML的skinparam
dpi是graphviz的参数设置,关于plantUML特有的skinparam参数,完整的信息请参考官方网址。主要能设置字体,背景等信息。
参考文档
本文档很大程度上参考了以下文档,向作者表示感谢!https://www.jianshu.com/p/e92a52770832