openfire推送插件开发

时间:2021-11-06 13:16:35

前两篇文章介绍了搭建openfire开发环境制作一个openfire插件   今天和大家分享一下如何编写一个openfire push插件

下面我们制作一个简单的openfire push插件,适合一次推送给几个用户,如果一次推送给多个用户并且并发很高的需要把插件修改成异步+线程池的模式,后续我们做群聊插件的时候会用到这种结构,还会用redis做一个简单的消息队列


PushPlugin.java

package com.xxdd.openfire.push.plugin;

import java.io.File;

import org.dom4j.Element;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xmpp.component.Component;
import org.xmpp.component.ComponentException;
import org.xmpp.component.ComponentManager;
import org.xmpp.component.ComponentManagerFactory;
import org.xmpp.packet.IQ;
import org.xmpp.packet.JID;
import org.xmpp.packet.Message;
import org.xmpp.packet.Message.Type;
import org.xmpp.packet.Packet;

/**
* openfire push 插件
*
* 1.此插件适合小范围的推送需求,不适合给多用户推送
* 如果一次性推送多个用户请使用异步模式
* 2.此插件适合单点登录,不适合一个账号使用多个客户端登录的情况
* @author xxdd
*/
public class PushPlugin implements Component, Plugin {

private ComponentManager componentManager;
private PluginManager pluginManager;

private final String serviceName = "push";
private final String from = "system";

/**
* 初始化插件
*/
@Override
public void initializePlugin(PluginManager manager, File pluginDirectory) {
// TODO Auto-generated method stub
pluginManager = manager;
componentManager = ComponentManagerFactory.getComponentManager();
try {
componentManager.addComponent(serviceName, this);
} catch (ComponentException e) {
e.printStackTrace();
}
System.out.println("[-- init server push plugin --]");
}

@Override
public void destroyPlugin() {
pluginManager = null;
}

@Override
public String getDescription() {
// TODO Auto-generated method stub
return pluginManager.getDescription(this);
}

@Override
public String getName() {
// TODO Auto-generated method stub
return pluginManager.getName(this);
}

@Override
public void initialize(JID arg0, ComponentManager arg1)
throws ComponentException {
// TODO Auto-generated method stub

}

/**
* 处理消息
*/
@Override
public void processPacket(Packet packet) {

if (packet instanceof IQ) {
//注册 组件
IQ replyPacket = handleIQ((IQ) packet);
try {
componentManager.sendPacket(this, replyPacket);
} catch (ComponentException e) {
e.printStackTrace();
}
} else if (packet instanceof Message) {
handleMessage((Message) packet);
}
}

/**
* 处理message类型的消息
* @param message
*/
private void handleMessage(Message message) {
Type type = message.getType();
//判断消息类型,根据需要设置自己想要的类型,我这里设置成了normal
if (type != Type.normal) {
return;
}
//获得当前openfire的domain
String domain = XMPPServer.getInstance().getServerInfo().getXMPPDomain();
//获得消息体
String body = message.getBody();
//获得消息的主题,我们这里的主题内容为要推送给的用户
String subject = message.getSubject();

String[] arr = subject.split(",");
for (String str : arr) {
//创建Message对象
Message msg = new Message();
msg.setFrom(from + "@" + domain);
msg.setBody(body);
msg.setTo(str + "@" + domain);
msg.setType(Type.chat);
try {
//发送消息,此消息发出后会走openfire的消息路由,最后推送给用户
componentManager.sendPacket(this, msg);
} catch (ComponentException e) {
e.printStackTrace();
}
}
System.out.println("["+domain+"]["+subject+"]");

}

/**
* 处理component注册消息
* @param iq
* @return
*/
private IQ handleIQ(IQ iq) {
final Element childElement = iq.getChildElement();
final String namespace = childElement.getNamespaceURI();
if (namespace.equals(IQDiscoInfoHandler.NAMESPACE_DISCO_INFO)) {
IQ replyPacket = IQ.createResultIQ(iq);
Element responseElement = replyPacket.setChildElement("query", IQDiscoInfoHandler.NAMESPACE_DISCO_INFO);
responseElement.addElement("identity")
.addAttribute("category", "push")
.addAttribute("type", "user")
.addAttribute("name", "Server Push");
return replyPacket;
}
return null;
}


@Override
public void shutdown() {
// TODO Auto-generated method stub

}

@Override
public void start() {
// TODO Auto-generated method stub

}

}


下面我们还两个客户端工具来配合测试我们的插件

1. smack3.4.1(java的客户端包)

2. spark2.6.3(官方的客户端,各种平台都与测试非常方便)


下载地址:http://www.igniterealtime.org/downloads/index.jsp


使用spark注册几个测试用户

openfire推送插件开发


openfire推送插件开发



然后使用刚注册的用户登录到openfire

openfire推送插件开发



下面该我们的smack出场了

TestMain.java

package cn.xxdd.client;

import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Message.Type;

public class TestMain {

public static void main(String[] args) {
new TestMain().createConn();
}

private void createConn() {
XMPPConnection connection = new XMPPConnection("localhost");
try {
connection.connect();
connection.login("test3", "111");

Message message = new Message();
//具体消息内容
message.setBody("测试推送 body");
message.setType(Type.normal);
//这里需要注意一下,就是plugin的name加上“.”然后是openfire的domain
message.setTo("push.openfire.cluster1");
//本条消息的接受者
message.setSubject("test1,test2");

connection.sendPacket(message);
Thread.sleep(10000);
} catch (XMPPException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}

}

}





本来想把客户端传上来,可是不知道怎么上传文件。。openfire推送插件开发

那就截个图吧,其实就是把下载的smack3.4.1的所有包都导入进来了

openfire推送插件开发