一般动作
登录
Wiki: BROPEN ▼: Document Index
»
Space: FAQ ▼: Document Index
»
Page: 应用与插件自动升级机制说明
搜索
zh
页面动作
导出 ▼: 以PDF格式导出 以RTF格式导出 以HTML格式导出
更多动作 ▼: 打印预览 察看源码
欢迎进入Wiki » FAQ » 应用与插件自动升级机制说明?

# 应用与插件自动升级机制说明?

在2015-08-08 19:04上被李小翔修改
评论 (0) · 附件 (0) · 记录 · 信息

供稿人：张文秀

插件或应用更新后，经常需要修改老的数据或数据库结构、新增基础数据（如配置、数据字典）等，部署到服务器时，为了实现自动化升级，我们通常在 XxxxBootStrap.groovy 中实现数据的升级，但是，通过 BootStrap 升级存在下面的问题：

1. 运行时间晚于 Grails 的数据库结构升级，因此，无法提前对数据进行预处理
2. 升级代码需要写很多判断条件（如XX不存在、则新增XX），影响每次启动性能
3. 升级代码容易变得过长，不易维护
4. 升级代码的版本不好控制
5. 如果中间升级失败，不易回滚、定位、重新执行

因此，在 BroFramework 中，新增了一种 Updater 的 Artefact，用于编写代码自动升级；并且将每次升级的插件名、应用名、版本号、升级成功与否等信息记录在数据表 brofwk_update_log 中。

以插件 BroBPM 为例，插件的 grails-app\conf\ 目录下有一个 update 文件夹，包下有多个前缀为 “Updater” 的 groovy 文件，分别是 UpdaterXXXInitiator 和 UpdaterXXX，升级的代码主要写在这些文件。

此外，子文件夹 resource 下面又存放了一些脚本，这些脚本会在 UpdaterXXXInitiator 和 UpdaterXXXX 中被调用执行；这些资源并不是必要的，而是根据情况自行添加、调用。

除了类名前缀外，这些升级器类的属性、方法规范如下面的模板所示：

class UpdaterXxxx {
def initiator = true/false
def version = "4.1.0.92940"
def pluginName = "broBpm"
def description = "......"
def beforeDbUpdate( Sql sqlInst, String dbName, String dbSchema ) {
....
}
def beforeDbUpdate_auditlog( Sql sqlInst, String dbName, String dbSchema ) {
....
}
def beforeBootStrap() {
....
}
def afterBootStrap() {
....
}
}

属性：

- initiator：是否为始化版本
  每个应用或插件中只允许有一个 true 的升级器，类名我们通常命名为 UpdaterXXXInitiator，该升级器中主要是一些基础数据初始化代码，并且只是在应用第一次启动的时候执行一次，之后启动就不会再执行。
- version：升级器的版本号
  格式为不超过四段的数字，如 w.x.y.z、x.y，前三段每段最多3个字符、最后一段最多10个字符，共22个字符。
  目前版本号组成是插件自己的版本号+svn版本号，假如你做了一个新功能，在升级的时候需要初始化一个新的系统参数，比如BPM的版本是4.1.0，提交了代码之后查看svn版本是92940，此时UpdaterXXX版本号就要更新为 4.1.0. 92940。
  版本号是-1 时则禁用，需要注意的是，如果修改了升级器类，则必须升级 version，否则新的升级代码在启动时不会被执行的。
- pluginName：插件名称
  默认为 app_应用名，即不属于任何插件
- description：升级器描述

事件：

- beforeDbUpdate( Sql sqlInst, String dbName, String dbSchema )
  在 Grails 自动更新数据库表结构前执行的。
  此方法支持多数据源，beforeDbUpdate 表示更新默认数据源，beforeDbUpdate_auditlog 表示更新名为 auditlog 的数据源，这个是和dataSource中数据源的配置是类似的。
  参数Sql sqlInst已初始化的数据库连接，用来执行sql；参数String dbName数据库名称，如数据库是oracle则这个参数的值是oracle，因为不同数据库的sql有差异，通过这个参数就可以判断不同数据库的时候执行不同的sql；参数String dbSchema数据库名，用于拼sql，如表名前缀：select * from ${dbSchema}.abc。
- beforeBootStrap()
  在所有的 BootStrap 类和 bootStrapInit 方法之前执行
- afterBootStrap()
  在所有的 BootStrap 类和 bootStrapInit 方法之前执行

下面是一个初始化升级器的示例：

package update
class UpdaterAppInitiator {
def initiator = true
def version = "1.0.0.1234"
def description = "初始化应用 Foobar，版本 1.0"
def settingService
def beforeBootStrap() {
settingService.create("foobar.foo.bar", ....).save()
....
}
}

下面是一个非初始化的升级器的示例：

package update
class UpdaterApp11 {
def version = "1.1.0.12345"
def description = "版本 1.0 到 1.1 的升级器"
def beforeDbUpdate( Sql sqlInst, String dbName, String dbSchema ) {
try {
if ( dbName == "oracle" ) {
sqlInst.executeUpdate("ALTER TABLE ...")
} else {
sqlInst.executeUpdate("ALTER TABLE ...")
}
} catch(Exception e) {}
}
def beforeDbUpdate_xxxx( Sql sqlInst, String dbName, String dbSchema ) {
....
}
def beforeBootStrap() {
if ( Xxxx.countByXX() == 0 ) {
new Xxxx(....).save()
}
if ( .... ) {
....
}
}
}
标签： BroFramework
在2015-08-08 19:04上被李小翔创建

- 评论 （0）
- 附件 （0）
- 记录
- 信息

# 快速链接

- 首页
- 新闻动态
- FAQ

Copyright © 2013 北京博瑞开源软件有限公司
京ICP备12048974号