openfire推送插件开发

前两篇文章介绍了搭建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




下面该我们的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();
		}
		
	}
	
}





本来想把客户端传上来,可是不知道怎么上传文件。。疑问

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






  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值