通过编写openfire的外部组件我们可以极大的扩展openfire的能力,那么我们今天就开始实战。
首先介绍一下官方提供的一些库和API
在jivesoft官方提供的各种开发工具中,用于开发组件的有2个包,一个叫做whack,一个叫做tinder。
tinder是后出的,应该是在openfire项目和smack项目中提取的一些关键逻辑重新编写的库,主要实现xmpp的消息片段,这个不在今天的讨论内容,不过先提前说一下,这个tinder的确是个很不错的好东西,我们会在后面的文章中专题介绍。
今天我们用whack来实现外部组件,之所以我把whack和tinder分开,是希望大家能弄清楚这2个东西的区别。
首先,下载whack的源码,为什么不要直接下载jar包,因为你会发现jar包中关联的很多类根本找不到,我不确定是不是jivesoftware版本控制的问题,不过的确新版的jar包中需要的一些关键类是来自tinder的。那么既然我们今天不用tinder,那就干脆彻底不用,所以请下载whack的源码。
下面开始新建项目
作为一个外部组件,其实就是一个应用程序,我们直接新建一个空项目
完成之后把whack的源码拷贝到src目录下:
上图的com.zbiti.sample是我的代码包
其余的是whack的源码
接着,请把whack源码Build目录下的Lib里的所有jar包拷贝到项目的lib目录,并在build里添加引用
这些包有:
不用管dist和merge目录,都拷贝到lib目录,添加引用
为了方便Log,我引用了jetty-util.jar,这样Log简单一些,大家可以自己下载jetty的完整包,有一堆。
然后我们开始编写组件。
首先创建一个类ChatComponent,由于Component是接口,这一点你可以查看whack的文档,所以你的类必须实现这些接口
public class ChatComponentimplements Component
并且重写相关方法,代码如下:package com.zbiti.sample;
import org.eclipse.jetty.util.log.Log;
import org.xmpp.component.Component;
import org.xmpp.component.ComponentException;
import org.xmpp.component.ComponentManager;
import org.xmpp.packet.JID;
import org.xmpp.packet.Packet;
public class ChatComponent implements Component{
private static final String name="chat";
private static final String description="实现多人通过组件在区域内聊天";
private JID jid;
private ComponentManager comMgr;
@Override
public String getName() {
return name;
}
@Override
public String getDescription() {
return description;
}
@Override
public void processPacket(Packet packet) {
Log.info(packet.toXML());
}
@Override
public void initialize(JID jid, ComponentManager componentManager)
throws ComponentException {
this.jid=jid;
this.comMgr=componentManager;
}
@Override
public void start() {
Log.info("component start");
}
@Override
public void shutdown() {
Log.info("component shutdown");
}
}
非常简单,这样组件的主要类就完成了,关键的代码部分在
@Override public void processPacket(Packet packet)
现在我们先Log出packet的内容,将来逻辑需要在这里完善。
那么如何让我们的组件跑起来
第一,我们要在openfire上开启外部组件,并设置安全性,在上一篇文章我已经介绍过了,这里不再重复。
第二,编写应用的主入口程序
新建Main.java
代码如下:
package com.zbiti.sample;
import org.jivesoftware.whack.ExternalComponentManager;
import org.xmpp.component.ComponentException;
public class Main {
public static void main(String[] args) {
ExternalComponentManager mgr = new ExternalComponentManager(
"192.168.111.122", 5275);
mgr.setSecretKey("chat", "123456");
try {
mgr.addComponent("chat", new ChatComponent());
} catch (ComponentException e) {
System.exit(-1);
}
// daemon
while (true)
try {
Thread.sleep(10000);
} catch (Exception e) {
}
}
}
这几行代码主要是让我们的进程一直运行,Thread.sleep(10000)可以大幅度降低服务器的cpu占用,相信大家都知道。
解释一下就是我们实例化了ExternalComponentManager,并且设置openfire服务器地址192.168.111.122端口5275
组件的子域为chat,密码123456
然后我们运行Main
可以看到console显示
2012-11-27 20:59:26.016:INFO::component start
下面我们来测试一下组件对子域数据的处理是否正常,安装spark或者任何xmpp客户端,用openfire上的用户登录
添加一个子域用户。我说过,子域的用户是虚拟的,其实根本不需要存在,因此你可以添加任何子域用户
红色部分是你的openfire的域名,也就是xmpp.host属性的值,你可以在openfire的管理界面看到自己服务器的域名
chat就是子域,也就是我们组件负责的那个
添加完之后,你可以看到一个挂起的好友
和他打个招呼
在console你会看到下面信息:
2012-11-27 21:07:35.244:INFO::<presence id="yW2Oc-34" to="nobody@chat.你的openfire域" type="subscribe" from="admin@你的openfire域"/>
2012-11-27 21:11:30.228:INFO::<message id="yW2Oc-35" to="nobody@chat.你的openfire域" from="admin@你的openfire域/Spark 2.6.3" type="chat"><body>hello nobody</body><thread>0gjBy3</thread><x xmlns="jabber:x:event"><offline/><composing/></x></message>
一条是好友关系申请的presence包,一条是消息内容的Message包,说明我们的外部组件正常运行了。那么下面我们让服务器做出回应好歹,改写刚才的代码
@Override
public void processPacket(Packet packet) {
Log.info(packet.toXML());
if(packet instanceof Message){
Message msg=(Message) packet;
Message response=msg.createCopy();
response.setTo(msg.getFrom());
response.setFrom(msg.getTo());
response.setBody("hi friend!");
try {
comMgr.sendPacket(this, response);
} catch (ComponentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
停止服务,重新运行,再说句话
回应了,console里面显示
2012-11-27 21:20:14.796:INFO::<message id="yW2Oc-36" to="nobody@chat.你的openfire域" from="admin@你的openfire域/Spark 2.6.3" type="chat"><body>你好</body><thread>0gjBy3</thread><x xmlns="jabber:x:event"><offline/><composing/></x></message>
整个过程我们都完成了,至于为什么显示对方没有在线,那是因为虽然子域的用户是虚拟用户,但是也需要有subscrib的关系,不是roster的联系人无法知道在线状态,这一点无所谓,我们反正也不用spark,如果你看着难受,不妨实现互为好友。那么今天的介绍就到这里,实现外部组件相当简单,后面我会继续介绍其他实现外部组件的方法,直到最终部署在服务器上。
原创文章,转载请注明出处。