前文我们假想我们有足够多的插件可以选择,那么我们可能无需开发,便可以动态构建出一个应用来。如果现有的插件无法满足需求,那么意味着我们需要二次开发一个插件或者新开发插件。
今日目标
开发一个可以上传和下载的jar包的应用。上传需要用户校验,下载不需要。
为了完成这个功能,我们首先应该思考
显然,user-system 可以满足用户相关的功能,包括注册,登录,权限校验等等。所以这个插件是我们需要依赖的。现在没有一个现成的插件可以完成上传下载jar包,所以我们需要开发一个新的插件完成这部分功能。
开发总体步骤
大致要做如下几个工作:
库表
因为我们会依赖user-system插件,用户相关的工作我们不需要做了。我们只需要两个表:
存储上传文件路径的表:
CREATE TABLE `plugin_store_item` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(256) DEFAULT NULL,
`path` text,
`version` varchar(256) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
上传用户和文件关联表:
CREATE TABLE `plugin_user` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(11) DEFAULT NULL,
`plugin_id` int(11) DEFAULT NULL,
`relate_type` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
假设数据库名叫 ar_plugin_repo
代码开发
安装辅助开发工具:
pip install watchdog requests click uuid sfcli
创建项目:
sfcli create --name ar_plugin_repo
使用idea 打开项目:
idea ar_plugin_repo
打开项目后,你会发现已经有一个脚手架代码,项目有两个子模块:
大致模样是这样的:
web-platform屏蔽了大部分技术细节,你只要继承CustomAction实现里面的run方法,该方法会响应http请求。这里我们提供了图中的两个类分别实现上传和下载。 里面的样子大概是这样的:
class DownloadPluginAction
extends CustomAction
with Logging {
override def run(params: Map[String, String]): String = {
//数据库操作
ctx.run(ctx.query[PluginStoreItem].filter { item =>
item.name == lift(pluginName) && item.version == lift(version)
}).headOption
//下载逻辑
}
}
object DownloadPluginAction {
def action = "downloadPlugin"
def plugin = PluginItem(DownloadPluginAction.action,
classOf[DownloadPluginAction].getName, PluginType.action, None)
}
class 类里面完成具体业务逻辑,object class里则提供该类的描述信息,比如名称,以及插件描述。
项目源码参考这里:
完成DownloadFileAction和UploadFileAction后,我们将他们放到PluginDesc里:
class PluginDesc extends Plugin {
override def entries: List[PluginItem] = {
List(
UploadPluginAction.plugin,
DownloadPluginAction.plugin
)
}
这样,一个插件就算开发了。
比如下载,你可以访问如下地址去下载一个jar包。
http://127.0.0.1:9007/run?action=downloadPlugin&pluginName=user-system&version=1.0.0
web-platform 提供的额外功能
我们现在看看web-platform如何进一步提高你的开发效率的。
sfcli 对项目提供了增量编译和动态热加载的功能。这意味着修改完代码会立刻生效。 先启动增量编译:
sfcli compile --dev true --mvn mvn
大概样子是这样的:
--mvn mvn 指定mvn命令的地址。如果不指定,默认会使用build目录下的mvn。他会自动下载scala发型包以及zinc 编译器。如果你网速快,建议使用build 目录下的mvn,也就是默认的mvn.
接着,可以启动插件了:
sfcli run --dev true --dev mvn
第一次启动时间会略微久。
假设我们修改代码,系统会自动感知,然后重启,这个过程会很快:
如果你想debug,也没有问题,打开idea 的run菜单,里面有个attach进程的选项:
然后会出现一个列表:
选择第一个AppRuntime即可。这个时候就和我们正常的debug一样了。
值得注意的是,当前sfcli还不能自动安装依赖,所以,你需要手动安装下这个插件依赖的其他插件,很简单:
sfcli plugin --add app_runtime_with_db:1.0.0 --token xxxx
sfcli plugin --add user-system:1.0.0 --token xxxxxx
注册下插件需要的数据库(只需要一次):
sfcli add_db --plugin_name user-system \
--host 127.0.0.1 \
--db_name app_runtime_plugin_full \
--user xxxx \
--password xxx \
--token xxxxx
sfcli add_db --plugin_name ar_plugin_repo \
--host 127.0.0.1 \
--db_name app_runtime_plugin_full \
--user xxxx \
--password xxx \
--token xxxxx
发布插件到商店
程序开发完成后,我们需要发布我们的插件到仓库里,一个指令就可以搞定:
sfcli release --deploy store --user xxxxx --password xxxxx --mvn mvn
默认发布到官方仓库里,你也可以发布到自己的私有仓库,将store换成你的仓库地址即可。
mvn install 插件lib库
如果我希望install我们的jar包到本地(尤其是你开发多个插件又有依赖的时候比较管用),你可以这样:
sfcli release --install lib --mvn mvn
这样就会将lib模块自动安装到你本地的.m2里。