Openfire插件开发实例--随机用户配对插件

Openfire支持插件开发,使得它的用处大大增加。前阵子,做一个匿名聊天软件,名字叫做“子曰”,再做这个项目之前,了解了许多关于Openfire的知识,得知他支持插件开发,并且能实现所需要的功能,所以最后就决定用它。这个匿名聊天软件最核心的功能就是陌生人配对了。服务器端实现也很简单,用户配对插件思路是这样的: 

1. 如果客户端是发来请求配对用户的包并且用户队列中没有用户,将请求的用户的用户名放入用户队列中并向客户端发送等待的包。
2. 如果客户端是发来请求配对用户的包并且用户队列中有其他用户,将其用户名从队列中取出,并给客户端发送包含其他用户名的包。 
3. 如果客户端是发来请求配对用户的包并且用户队列中有用户本身,给客户端发送继续等待的包。
4. 如果客户端是发来请求退出配对的包,将其用户名从用户队列中移除。

我们写两个Java源文件
1. MatchUserPlugin.java,插件的入口和插件的所有逻辑判断。

public class MatchUserPlugin  implements Plugin {

	private IQRouter iqRouter;
	private  final Logger Log = LoggerFactory.getLogger(MatchUserPlugin.class);
	private SimpleDateFormat simpleDateFormat=new SimpleDateFormat("HH:mm:ss.SSS");
	SessionManager sessionManager=new SessionManager();
	
	@Override
	public void destroyPlugin() {
		// TODO Auto-generated method stub
		Log.info("------------------->MatchUserPlugin destroy!");
		
	}

       /**
       * 插件初始化时被调用
       */
	@Override
	public void initializePlugin(PluginManager pluginManager, File file) {
		// TODO Auto-generated method stub
		Log.info("------------------->MatchUserPlugin initialize!");
		try {


			iqRouter  = XMPPServer.getInstance().getIQRouter();
			iqRouter.addHandler(new MyIQHandler("MyIQHandler"));  


		} catch (Exception e) {
			// TODO: handle exception
			Log.info("------------------->Bind Exception:"+e.toString());
		}
	}

	/**
	 * 处理数据包
	 * @author Administrator
	 *
	 */
	private class MyIQHandler extends IQHandler{
		//客户端可能发来的消息
		private static final String QUIT_MATCH="quit_match";//退出用户配对
		private static final String MATCH_USER="match_user";//请求用户配对
		//服务端要发送的消息
		private static final String MATCH_WAIT="match_wait";//等待状态
		private static final String MATCH_SUCCESS="match_success_server";//匹配成功
		private static final String QUIT_MATCH_SUCCESS="quit_match_success";//退出配对成功
		private static final String NAMESPACE_INFO="match:iq:info";//iq包的命名控件
		private static final String QUIT_CHAT="quit_chat";


		private Dao redisDAO;
		private IQHandlerInfo info;
		//private final  Logger log = LoggerFactory.getLogger(MyIQHandler.class);
		@Override
		public void initialize(XMPPServer server) {
			// TODO Auto-generated method stub
			super.initialize(server);
			
		}
		
		
		
		public MyIQHandler(String moduleName) {
			super(moduleName);
			redisDAO=Dao.getInstance();
			// TODO Auto-generated constructor stub
			info=new IQHandlerInfo("info", NAMESPACE_INFO);
		}




		@Override
		public IQHandlerInfo getInfo() {
			// TODO Auto-generated method stub
			return info;
		}


		@Override
		public IQ handleIQ(IQ packet) throws UnauthorizedException {
			// TODO Auto-generated method stub
			IQ iq=new IQ();
			String childName=packet.getChildElement().getName();
			
			if(childName==null)
				return packet;
			
			if(!childName.equals("info"))
			{
				return packet;
			}
			
			IQ replyIQ=IQ.createResultIQ(packet);
			ClientSession clientSession=sessionManager.getSession(packet.getFrom());
			
			if(clientSession==null)
			{
				log("Error user info.Session not found"
						+sessionManager.getPreAuthenticatedKeys()
						+" from "+packet.getFrom());
				replyIQ.setChildElement(packet.getChildElement().createCopy());
				replyIQ.setError(PacketError.Condition.forbidden);
				return replyIQ;
			}


			org.dom4j.Element child= packet.getChildElement().createCopy();
			String type=child.attributeValue("type");
			String ns=child.getNamespaceURI();
			if(!ns.equals(NAMESPACE_INFO))
			{
				log("This namespace is valid !"
						+sessionManager.getPreAuthenticatedKeys()
						+" from "+packet.getFrom());
				replyIQ.setChildElement(packet.getChildElement().createCopy());
				replyIQ.setError(PacketError.Condition.bad_request);
				return replyIQ;
			}
			
			Element infoElement = DocumentHelper.createElement("info");
			infoElement.addNamespace("", NAMESPACE_INFO);
			switch (type) {
				case MATCH_USER:
					//log("------------------->MATCH_USER");
					String  queueJID=redisDAO.lget();
					//队列中没有人
					if(queueJID==null)
					{
						//将自己的jid放入队列,并返回等待
						try {
							redisDAO.push(packet.getFrom().toFullJID());
							
							infoElement.addAttribute("type", MATCH_WAIT);
							infoElement.addAttribute("data","nil");
							replyIQ.setChildElement(infoElement);
						
						} catch (Exception e) {
							// TODO: handle exception
						}
						
					}
					//队列中有人
					else 
					{
						try {
							//如果队列只有自己,等待
							if(queueJID.equals(packet.getFrom().toFullJID()))
							{
								infoElement.addAttribute("type", MATCH_WAIT);
								infoElement.addAttribute("data","nil");
								replyIQ.setChildElement(infoElement);
								
							}
							else
							{
								//从队列中弹出一个元素
								queueJID=redisDAO.lpop();
								infoElement.addAttribute("type", MATCH_SUCCESS);
								infoElement.addAttribute("data",queueJID);
								replyIQ.setChildElement(infoElement);
							}
						} catch (Exception e) {
							// TODO: handle exception
						}
					}
					break;
				case QUIT_MATCH:
					long idx=redisDAO.remove(packet.getFrom().toFullJID());
					if(idx!=-1){
						infoElement.addAttribute("type", QUIT_MATCH_SUCCESS);
						infoElement.addAttribute("data","nil");
						replyIQ.setChildElement(infoElement);
					}
					break;
				case QUIT_CHAT:
						return packet;
				default:
					return packet;
			}//switch
			
			return replyIQ;
		}
	}//MyIQHandler


	public void log(String text)
	{
		Log.info(text);
	}
}

 


2. Dao.java,Redis数据库操作类,并模拟一个用户队列,依赖Jedis.jar.

 

 

public class Dao {
	private static Dao dao; 
	private static Jedis jRedis;
	private final static String KEY="UserQueue";//Redis数据库中的键名
	private final static String LOCAL_HOST="127.0.0.1";//Redis数据库ip
	private  final Logger Log = LoggerFactory.getLogger(Dao.class);
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Dao dao=Dao.getInstance();
	}
	/**
	 * 
	 * @return
	 */
	public static Dao getInstance()
	{
		if(dao==null)
		{
			dao = new Dao();
		}
		
		return dao;
		
	}
	
	/**
	 * 移除指定元素
	 */
	public Long remove(String value)
	{
		return jRedis.lrem(KEY, 1, value);
	}
	/**
	 * 弹出最左边的数据
	 * @return
	 */
	public  String lpop() {
		// TODO Auto-generated method stub
		return jRedis.lpop(KEY);
	}
	
	/**
	 * 获取最左边的数据
	 * @return
	 */
	public  String lget() {
		// TODO Auto-generated method stub
		return jRedis.lindex(KEY, jRedis.llen(KEY)-1);
	}
	/**
	 * 将元素放入队列尾
	 * @param jid
	 */
	public  void push(String jid) {
		// TODO Auto-generated method stub
		jRedis.rpush(KEY, jid);
	}
	
	private Dao(){


		if(jRedis==null)
		{
			jRedis=new Jedis(LOCAL_HOST);
		}
		
		String ping=jRedis.ping();
		Log.info("---------->"+ping);
	}
}



完整代码:https://github.com/luoyesiqiu/MatchUserPlugin

 

 

 

你可能感兴趣的:(Openfire/Smack)