openfire插件开发
- 格式:doc
- 大小:95.50 KB
- 文档页数:8
OpenFire源码学习之二十:在openfire中使用redis插件(下)Redis插件实现首先来看下插件目录:RedisServicePlugin源码清单:[java] view plain copyprint?1.import java.io.File;2.import java.sql.Connection;3.import java.sql.PreparedStatement;4.import java.util.Collection;5.import java.util.HashMap;6.import java.util.Map;7.8.import org.jivesoftware.database.DbConnectionManager;9.import org.jivesoftware.openfire.XMPPServer;10.import org.jivesoftware.openfire.container.Plugin;11.import org.jivesoftware.openfire.container.PluginMana ger;12.import org.jivesoftware.util.JiveGlobals;13.import org.jivesoftware.util.PropertyEventDispatcher;14.import org.jivesoftware.util.PropertyEventListener;15.import org.jivesoftware.util.redis.enity.RedisConfig;16.import er;17.import erVcard;18.import org.slf4j.Logger;19.import org.slf4j.LoggerFactory;20.import redis.clients.jedis.Jedis;21.22.public class RedisServicePlugin implements Plugin, Pr opertyEventListener{23.24.private static final Logger log = LoggerFactory.getLog ger(RedisServicePlugin.class);25.26.private static final String OF_REDIS_CONFIG_DELETE = "delete from redisConfiguration";27.private static final String OF_REDIS_CONFIG_INSERT = "INSERT INTO redisConfiguration (name, ip, port, auto) VALUES (?, ?, ?, ?)";28.29.private XMPPServer server;30.private boolean enabled;31.32.@Override33.public void propertySet(String property, Map<String, Object> params) {34.if (property.equals("plugin.redis.enabled")) {35.this.enabled = Boolean.parseBoolean((String)params.g et("value"));36.}37.}38.......39.public boolean isEnabled() {40.return enabled;41.}42.43.public void setEnabled(boolean enabled) {44.this.enabled = enabled;45.JiveGlobals.setProperty("plugin.redis.enabled", enabled ? "true" : "false");46.}47.48.@Override49.public void initializePlugin(PluginManager manager, Fi le pluginDirectory) {50.enabled = JiveGlobals.getBooleanProperty("plugin.red is.enabled", true);51.server = XMPPServer.getInstance();52.PropertyEventDispatcher.addListener(this);53.}54.55.@Override56.public void destroyPlugin() {57.enabled = JiveGlobals.getBooleanProperty("plugin.redis.enabled", false);58.PropertyEventDispatcher.removeListener(this);59.}60.61.public void initializeAllData () {62.Collection<RedisConfig> crcfs = getAllRedisConfig();63.if (!crcfs.isEmpty()) {64.for (RedisConfig rcf : crcfs) {65.if ("REDIS_USER".equals(rcf.getName())) {66.setRedisByUserInfo();67.}68.}69.}70.}71.72.public void saveRedisConfig(Collection<RedisConfig> object) {73.PreparedStatement pstmt = null;74.Connection con = null;75.try {76.con = (Connection) DbConnectionManager.getConnec tion();77.if (object != null) {78.pstmt = con.prepareStatement(OF_REDIS_CONFIG_DE LETE);79.pstmt.execute();80.pstmt = (PreparedStatement) con.prepareStatement(O F_REDIS_CONFIG_INSERT);81.for (RedisConfig cr : object) {82.pstmt.setString(1, cr.getName());83.pstmt.setString(2, cr.getIp());84.pstmt.setString(3, cr.getPort());85.pstmt.setString(4, cr.getAuto());86.pstmt.executeUpdate();87.}88.}89.} catch (Exception e) {(e.getMessage());91. e.printStackTrace();92.}93.finally {94.DbConnectionManager.closeConnection(pstmt, con);95.}96.}97.98.public Collection<RedisConfig> getAllRedisConfig() {99.if (server == null)100.server = XMPPServer.getInstance();101.return server.getJedisConfDao().getAllRedisConfig();102.}103.104.public void setRedisOfflineMessage() {105.XMPPServer.getInstance().getChatMessageJedisPoolM anager().initDataByOfflineMessage();106.}107.108.public void destroyOfflineMessage() {109.Jedis jedis = server.getChatMessageJedisPoolManager ().getJedis();110.jedis.flushDB();111.server.getChatMessageJedisPoolManager().returnRes(j edis);112.}113.114.public void setRedisUserSearch() {115.XMPPServer.getInstance().getRedisSearchManager().cr eateSearchAllUserData();116.}117.118.public void destroyUserSearch() {119.Jedis jedis = server.getRedisSearchManager().getSearc hJedis();120.jedis.flushDB();121.XMPPServer.getInstance().getUserJedis().returnRes(jed is);122.}123.124.public void destroyRedisByUserInfo () {125.Jedis jedis = server.getUserJedis().getJedis();126.Map<String, String > user = jedis.hgetAll("OFUSER:ad min");127.jedis.flushAll();128.jedis.hmset("OFUSER:admin", user);129.XMPPServer.getInstance().getUserJedis().returnRes(jed is);130.}131.132.public void setRedisByUserInfo () {133.Jedis jedis = server.getUserJedis().getJedis();134.int i = 1;135.136.Collection<User> users = server.getUserJedis().getAll User();137.if (!users.isEmpty()) {138.for (User user : users) {139.Map<String,String> map = new HashMap<String, Stri ng>();140.map.put("PASSWORD", user.getPassword());141.if (user.getName() != null )142.map.put("NAME", user.getName());143.if (user.getMoblie() != null )144.map.put("MOBILE", user.getMoblie().trim());145.if (user.getEmail() != null)146.map.put("EMAIL", user.getEmail().trim());147.map.put("CREATIONDATE",user.getCreationDate().trim ());148.map.put("MODIFICATIONDATE",user.getModificationD ate().trim());149.jedis.hmset("OFUSER:" + user.getUsername(), map);150.151.System.out.println("The " + i++ + "user generation=> username:" + user.getUsername() + ", name:" + user.getName() );152.}153.System.out.println("the end:user base info generated... ");154.i = 1;155.156.for (User user : users) {157.if (user.getMoblie() != null && !"".equals(user.getMoblie())) {158.jedis.set("MOBILE:" + user.getMoblie(), user.getUserna me());159.System.out.println("The" + i++ + "user,mobile relation generation=> mobile:" + user.getMoblie() + ", username:" + us er.getUsername());160.}161.}162.System.out.println("the end:user and mobile relation g enerated...");163.i = 1;164.}165.166.Collection<UserVcard> uservcards = server.getUserJe dis().getUserVcard();167.if (!uservcards.isEmpty()) {168.for (UserVcard uv : uservcards) {169.if (uv.getVcard() != null && !"".equals(uv.getVcard())) {170.jedis.set("OFVCARD:" + uv.getUsername(), uv.getVcard ());171.System.out.println("The" + i++ + "user vcard generati on=> username:" + uv.getUsername());172.}173.}174.i = 1;175.System.out.println("the end:user vcard generated...");176.}177.178.server.getUserJedis().returnRes(jedis);179.}180.}RedisUserInfoOpt:[java] view plain copyprint?1.import java.util.HashMap;2.import java.util.Map;3.4.import org.jivesoftware.openfire.XMPPServer;5.import er;6.import org.slf4j.Logger;7.import org.slf4j.LoggerFactory;8.9.import redis.clients.jedis.Jedis;10.11.public class RedisUserInfoOpt {12.13.private static final Logger Log = LoggerFactory.getLog ger(RedisUserInfoOpt.class);14.15.public void setBaseUserInfo(User user) {16.if (user != null) {17.Jedis jedis = XMPPServer.getInstance().getUserJedis(). getJedis();18.19.try {20.Map<String,String> map = new HashMap<String, Stri ng>();21.map.put("PASSWORD", user.getPassword());22.if (user.getName() != null )23.map.put("NAME", user.getName());24.if (user.getMoblie() != null )25.map.put("MOBILE", user.getMoblie().trim());26.if (user.getEmail() != null)27.map.put("EMAIL", user.getEmail().trim());28.map.put("CREATIONDATE",user.getCreationDate().trim ());29.map.put("MODIFICATIONDATE",user.getModificationD ate().trim());30.jedis.hmset("OFUSER:" + user.getUsername(), map);("user generation=> username:" + user.getUs ername() + ", name:" + user.getName());32.} finally{33.XMPPServer.getInstance().getUserJedis().returnRes(jed is);34.}35.}36.}37.38.public void setUserMobile(User user) {39.if (user != null) {40.Jedis jedis = XMPPServer.getInstance().getUserJedis(). getJedis();41.try {42.43.} finally {44.XMPPServer.getInstance().getUserJedis().returnRes(jed is);45.}46.47.}48.}49.}redis-service.jsp[html] view plain copyprint?1.<%@ page import="java.util.*,.jivesoftware.openfire.XMPPServer,.jivesoftware.util.*,.montnets.redis.plugin.RedisServicePlugin,.jivesoftware.util.redis.enity.RedisConfig"6.errorPage="error.jsp"7.%>8.9.<%@ taglib uri="/jstl/core_rt" prefix="c" %>10.<%@ taglib uri="/jstl/fmt_rt" prefix="fmt" %>11.12.<%-- Define Administration Bean --%>13.<jsp:useBean id="admin" class="org.jivesoftware.util. WebManager" />14.<c:set var="admin" value="${admin.manager}" />15.<% admin.init(request, response, session, application, out ); %>16.17.<% // Get parameters18.boolean save = request.getParameter("save") != null;19.String initdata = request.getParameter("initdata");20.String deldata = request.getParameter("deldata");21.boolean success = request.getParameter("success") != null;22.RedisServicePlugin rsp = new RedisServicePlugin();23.Collection<RedisConfig> rcList = rsp.getAllRedisConfi g();24.25.// Handle a save26.Map errors = new HashMap();27.Collection<RedisConfig> rcColl = new ArrayList<Redis Config>();28.29.if ("REDIS_USER".equals(initdata)) {30.rsp.initializeAllData();31.response.sendRedirect("redis-service.jsp?success=true");32.return;33.}34.else if ("REDIS_USER".equals(deldata)) {35.rsp.destroyRedisByUserInfo();36.response.sendRedirect("redis-service.jsp?success=true");37.return;38.}39.......40.if (save) {41.String uname = request.getParameter("REDIS_USER");42.String r_user_name = request.getParameter("REDIS_U SER_IP").trim();43.String r_user_port = request.getParameter("REDIS_USE R_PORT").trim();44.String r_user_auto = request.getParameter("REDIS_USER_AUTO").trim();45.if (r_user_name == null || r_user_port == null) {46.errors.put("uname", "Redis-User is error!");47.}48.else {49.RedisConfig rc = new RedisConfig();50.rc.setName(uname);51.rc.setIp(r_user_name);52.rc.setPort(r_user_port);53.rc.setAuto(r_user_auto);54.rcColl.add(rc);55.}56.......57.String mmname = request.getParameter("REDIS_MUC _MESSAGE");58.String r_mm_name = request.getParameter("REDIS_M UC_MESSAGE_IP").trim();59.String r_mm_port = request.getParameter("REDIS_MU C_MESSAGE_PORT").trim();60.String r_mm_auto = request.getParameter("REDIS_MU C_MESSAGE_AUTO").trim();61.if (r_mm_name == "" || r_mm_port == "") {62.errors.put("mname", "Redis-MUC MESSAGE is error!");63.}64.else {65.RedisConfig rc = new RedisConfig();66.rc.setName(mmname);67.rc.setIp(r_mm_name);68.rc.setPort(r_mm_port);69.rc.setAuto(r_mm_auto);70.rcColl.add(rc);71.}72.73.String omname = request.getParameter("REDIS_OFFLI NE_MESSAGE");74.......75.if (errors.size() == 0) {76.rsp.saveRedisConfig(rcColl);77.response.sendRedirect("redis-service.jsp?success=true");78.return;79.}80.}81.82.%>83.84.<html>85.<head>86.<title>Redis Service Properties</title>87.<meta name="pageID" content="redis-service"/>88.</head>89.<body>90.<% if (!errors.isEmpty()) { %>91.92.<div class="jive-error">93.<table cellpadding="0" cellspacing="0" border="0">94.<tbody>95.<tr>96.<td class="jive-icon"><img src="images/error-16x16.gif" width="16" height="16" border="0" alt=""/></td>97.<td class="jive-icon-label">98.99.<% if (errors.get("uname") != null) { %>100.<%=errors.get("uname") %>101.<% } else if (errors.get("gname") != null) { %>102.<%=errors.get("gname") %>103.<% } else if (errors.get("rname") != null) { %>104.<%=errors.get("rname") %>105.<% } else if (errors.get("mname") != null) { %>106.<%=errors.get("mname") %>107.<% } else if (errors.get("mmname") != null) { %>108.<%=errors.get("mmname") %>109.<% } else if (errors.get("omname") != null) { %>110.<%=errors.get("omname") %>111.<% } else if (errors.get("cmname") != null) { %>112.<%=errors.get("cmname") %>113.<% } %>114.</td>115.</tr>116.</tbody>117.</table>118.</div><br>119.120.<% } %>121.122.<p>123.This is redis plugin124.</p>125.126.<% if (success) { %>127.128.<div class="jive-success">129.<table cellpadding="0" cellspacing="0" border="0"> 130.<tbody>131.<tr><td class="jive-icon"><img src="images/success-16x16.gif" width="16" height="16" border="0"></td> 132.<td class="jive-icon-label">133.redis service properties edited successfully.134.</td></tr>135.</tbody>136.</table>137.</div><br>138.<% } %>139.140.<form action="redis-service.jsp?save=true" method="post">141.142.<fieldset>143.<legend>Redis Service</legend>144.<div>145.<ul>146.<%if (rcList.size() < 1) { %>147.<label for="r_user">REDIS_USER:</label>148.<input type="hidden" id="r_user_name" name="REDI S_USER" value="REDIS_USER"/>149.<input type="text" id="r_user_ip" name="REDIS_USER _IP" size="20" value=""/>150.<label for="r_port">port:</label>151.<input type="text" id="r_user_port" name="REDIS_US ER_PORT" size="5" value=""/>152.<label for="r_auto">auto:</label>153.<input type="text" name="REDIS_USER_AUTO" size=" 10" value=""/>154.<br><br>155.156.<label for="r_user">REDIS_GROUP:</label>157.<input type="hidden" id="r_group_name" name="RE DIS_GROUP" value="REDIS_GROUP"/>158.<input type="text" id="r_group_ip" name="REDIS_GR OUP_IP" size="20" value=""/>159.<label for="r_port">port:</label>160.<input type="text" id="r_group_port" name="REDIS_ GROUP_PORT" size="5" value=""/>161.<label for="r_auto">auto:</label>162.<input type="text" name="REDIS_GROUP_AUTO" size ="10" value=""/>163.<br><br>164.165.<label for="r_user">REDIS_ROSTER:</label>166.<input type="hidden" id="r_roster_name" name="RE DIS_ROSTER" value="REDIS_ROSTER"/>167.<input type="text" id="r_roster_ip" name="REDIS_RO STER_IP" size="20" value=""/>168.<label for="r_port">port:</label>169.<input type="text" id="r_roster_port" name="REDIS_R OSTER_PORT" size="5" value=""/>170.<label for="r_auto">auto:</label>171.<input type="text" name="REDIS_ROSTER_AUTO" size="10" value=""/>172.<br><br>173.174.<label for="r_user">REDIS_MUC:</label>175.<input type="hidden" id="r_muc_name" name="REDI S_MUC" value="REDIS_MUC"/>176.<input type="text" id="r_muc_ip" name="REDIS_MUC _IP" size="20" value=""/>177.<label for="r_port">port:</label>178.<input type="text" id="r_muc_port" name="REDIS_M UC_PORT" size="5" value=""/>179.<label for="r_auto">auto:</label>180.<input type="text" name="REDIS_MUC_AUTO" size=" 10" value=""/>181.<br><br>182.183.<label for="r_user">REDIS_MUC_MESSAGE:</label> 184.<input type="hidden" id="r_mm_name" name="REDI S_MUC_MESSAGE" value="REDIS_MUC_MESSAGE"/> 185.<input type="text" id="r_mm_ip" name="REDIS_MUC _MESSAGE_IP" size="20" value=""/>186.<label for="r_port">port:</label>187.<input type="text" id="r_mm_port" name="REDIS_M UC_MESSAGE_PORT" size="5" value=""/>188.<label for="r_auto">auto:</label>189.<input type="text" name="REDIS_MUC_MESSAGE_AU TO" size="10" value=""/>190.<br><br>191.192.<label for="r_user">REDIS_OFFLINE_MESSAGE:</label>193.<input type="hidden" id="r_om_name" name="REDIS _OFFLINE_MESSAGE" value="REDIS_OFFLINE_MESSAGE"/> 194.<input type="text" id="r_om_ip" name="REDIS_OFFLI NE_MESSAGE_IP" size="20" value=""/>195.<label for="r_port">port:</label>196.<input type="text" id="r_om_port" name="REDIS_OFF LINE_MESSAGE_PORT" size="5" value=""/>197.<label for="r_auto">auto:</label>198.<input type="text" name="REDIS_OFFLINE_MESSAGE _AUTO" size="10" value=""/>199.<br><br>200.201.<label for="r_user">REDIS_CHAT_MESSAGE:</label> 202.<input type="hidden" id="r_cm_name" name="REDIS _CHAT_MESSAGE" value="REDIS_CHAT_MESSAGE"/> 203.<input type="text" id="r_cm_ip" name="REDIS_CHAT_ MESSAGE_IP" size="20" value=""/>204.<label for="r_port">port:</label>205.<input type="text" id="r_cm_port" name="REDIS_CH AT_MESSAGE_PORT" size="5" value=""/>206.<label for="r_auto">auto:</label>207.<input type="text" name="REDIS_CHAT_MESSAGE_A UTO" size="10" value=""/>208.<br><br>209.210.<label for="r_user">REDIS_SEARCH:</label>211.<input type="hidden" id="r_rs_name" name="REDIS_ SEARCH" value="REDIS_SEARCH"/>212.<input type="text" id="r_rs_ip" name="REDIS_SEARCH_IP" size="20" value=""/>213.<label for="r_port">port:</label>214.<input type="text" id="r_rs_port" name="REDIS_SEAR CH_PORT" size="5" value=""/>215.<label for="r_auto">auto:</label>216.<input type="text" name="REDIS_SEARCH_AUTO" siz e="10" value=""/>217.<br><br>218.219.<% } %>220.<% if (rcList.size() >= 1) { %>221.<% for (RedisConfig cr : rcList) { %>222.<label for="r_user"><%=cr.getName() %></label> 223.<input type="hidden" name="<%=cr.getName() %>" value="<%=cr.getName() %>"/>224.<input type="text" name="<%=cr.getName() %>_IP" size="20" value="<%=cr.getIp() %>"/>225.<label for="r_port">port:</label>226.<input type="text" name="<%=cr.getName() %>_PO RT" size="5" value="<%=cr.getPort() %>"/>227.<label for="r_auto">auto:</label>228.<input type="text" name="<%=cr.getName() %>_AU TO" size="10" value="<%=cr.getAuto() %>"/>229.<br>230.<input type="button" value="initialize data" onclick=" window.location.href='redis-service.jsp?initdata=<%=cr.getName() %>'; return false;"/> 231.<input type="button" value="destroy data" onclick=" window.location.href='redis-service.jsp?deldata=<%=cr.getName() %>'; return false;"/>232.<br><br>233.<%} %>234.<% } %>235.</ul>236.</div>237.</fieldset>238.239.<br><br>240.241.<input type="submit" value="Save Settings">242.<input type="hidden" name="initdata" value=""/> 243.</form>244.245.</body>246.</html>Plugin.xml[html] view plain copyprint?1.<?xml version="1.0" encoding="UTF-8"?>2.<plugin>3.<class>com.montnets.redis.plugin.RedisServicePlugin</cl ass>4.<name>Redis Service</name>5.<description>Redis distributed cache</description>6.<author>HuWenFeng</author>7.<version>1.3.3</version>8.<date>17/1/2014</date>9.<minServerVersion>3.8.2</minServerVersion>10.11.<adminconsole>12.<tab id="tab-redis" name="Redis" url="redis-service.jsp">13.<sidebar id="sidebar-redis-settings" name="Redis Service" >14.<item id="redis-service" name="Redis Service" url="redis-service.jsp"15.description="Redis distributed cache" />16.</sidebar>17.</tab>18.</adminconsole>19.</plugin>这里只简单贴出了用户这类的相关数据的预加载。
Openfire插件编译及部署插件编译1、编译参数配置打开eclipse或者Myeclipse,点击菜单栏里的run选项,在其下拉菜单中选择External Tools按钮,在它的下一级菜单中点击External Tools Configuration即可进入配置页面。
如图1所示。
图1图2所示为配置页面。
图2选择左侧导航栏中的Ant Build选项,点击新建按钮来新建一个编译配置。
如图3所示。
图3接下来就可以来配置插件的编译参数了。
首先,在Name框中为该编制配置项命名以示区别,如图4所示:图4其次,打开Main选项卡,点击在Buildfile框下面Browse Workspace按钮,来选择用来编译插件的Build文件,它的目录是openfire/build/build.xml。
如图5所示。
图5完成后框内显示数据为“${workspace_loc:/openfire/build/build.xml}”,如图6所示。
图6再填写Arguments框,内容格式为“-Dplugin=XXXX”,其中“XXXX”是我们要编译的插件名。
完成后如图7所示。
图7打开Targets勾选plugin,若编译所有插件就勾选plugins,完成后如图8所示。
图8再打开Common选项卡,设置编译的编码格式一般为UTF_8格式。
完成后如图9所示。
图9最后点击按钮保存设置,点击就可对插件进行编译。
2、检查编译结果当控制台出现编译成功的结果时,即代表编译已经完成,如图10所示。
图10在openfire/target/plugins目录,出现对应的插件jar文件,就代表编译成功了!如图11所示。
图11最后,将编译好的插件jar文件复制出来,以备上传导服务器。
插件部署首先,访问openfire服务器的管理控制台,URL是http://服务器IP:9090。
输入管理员用户名和密码。
如图12所示。
图12登录进入后,选择“插件”网页中机会显示服务器目前所安装的所有插件,如图13所示。
调试、编译开发环境Openfire与安装自己实践:说明:开发环境(IDE):Eclipse3.3.2+JDK1.6+Ant1.7+Openfire_src_3_5_1.zip1.如果代码中使用了importtestng.xxx语句,就需要导入testng-5.8-jdk15.jar类库;2.对于警告信息,是没有关系的。
因为这些警告信息是使用1.5以上版本JDK时候才出现的,使用JDK1.4是不会出现这些警告信息的。
因为这些代码中的有些是使用JDK1.4编写的,而JDK1.4不支持泛型,而JDK1.5和JDK1.6是支持泛型的。
这些警告信息主要是提示将这些非泛型的代码修改为更加高级的方法——泛型,所以这些警告信息是不影响代码结果的。
如果需要修改为泛型也是可以,使用泛型来处理相关的集合类。
3.在使用ant进行编译的时候,在ant视图中可能会出现警告如下信息:taskdefclasscom.install4j.install4jtaskcannotfound这个主要是要安装用来打包Java应用程序的install4j.exe程序,要安装到其默认的安装路径下。
也就是C:\ProgramFiles\目录下即可。
4.在源码里面有一个文件夹里有个打包的图标,双击那个图标,install4j就会读取你在build.xml文件里的信息、在里面完成做界面等打包工作。
编译调试的环境(IDE):Eclipse3.3.2+JDK1.6+Ant(内置)+openfire_src_2008-06-04.zip 在Windows操作系统下编译、调试openfire之前,需要确保HTTPSSL服务已经启动。
否则,会出现各种错误信息。
1.获取Openfire源代码从官方网站上直接下载官方发布版本的源代码openfire_src_2008-06-04.zip源代码压缩包;2.创建openfire工程将openfire_src_2008-06-04.zip解压后,目录下除了READEME.html、LICENSE.html和changelog.html三个网页文件之外,有下面四个子目录。
GMPP协议及其服务器端的Openfire插件开发GMPP背景知识GMPP是一种基于GML的协议,它继承了在GML环境中灵活的发展性。
因此,基于GMPP的应用具有超强的可扩展性。
绊过扩展以后的GMPP可以通过发送扩展的信息来处理用户的需求,以及在GMPP的顶端建立如内容发布系统和基于地址的服务等应用程序。
而且,GMPP包含了针对服务器端的软件协议,使乊能不另一个进行通话,这使得开发者更容易建立客户应用程序戒给一个配好系统添加功能。
GMPP(可扩展消息处理现场协议)是基于可扩展标记语言(GML)的协议,它用于即时消息(IM)以及在线现场探测。
它在促进服务器乊间的准即时操作。
这个协议可能最终允许因特网用户向因特网上的其他任何人发送即时消息,即使其操作系统和浏览器丌同。
GMPP的前身是Jabber,一个开源形式组织产生的网络即时通信协议。
GMPP目前被IETF国际标准组织完成了标准化工作。
标准化的核心绌果分为两部分;核心的GML流传输协议基于GMLFreeEIM流传输的即时通讯扩展应用GMPP的核心GML流传输协议的定义使得GMPP能够在一个比以往网络通信协议更规范的平台上。
借劣于GML 易于解析和阅读的特性,使得GMPP的协议能够非常漂亮。
GMPP的即时通讯扩展应用部分是根据IETF在这乊前对即时通讯的一个抽象定义的,不其他业已得到广泛使用的即时通讯协议,诸如AIM,QQ等有功能完整,完善等先进性。
GMPP的扩展协议Jingle使得其支持语音和视频。
基本网络结构GMPP中定义了三个角色,客户端,服务器,网关。
通信能够在这三者的任意两个之间双向发生。
服务器同时承担了客户端信息记录,连接管理和信息的路由功能。
网关承担着不异构即时通信系统的互联互通,异构系统可以包括SMS (短信),MSN,ICQ等。
基本的网络形式是单客户端通过TCP/IP连接到单服务器,然后在乊上传输GML。
功能传输的是不即时通讯相关的指令。
openfirespark二次开发服务插件==================== 废话begin============================最近老大让我为研发平台增加即时通讯功能。
告诉我用comet 在web端实现即时通讯。
最初狂搜集资料。
不能让自己方向错了。
这是很重要的。
不过还是难免的周折了一番。
测试了一个comet4j的聊天小例子。
用它前后端开发成本太大、对服务器也太大压力放弃了。
最终决定使用openfire +jsjac.js + JabberHTTPBind 然后实现老大要求的web 及时通讯功能。
很庆幸找到了hoojo大哥的demo 很不幸,他为了让大家复制代码,自己练习。
不提供jar包js下载。
(虽然好心但是足足浪费了我两天时间)一个jsjac.js库版本有问题。
很费劲的看源码。
哎。
然后、拿这个小demo 先交差。
顺便展示了spark 和web 聊天窗口,交互即时聊天。
顺便构想了一下,修改openfire用户表。
让用户来自系统。
组织则用自带的。
(当然这是预想。
其实openfire已经帮我们想过了。
)接着、全局搜索了openfire源码中包含ofuser表sql的类。
只有两个类。
很庆幸。
改了之后,改造用户密码加密认证方式。
当然这样做是错误的。
直到我发现类名字似乎有些不对的时候。
DefaultUserProvider 哈哈、嘲讽啊。
不出所料有一个实现类JDBCUuserProvider 。
直接配置就可以搞定、但是加密sha256加密过程和我平台不一样。
改造后就顺利搞定。
接着、到了插件开发过程。
这个过程很烦人。
网上很多帖子很多人去讲这个开发过程。
或许是两三年前的贴了。
很多过时了。
只能有一点帮助。
更多的是走向了错误的道路。
磕磕碰碰。
最终还是只能从源码中寻求出路。
这个过程整整浪费了我两星期时间。
很痛苦。
所以。
我会针对最新代码聊聊,spark 开发一个组织架构树插件。
展示出用户。
并可以与之聊天。
Openfire开发文档修订记录目录1OPENFIRE项目工程搭建及调试 (1)1.1准备工作 (1)1.2解压源码 (1)1.3创建工程 (2)1.4编译 (3)1.5配置调试与运行环境 (5)1.6打包发布 (10)2OPENFIRE代码框架介绍 (10)2.1框架 (11)2.1.1Module (11)2.1.2数据流 (13)2.2O PENFIRE与MIMA (13)2.3M ULTI-U SER-C HAT (14)2.3.1MUCUser (14)2.3.2MUCRole (15)2.3.3MUCRoom (15)2.3.4MultiUserChatServiceImpl (15)2.3.5时序图 (16)2.4P UB-S UB (16)2.4.1Node (16)2.4.2NodeAffiliate (17)2.4.3NodeSubscription (17)2.4.4PubSubModule (17)2.4.5PubSubEngine (18)2.4.6时序图 (18)2.5插件开发 (19)2.5.1注册为组件 (19)2.5.2注册为拦截器 (19)2.5.3注册为IQHandler (20)2.6命名规则 (21)2.6.1XXStarter (21)2.6.2XXListener (21)2.6.3XXDispatcher (21)2.6.4XXPlugin (21)2.6.5XXProvider (21)2.6.6XXHandler (22)2.7系统配置项 (22)2.8系统启动流程 (23)2.9网络处理 (23)2.9.1presence(出席状态)消息处理流程 (23)2.9.2消息监听服务 (25)2.9.3消息封装 (26)2.9.4Openfire消息包接受处理流程 (27)2.10数据库处理 (28)2.10.1Openfire连接数据库修改 (28)2.10.2ConnectionProvider (28)2.10.3处理方式 (28)2.10.4常用类 (28)3OPENFIRE插件开发流程 (29)3.1O PENFIRE P LUGINS加载流程 (29)3.2开发说明 (29)3.2.1总体插件目录结构 (30)3.2.2编写Plugin.xml (30)3.2.3继承Plugin接口 (33)3.2.4插件开发的最优方法 (34)3.2.5JSP页面配置步骤 (34)3.2.6i18n国际化配置 (37)3.2.7Ant build 插件 (38)4OPENFIRE 的CACHE机制 (39)4.1实现机制 (39)1Openfire项目工程搭建及调试Openfire的最新源码3.7.1下源码的运行及打包1.1 准备工作开发工具:Eclipse源码下载:官网地址/downloads/source.jsp,当前最新版本为3.7.1。
O p e n F i r e插件开发基础教程(总3页)-CAL-FENGHAI.-(YICAI)-Company One1-CAL-本页仅作为文档封面,使用请直接删除OpenFire 插件开发基础教程Openfire是一款优秀的XMPP服务器,而且是开放源码的.大家可以根据自己的需求进行二次开发。
二次开发主要有两种方式:1.修改源代码,2开发openfire插件。
从可扩展性上考虑,自然是开发插件是上策,只有插件无法实现时候才会选择修改源代码。
下面就个人经验,说明一下如何开发openfire插件一、环境基础要有一个配置好的openfire开发环境,这个网络上有比较详细的教程了。
比如《源代码导入eclipse中开发配置指南》和《源码部署及运行》,这时候ant应该是可以正常运行的,先执行openfire 【default】,就生成了openfire的目标代码,再执行plugins,就个生成所以系统自带的插件。
二、目录拷贝打开workspace\openfire_src\src\plugins目录,找一个要修改的插件,我选的是subscription,拷贝生成“subscriptionUF”。
打开src目录,里面有两个文件夹,java就是我们要改的源码,而web里面是修改这个插件所要用的web配置页面,目前用不到,直接删除。
三、修改这个一个xml文件,里面的内容就按照自己的样子更改吧。
最关键是确定<class>,插件所在的类名,既然没有web文件夹了adminconsole也全部注释掉吧.四、修改类和类目录修改src/java里面的目录层次,Class和src/java中的路径必须一致。
五、引入openfire项目右击openfire项目,选择New->Source Folder,在Floder name中选择到刚刚新增的插件目录,注意要选到src/java这一层六、修改类文件SubscriptionPluginUF是完全copy SubscriptionPlugin的,因此有两个类名不符的error修改一下.至此,整个openfire已经把我们新加的SubscriptionPluginUF包含在他的plugins中了,通过控制台也能看到一个仿冒的SubscriptionPluginUF插件七、单独编译插件如果每次都运行plugins,生成所有插件的同时生成我们修改的插件,固然可行,就是慢了一点,插件有什么错误也要找半天。
OPENFIRE使用Hazelcast插件进行集群参考资料:
我使用的是openfire3.9.3 ,两台linux,还是一样,直接上图:试了几次终于成功了!
openfire设置的域名要一样,数据库要设置到同一个地方,我的是A服务器的openfire数据库设置为本地的数据库,即数据库地址为localhost(A服务器地址),B服务器的openfire数据库则为A服务器的数据地址。
1.为了提高成功率,我是在openfire部署好之后,进入openfire 后台,分别在插件那栏安装Hazelcast Clustering Plugin ,安装过程全部自动进行,如下图
2. 确认5071端口是否开放了:输入
/sbin/iptables -I INPUT -p tcp --dport 9090 -j ACCEPT;
保存重启:
启动openfire之后,分别编辑Hazelcast插件下面的文件夹中classpath中的hazelcast-cache-config.xml
然后重启openfire,在clustering链接那里启用集群选项,耐心等待,虽然我也不知道结果是什么(这个过程坑爹,说好的30秒左右呢,结果我等了十几分钟还是不行,人与人之间的信任都去哪儿了啊!),因为我是后来想重启openfire的,但是停不掉,最后是杀掉进程的:
然后再输入 kill -9 25526杀掉即可。
分别重启openfire之后,进入控制台,终于看到了我希望看到的结果:
在不同的客户端端登陆不同的IP地址,可以登录上去,也可进行聊天,OK!
就这样吧!。
作用:初始化时在控制台打印测试消息。
开发环境:winxp/myeclipse6.5/jdk1.5&1.6/mysql5.0/openfire3.6.3 QQ群:28588322 (openfire专题研究小组)开发步骤:1. 布署openfire3.6.3源码(请参考openfire3.6.3导入eclipse项目实现方法) 结构如下:2. src/plugins目录下新建文件夹itvi。
并按下图的目录结构新建对应的文件。
plugin.xml文件代码如下:<?xml version="1.0" encoding="UTF-8"?><plugin><class>org.jivesoftware.openfire.plugin.Itvi</class><name>Itvi</name><description>Broadcasts messages to users.</description> <author>openfireteam</author><version>1.7.0</version><date>2/19/2009</date><url></url><minServerVersion>3.6.3</minServerVersion></plugin>Itvi.java文件代码如下:package org.jivesoftware.openfire.plugin;import org.dom4j.Element;import org.jivesoftware.openfire.IQHandlerInfo;import org.xmpp.packet.*;import org.jivesoftware.openfire.handler.IQHandler;import org.jivesoftware.openfire.auth.UnauthorizedException;/*** 处理客户端发来的IQ,并回送结果IQ** @author Phoenix** Mar 14, 2008 4:55:33 PM** version 0.1*/import org.dom4j.DocumentHelper;import org.dom4j.Element;import org.dom4j.QName;import org.jivesoftware.openfire.XMPPServer;import org.jivesoftware.openfire.container.Plugin;import org.jivesoftware.openfire.container.PluginManager; import org.jivesoftware.openfire.disco.IQDiscoInfoHandler; import org.jivesoftware.openfire.disco.IQDiscoItemsHandler; import org.jivesoftware.openfire.forms.DataForm;import org.jivesoftware.openfire.forms.FormField;import org.jivesoftware.openfire.forms.spi.XDataFormImpl; import org.jivesoftware.openfire.forms.spi.XFormFieldImpl; import org.jivesoftware.openfire.resultsetmanager.ResultSet; import org.jivesoftware.openfire.resultsetmanager.ResultSetImpl; import er;import erManager;import erNotFoundException; import org.jivesoftware.util.*;import ponent;import ponentException;import ponentManager;import ponentManagerFactory;import org.xmpp.packet.IQ;import org.xmpp.packet.IQ.Type;import org.xmpp.packet.JID;import org.xmpp.packet.Packet;import org.xmpp.packet.PacketError;import org.xmpp.packet.PacketError.Condition;import java.io.File;import java.util.*;import java.util.Map.Entry;public class Itvi implements Plugin{private XMPPServer server;/** (non-Javadoc)** @see org.jivesoftware.openfire.container.Plugin#destroyPlugin()*/public void destroyPlugin(){}/** (non-Javadoc)** @seeorg.jivesoftware.openfire.container.Plugin#initializePlugin(org.jivesoftware.openfir e.container.PluginManager,* java.io.File)*/public void initializePlugin(PluginManager manager, File pluginDirectory){server = XMPPServer.getInstance();server.getIQRouter().addHandler(new ItviIQHander()); //System.out.println("测试插件启动成功");}}ItviIQHander.java文件代码如下:package org.jivesoftware.openfire.plugin;import org.dom4j.Element;import org.jivesoftware.openfire.IQHandlerInfo;import org.xmpp.packet.*;import org.jivesoftware.openfire.handler.IQHandler;import org.jivesoftware.openfire.auth.UnauthorizedException;/*** 处理客户端发来的IQ,并回送结果IQ** @author Phoenix** Mar 14, 2008 4:55:33 PM** version 0.1*/public class ItviIQHander extends IQHandler{private static final String MODULE_NAME = "group tree handler";private static final String NAME_SPACE = "com:im:group";private IQHandlerInfo info;public ItviIQHander(){super(MODULE_NAME);//info = new IQHandlerInfo("gruops", NAME_SPACE);info = new IQHandlerInfo("query", "jabber:iq:roster");//这里我们对”联系人”的IQ进入监控}/** (non-Javadoc)** @see org.jivesoftware.openfire.handler.IQHandler#getInfo()*/@Overridepublic IQHandlerInfo getInfo(){return info;}/** (non-Javadoc)** @seeorg.jivesoftware.openfire.handler.IQHandler#handleIQ(org.xmpp.packet.IQ) */@Overridepublic IQ handleIQ(IQ packet) throws UnauthorizedException{IQ reply = IQ.createResultIQ(packet);Element groups = packet.getChildElement();//1if (true){System.out.println("非法的请求类型111111");}if (!IQ.Type.get.equals(packet.getType())){System.out.println("非法的请求类型");reply.setChildElement(groups.createCopy());System.out.println("返回的最终XML-SetError前"+reply.toXML());reply.setError(PacketError.Condition.bad_request);System.out.println("返回的最终XML-SetError后"+reply.toXML());return reply;}//String userName =StringUtils.substringBefore(packet.getFrom().toString(),"@");//GroupManager.getInstance().initElement(groups,userName); //reply.setChildElement(groups.createCopy());//2//System.out.println("返回的最终XML" reply.toXML());return reply;}}3.打包插件a.第一次打包需配置ant工具。