如何编写一个zrlog插件
背景
插件(Plugin),在很多系统中都会有这样的关键字,或许这样会让个系统不是简单CRUD操作。特别是 wordpress, emlog 这样的cms。或许Java本身的特点(企业应用开发,不需要太多灵活的东西)。做起插件这种东西来并不是那么容易。网上找相关的实现更是少的可怜。Java在cms这方面并没有像dz,phpwind,wordpress,织梦等 这么受广大站长欢迎的程序。
想法
Java本生特点
Java运行的是需要将.java
文件编译为.class
文件。所有就有了一些说法是.class
是伪机器码,这样就会失去了一些灵活性,不让像php
这些语言可以马上的看到变更后效果。而对应插件来言这样种效果有显得格外的重要了。比如绑定了一个 /admin/plugin/first
的路由。php 可以轻松的关闭这个路由,而Java呢?首先在tomcat这类容器启动的时候就已经把路由加载完了。想再去通过程序去控制路由会变得相当的复杂。
J2ME
或许第一款手机不是android
,苹果
喜欢玩手机的朋友都或多或少都知道这个名词吧,影响比较深的是想在一个软件中启动另外一个软件是多么困难,而插件呢?当时记得用过最多的浏览器是UC(感觉就是比默认的浏览器好看很多),而当时的UC也只是有一个主题中心的东西。反而是mrp
做到了(参见冒泡的应用中心)。
Eclipse & OSGi
Eclipse 这个词或许对于Javaer都不陌生,甚至有些的C/C++的程序员都在使用。Eclipse就是一个Java中做插件做的比较牛逼的。有人说MyEclipse就是装了一大堆插件Eclipse。然而Eclipse 这样强大的插件模式对 OSGi 的一种实现
OSGi (Open Service Gateway Initiative)技术是Java动态化模块化系统的一系列规范,由于这种东西并不几句化就可以说通的。目前我理解到的OSGi还只是局限与将一段的代码打包到一个 war,jar,ear 中。对这方面很感兴趣的可以看下 《Java应用架构设计 - 模块化模式与OSGi》 这本书。
既然不容易的实现,还要实现?答案当然肯定的,不然就不会有下面这些内容了。
实现
既然对OSGi的理解还仅仅的局限打包,那么估计要让一个初学者也体会到OSGi的强大会更加的困难。这样并不利于一个需要快速开发的插件。结合自己对OSGi已有的理解倒腾出zrlog插件的第二版本。
细节
jar & war
将项目打jar而不是war包。war自己能控制太少了,而却这个还完完全全的的运行在web容器中。于是使用 jar的方式。
插件核心服务
Socket
插件集中化管理,这里插件与核心服务通信使用TCP长连接做消息通知。这里plugin-core将会占用2个端口,一个用于处理zrlog发起的Http请求。另个用于管理插件和通知插件,以及中转服务。
当然大多时候插件不用关心TCP连接的创建和销毁,可以理解为J2EE中的web容器,编写对应路由代码就可以了。
命名空间
nampspace,插件的唯一标示,及在 plugin.properties
里面 shortName
这个key对应的value。不要使用中文,中文有时候会带来无故的编码问题,比如 shortName
的值是 first 那么 /admin/plugin/first/*
就会路由给这个插件,当然可以通过 path
将有的路由公开。这样 /p/first/*
/plugin/first/*
的请求也将路由给这个插件
静态资源和页面渲染
页面渲染目前提供了Freemarker,Jtwig。后期将会支持 beetl。关于静态资源的判定是根据请求中包含 .
将会被标示一个文件,这个只需要将文件放到对应目录下面就可以了。
插件安全
由于在插件核心绑定了TCP端口,程序将绑定的端口绑定的网卡设置为 127.0.0.1
不通过代理工具公开这些端口是不可能在外网访问到的,当然每次创建的端口都是随机的(一个服务器可以运行多个博客程序)。对于没有通过 path
单独添加的路径,都检查是否登录。
关于权限
public enum ActionType {
INIT_CONNECT(0, "插件初始化"),
HTTP_FILE(0, "获取HTTP资源文件"),
HTTP_METHOD(0, "处理HTTP请求方法"),
GET_WEBSITE(0, "读取数据到website表中"),
SET_WEBSITE(0, "保存数据到website表中"),
PLUGIN_START(0, "插件启动"),
PLUGIN_STOP(0, "插件停止"),
PLUGIN_INSTALL(0, "安装插件"),
PLUGIN_UNINSTALL(0, "卸载启动"),
SERVICE(1, "注册服务,调用其他服务"),
ADD_COMMENT(1, "添加文章评论"),
DELETE_COMMENT(1, "删除文章评论"),
GET_DB_PROPERTIES(1, "读取程序数据库配置文件"),
HTTP_ATTACHMENT_FILE(0, "响应HTTP附件"),
LOAD_PUBLIC_INFO(0, "读取程序公开信息");
private int level;
private String desc;
private ActionType(int level, String desc) {
this.level = level;
this.desc = desc;
}
}
插件调用level不为0的请求将会获取用户同意后才进行处理(未完成),及0为基础权限。需要更多交互需要扩充这些枚举,在plugin-core编写对应的方法参才可以
内存使用
由于每个插件都是单独启动的JVM,如果不对使用内存量进行控制,很容易在系统资源将耗尽的时候程序被关闭。于是jar文件在被加载时通过启动参数 -xmx16m -xms4m
进行限制,及单个插件能最多使用16m的内存
开发环境&运行环境
为了方便开发,于是多提供了一个开发环境,这个环境的值是有INIT_CONNET完成后确定的,环境状态控制通过 plugin-core 控制。当部分情况与运行环境有差异的时候通过这个参数进行判定。
日志&控制台
程序所有输出将会在plugin-core进行输出,方便开发,日志工具选择自己经常使用的就可了。当然也可以使用 LoggerUtil
进行记录。
打包
推荐使用Maven构建项目,这样就方便打包为 jar 文件。
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/templates/**</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<encoding>UTF-8</encoding>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.5.5</version>
<configuration>
<archive>
<manifest>
<mainClass>com.fzb.zrlog.plugin.mail.Start</mainClass>
</manifest>
</archive>
<finalName>mail</finalName>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<appendAssemblyId>false</appendAssemblyId>
<outputDirectory>/home/xxx/zrlog-plugin/</outputDirectory>
</configuration>
</plugin>
</plugins>
</build>
mvn 打包命令
mvn clean compile assemby:single
七牛插件代码
具体代码的实现移步到osc@git
https://git.oschina.net/94fzb/zrlog-plugin-qiniu
开发注意事项
- 建议 JDK7+
- 目前静态文件也需要打包到 jar 文件
源码托管
接下来
- 完善插件版本问题
- 控制插件访问ActionType非零的请求
- 整合国产模板引擎 beetl
期待JDK9将会加入的 Jigsaw
。
Reproduced please indicate the author and the source, and error a link to this page.
text link:
/zrlog-plugin-dev.html
