如何编写一个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 单独添加的路径,都检查是否登录。

关于权限

  1. public enum ActionType {
  2. INIT_CONNECT(0, "插件初始化"),
  3. HTTP_FILE(0, "获取HTTP资源文件"),
  4. HTTP_METHOD(0, "处理HTTP请求方法"),
  5. GET_WEBSITE(0, "读取数据到website表中"),
  6. SET_WEBSITE(0, "保存数据到website表中"),
  7. PLUGIN_START(0, "插件启动"),
  8. PLUGIN_STOP(0, "插件停止"),
  9. PLUGIN_INSTALL(0, "安装插件"),
  10. PLUGIN_UNINSTALL(0, "卸载启动"),
  11. SERVICE(1, "注册服务,调用其他服务"),
  12. ADD_COMMENT(1, "添加文章评论"),
  13. DELETE_COMMENT(1, "删除文章评论"),
  14. GET_DB_PROPERTIES(1, "读取程序数据库配置文件"),
  15. HTTP_ATTACHMENT_FILE(0, "响应HTTP附件"),
  16. LOAD_PUBLIC_INFO(0, "读取程序公开信息");
  17. private int level;
  18. private String desc;
  19. private ActionType(int level, String desc) {
  20. this.level = level;
  21. this.desc = desc;
  22. }
  23. }

插件调用level不为0的请求将会获取用户同意后才进行处理(未完成),及0为基础权限。需要更多交互需要扩充这些枚举,在plugin-core编写对应的方法参才可以

内存使用

由于每个插件都是单独启动的JVM,如果不对使用内存量进行控制,很容易在系统资源将耗尽的时候程序被关闭。于是jar文件在被加载时通过启动参数 -xmx16m -xms4m 进行限制,及单个插件能最多使用16m的内存

开发环境&运行环境

为了方便开发,于是多提供了一个开发环境,这个环境的值是有INIT_CONNET完成后确定的,环境状态控制通过 plugin-core 控制。当部分情况与运行环境有差异的时候通过这个参数进行判定。

日志&控制台

程序所有输出将会在plugin-core进行输出,方便开发,日志工具选择自己经常使用的就可了。当然也可以使用 LoggerUtil 进行记录。

打包

推荐使用Maven构建项目,这样就方便打包为 jar 文件。

  1. <build>
  2. <resources>
  3. <resource>
  4. <directory>src/main/resources</directory>
  5. <includes>
  6. <include>**/*.properties</include>
  7. <include>**/templates/**</include>
  8. </includes>
  9. </resource>
  10. </resources>
  11. <plugins>
  12. <plugin>
  13. <artifactId>maven-compiler-plugin</artifactId>
  14. <version>3.1</version>
  15. <configuration>
  16. <encoding>UTF-8</encoding>
  17. <source>1.7</source>
  18. <target>1.7</target>
  19. </configuration>
  20. </plugin>
  21. <plugin>
  22. <artifactId>maven-assembly-plugin</artifactId>
  23. <version>2.5.5</version>
  24. <configuration>
  25. <archive>
  26. <manifest>
  27. <mainClass>com.fzb.zrlog.plugin.mail.Start</mainClass>
  28. </manifest>
  29. </archive>
  30. <finalName>mail</finalName>
  31. <descriptorRefs>
  32. <descriptorRef>jar-with-dependencies</descriptorRef>
  33. </descriptorRefs>
  34. <appendAssemblyId>false</appendAssemblyId>
  35. <outputDirectory>/home/xxx/zrlog-plugin/</outputDirectory>
  36. </configuration>
  37. </plugin>
  38. </plugins>
  39. </build>

mvn 打包命令

  1. mvn clean compile assemby:single

七牛插件代码

具体代码的实现移步到osc@git
https://git.oschina.net/94fzb/zrlog-plugin-qiniu

开发注意事项

  • 建议 JDK7+
  • 目前静态文件也需要打包到 jar 文件

源码托管

接下来

  • 完善插件版本问题
  • 控制插件访问ActionType非零的请求
  • 整合国产模板引擎 beetl

期待JDK9将会加入的 Jigsaw

转载请注明作者和出处,并添加本页链接。
原文链接: https://blog.zrlog.com/post/zrlog-plugin-dev