openfire批量推送

openfire批量推送

标签: openfire批量推送openfire全服推送openfire在线推送
  1606人阅读  评论(2)  收藏  举报
  分类:

目录(?)[+]

今天分享一个openfire批量推送的插件,上次我们做的插件只是适合小范围推送,这次我们做一个给全部“在线”的用户推送消息的插件,只有在线用户才会收到推送消息,离线的用户不会收到消息(不会收到离线消息),如果同一账号使用多个终端登录那么多个终端都会收到推送消息。当然也可以把这个插件稍作修改就变成一个批量推送的插件,不一定要给全服的用户推送消息。


由于这次考虑到操作的用户量比较大,所以采用比较传统的方式

1. 推送的信息首先保存到数据库

2. checkThread以轮训的方式检查数据库是否有需要推送的消息

3. 有消息后创建Runnable对象并且扔到threadpool内执行




插件实现起来并不能,甚至是有一点简单,主要是如何获取数据库内的用户和如何检查用户是否在线,这两点了解的剩下的就简单了。


1. 检查是否有需要推送的消息


CheckThread.Java

个人觉得这部分是写的最失败的地方,采用的是原始的数据库轮训的机制,如果是生产环境是可以使用像Redis、activeMQ或者其他的方式来实现

[java]  view plain  copy
  1. package com.xxdd.openfire.batchpush.plugin.thread;  
  2.   
  3. import java.util.List;  
  4.   
  5. import org.xmpp.component.ComponentManager;  
  6. import org.xmpp.component.ComponentManagerFactory;  
  7.   
  8. import com.xxdd.openfire.batchpush.plugin.model.OFBatchPush;  
  9. import com.xxdd.openfire.batchpush.plugin.model.OFUser;  
  10. import com.xxdd.openfire.batchpush.plugin.provider.OFBatchPushProvider;  
  11. import com.xxdd.openfire.batchpush.plugin.provider.OFUserProvider;  
  12.   
  13. public class CheckThread extends Thread {  
  14.   
  15.     ComponentManager componentManager = ComponentManagerFactory.getComponentManager();  
  16.       
  17.     public void run() {  
  18.         while (ThreadPool.RUNNING) {  
  19.             OFBatchPush batPush = OFBatchPushProvider.getInstance().getPushContent();  
  20.             if (batPush == null) {//没有需要推送的消息  
  21.                 try {  
  22.                     Thread.sleep(3000);  
  23.                 } catch (InterruptedException e) {  
  24.                     e.printStackTrace();  
  25.                 }  
  26.             } else {//有需要推送的消息  
  27.                 //检查数据库内用户的数量  
  28.                 int count = OFUserProvider.getInstance().getUserCount();  
  29.                 int len = 20;  
  30.                 int maxPage = (int) Math.ceil((float) count / (float) len);  
  31.                 for (int i=0; i<maxPage; i++) {  
  32.                     //分页查询用户  
  33.                     List<OFUser> users = OFUserProvider.getInstance().findUsers(i*len, len);  
  34.                     if (users != null && users.size() > 0) {  
  35.                         for (OFUser user : users) {  
  36.                             //把要发送的消息内容和消息的接收人组装成Runnable对象  
  37.                             PushRunnable runnable = new PushRunnable(  
  38.                                     user.getUsername(),  
  39.                                     componentManager,  
  40.                                     batPush.getBody()  
  41.                                     );  
  42.                             //把runnable对象放到线程池内执行  
  43.                             ThreadPool.execute(runnable);  
  44.                         }  
  45.                     }  
  46.                 }  
  47.                 //最后发送完成,在数据库内删除消息内容  
  48.                 OFBatchPushProvider.getInstance().delPush(batPush.getId());  
  49.             }  
  50.         }  
  51.     }  
  52. }  


OFBatchPushProvider.java

[java]  view plain  copy
  1. package com.xxdd.openfire.batchpush.plugin.provider;  
  2.   
  3. import java.sql.Connection;  
  4. import java.sql.PreparedStatement;  
  5. import java.sql.ResultSet;  
  6. import java.sql.SQLException;  
  7.   
  8. import org.jivesoftware.database.DbConnectionManager;  
  9.   
  10. import com.xxdd.openfire.batchpush.plugin.model.OFBatchPush;  
  11.   
  12. public class OFBatchPushProvider {  
  13.   
  14.     private static OFBatchPushProvider self;  
  15.       
  16.     private OFBatchPushProvider() {  
  17.           
  18.     }  
  19.       
  20.     public static OFBatchPushProvider getInstance() {  
  21.         if (self == null)  
  22.             self = new OFBatchPushProvider();  
  23.         return self;  
  24.     }  
  25.       
  26.     /** 
  27.      * 获得需要推送的内容 
  28.      * @return 
  29.      */  
  30.     public OFBatchPush getPushContent() {  
  31.         String loadPushSQL = "SELECT id, body, create_time FROM ofBatchpush ORDER BY create_time LIMIT 1";  
  32.         Connection con = null;  
  33.         PreparedStatement pstmt = null;  
  34.         ResultSet rs = null;  
  35.           
  36.           
  37.         try {  
  38.             con = DbConnectionManager.getConnection();  
  39.             pstmt = con.prepareStatement(loadPushSQL);  
  40.               
  41.             rs = pstmt.executeQuery();  
  42.             if (rs.next()) {  
  43.                 OFBatchPush batPush = new OFBatchPush();  
  44.                 batPush.setId(rs.getInt(1));  
  45.                 batPush.setBody(rs.getString(2));  
  46.                 batPush.setCreateTime(rs.getDate(3));  
  47.                 return batPush;  
  48.             }  
  49.         } catch (SQLException e) {  
  50.             e.printStackTrace();  
  51.         } finally {  
  52.             DbConnectionManager.closeConnection(rs, pstmt, con);  
  53.         }  
  54.         return null;  
  55.     }  
  56.       
  57.     /** 
  58.      *  删除推送消息内容 
  59.      * @param id 
  60.      */  
  61.     public void delPush(int id) {  
  62.         String delPushSQL = "DELETE FROM ofBatchpush WHERE id = ?";  
  63.         Connection con = null;  
  64.         PreparedStatement pstmt = null;  
  65.         ResultSet rs = null;  
  66.           
  67.         try {  
  68.             con = DbConnectionManager.getConnection();  
  69.             pstmt = con.prepareStatement(delPushSQL);  
  70.             pstmt.setInt(1,id);  
  71.               
  72.             pstmt.executeUpdate();  
  73.               
  74.         } catch (SQLException e) {  
  75.             e.printStackTrace();  
  76.         } finally {  
  77.             DbConnectionManager.closeConnection(rs, pstmt, con);  
  78.         }  
  79.     }  
  80.       
  81. }  

OFBatchPush.java

[java]  view plain  copy
  1. package com.xxdd.openfire.batchpush.plugin.model;  
  2.   
  3. import java.util.Date;  
  4.   
  5. public class OFBatchPush {  
  6.   
  7.     private int id;  
  8.     private String body;  
  9.     private Date createTime;  
  10.       
  11.       
  12.     public int getId() {  
  13.         return id;  
  14.     }  
  15.     public void setId(int id) {  
  16.         this.id = id;  
  17.     }  
  18.     public String getBody() {  
  19.         return body;  
  20.     }  
  21.     public void setBody(String body) {  
  22.         this.body = body;  
  23.     }  
  24.     public Date getCreateTime() {  
  25.         return createTime;  
  26.     }  
  27.     public void setCreateTime(Date createTime) {  
  28.         this.createTime = createTime;  
  29.     }  
  30. }  


OFUserProvider.java

[java]  view plain  copy
  1. package com.xxdd.openfire.batchpush.plugin.provider;  
  2.   
  3. import java.sql.Connection;  
  4. import java.sql.PreparedStatement;  
  5. import java.sql.ResultSet;  
  6. import java.sql.SQLException;  
  7. import java.util.ArrayList;  
  8. import java.util.List;  
  9.   
  10. import org.jivesoftware.database.DbConnectionManager;  
  11.   
  12. import com.xxdd.openfire.batchpush.plugin.model.OFUser;  
  13.   
  14. /** 
  15.  *  
  16.  * @author xxdd 
  17.  */  
  18. public class OFUserProvider {  
  19.   
  20.     private static OFUserProvider self = null;  
  21.       
  22.     private OFUserProvider() {  
  23.           
  24.     }  
  25.       
  26.     public static OFUserProvider getInstance() {  
  27.         if (self == null)  
  28.             self = new OFUserProvider();  
  29.         return self;  
  30.     }  
  31.       
  32.     /** 
  33.      * 分页查询用户 
  34.      * @param offset 
  35.      * @param len 
  36.      * @return 
  37.      */  
  38.     public List<OFUser> findUsers(int offset, int len) {  
  39.           
  40.         String loadUsersSQL = "SELECT username FROM ofUser LIMIT ?,?";  
  41.         Connection con = null;  
  42.         PreparedStatement pstmt = null;  
  43.         ResultSet rs = null;  
  44.           
  45.         List<OFUser> users = new ArrayList<OFUser>(len);  
  46.         try {  
  47.             con = DbConnectionManager.getConnection();  
  48.             pstmt = con.prepareStatement(loadUsersSQL);  
  49.             pstmt.setInt(1, offset);  
  50.             pstmt.setInt(2, len);  
  51.               
  52.             rs = pstmt.executeQuery();  
  53.             while (rs.next()) {  
  54.                 OFUser user = new OFUser(rs.getString(1));  
  55.                 users.add(user);  
  56.             }  
  57.   
  58.         } catch (SQLException e) {  
  59.             e.printStackTrace();  
  60.         } finally {  
  61.             DbConnectionManager.closeConnection(rs, pstmt, con);  
  62.         }  
  63.         return users;  
  64.     }  
  65.       
  66.     /** 
  67.      * 获得用户总量 
  68.      * @return 
  69.      */  
  70.     public int getUserCount() {  
  71.           
  72.         String loadUserCountSQL = "SELECT COUNT(1) FROM ofUser";  
  73.         Connection con = null;  
  74.         PreparedStatement pstmt = null;  
  75.         ResultSet rs = null;  
  76.           
  77.         int count = 0;  
  78.         try {  
  79.             con = DbConnectionManager.getConnection();  
  80.             pstmt = con.prepareStatement(loadUserCountSQL);  
  81.               
  82.             rs = pstmt.executeQuery();  
  83.             rs.next();  
  84.             count = rs.getInt(1);  
  85.   
  86.         } catch (SQLException e) {  
  87.             e.printStackTrace();  
  88.         } finally {  
  89.             DbConnectionManager.closeConnection(rs, pstmt, con);  
  90.         }  
  91.         return count;  
  92.     }  
  93.       
  94. }  

OFUser.java

[java]  view plain  copy
  1. package com.xxdd.openfire.batchpush.plugin.model;  
  2.   
  3. public class OFUser {  
  4.   
  5.     private String username;  
  6.       
  7.     public OFUser() {  
  8.           
  9.     }  
  10.       
  11.     public OFUser(String username) {  
  12.         this.username = username;  
  13.     }  
  14.       
  15.     public String getUsername() {  
  16.         return username;  
  17.     }  
  18.   
  19.     public void setUsername(String username) {  
  20.         this.username = username;  
  21.     }  
  22. }  



2. 线程池

使用jdk自带的executor框架,创建一个简单的线程池,网上已经有很多的例子了,这里就不啰嗦了

[java]  view plain  copy
  1. package com.xxdd.openfire.batchpush.plugin.thread;  
  2.   
  3. import java.util.concurrent.ExecutorService;  
  4. import java.util.concurrent.LinkedBlockingDeque;  
  5. import java.util.concurrent.ThreadPoolExecutor;  
  6. import java.util.concurrent.TimeUnit;  
  7.   
  8. public class ThreadPool {  
  9.   
  10.   
  11.     private static ExecutorService pool = null;  
  12.       
  13.     private static int minThread = 5;  
  14.     private static int maxThread = 20;  
  15.       
  16.     private static LinkedBlockingDeque<Runnable> queue = new LinkedBlockingDeque<Runnable>(100);  
  17.       
  18.     public static boolean RUNNING = true;  
  19.       
  20.     static {  
  21.         pool = new ThreadPoolExecutor(  
  22.                 minThread,   
  23.                 maxThread,  
  24.                 60L,   
  25.                 TimeUnit.SECONDS,  
  26.                 queue,  
  27.                 new ThreadPoolExecutor.CallerRunsPolicy()  
  28.             );  
  29.         RUNNING = true;  
  30.     }  
  31.       
  32.       
  33.     public static void execute(Runnable runnable) {  
  34.         if (RUNNING) {  
  35.             pool.execute(runnable);  
  36.         }  
  37.     }  
  38.       
  39.     public static void shutDown() {  
  40.         RUNNING = false;  
  41.         pool.shutdownNow();  
  42.     }  
  43. }  

3. 发送线程

这部分代码不叫关键,是整个推送的核心部分

[java]  view plain  copy
  1. package com.xxdd.openfire.batchpush.plugin.thread;  
  2.   
  3. import java.util.Collection;  
  4.   
  5. import org.jivesoftware.openfire.SessionManager;  
  6. import org.jivesoftware.openfire.XMPPServer;  
  7. import org.jivesoftware.openfire.session.ClientSession;  
  8. import org.xmpp.component.ComponentException;  
  9. import org.xmpp.component.ComponentManager;  
  10. import org.xmpp.packet.JID;  
  11. import org.xmpp.packet.Message;  
  12. import org.xmpp.packet.Message.Type;  
  13.   
  14. public class PushRunnable implements Runnable {  
  15.   
  16.     SessionManager sessionManager = SessionManager.getInstance();  
  17.       
  18.     String toUsername;  
  19.     ComponentManager componentManager;  
  20.     String body;  
  21.       
  22.     private static final String from = "system";  
  23.     private static final String domain = XMPPServer.getInstance().getServerInfo().getXMPPDomain();  
  24.       
  25.     public PushRunnable(  
  26.             String toUsername,  
  27.             ComponentManager componentManager,  
  28.             String body) {  
  29.         this.toUsername = toUsername;  
  30.         this.componentManager = componentManager;  
  31.         this.body = body;  
  32.     }  
  33.       
  34.     @Override  
  35.     public void run() {  
  36.         //获得在线用户session  
  37.         Collection<ClientSession> sessions = sessionManager.getSessions(toUsername);  
  38.         if (sessions != null && sessions.size() > 0) {//存在在线用户的session  
  39.             Message message = new Message();  
  40.             message.setBody(body);  
  41.             message.setFrom(from + "@" + domain);  
  42.             message.setTo(toUsername + "@" + domain);  
  43.             message.setType(Type.normal);  
  44.               
  45.             //给单个用户的所有登录的客户端发送消息  
  46.             for (ClientSession session : sessions) {  
  47.                 JID jid = session.getAddress();  
  48.                 Message cpMessage = message.createCopy();  
  49.                 cpMessage.setTo(jid);  
  50.                 try {  
  51.                     //给在线用户推送消息  
  52.                     componentManager.sendPacket(null, message);  
  53.                 } catch (ComponentException e) {  
  54.                     e.printStackTrace();  
  55.                 }  
  56.             }  
  57.         }  
  58.     }  
  59.   
  60. }  





完整代码下载地址:http://download.csdn.NET/detail/kaixinwoo5/7579365


有问题欢迎邮件讨论7325356@qq.com


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值