Openfire开发广播服务接口,支持离线广播消息
概要
最近公司要求做一个web端向所有移动端发送公告,所以考虑到即时性就用openfire做服务。不过为了减轻web端的工作量,我们开发一个简单的插件给openfire,对外开放http接口即可。
准备
系统环境:window10(surface pro4)
JDK:1.7 or later
开发工具:eclipse-Mars.2 Release (4.5.2)
Openfire版本:4.0.3
内容
Web端发送公告有两个方案:
1、web端集成smack,添加公告时候调用smack进行发送广播(默认不支持离线广播,要进行改造)比较繁琐。
2、openfire服务端进行发送广播,对外开放http接口,服务端开发插件简单而且权限比较大。
这里我们选择了方案2,下面我们进行对方案2的开发过程进行讲解。
用到Openfire本身的类:
- org.jivesoftware.util.WebManager:在post请求中进行注册,通过它可以获取所有用户。
- org.jivesoftware.openfire.PresenceManager:可以通过webManager. getPresenceManager();获取对象,用来判断用户是否在登陆状态。
- org.jivesoftware.openfire.XMPPServer:通过它的静态方法我们可以获取RoutingTable(发送消息)和OfflineMessageStrategy(保存离线消息)。
实现思路
实现核心代码
- post请求
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { webManager.init(req, resp, req.getSession(), req.getServletContext());//初始化webManager Collection<User> users = webManager.getUserManager().getUsers();//获取所有用户 NatureMap natureMap = combineReq(req); boolean result = sendMsg(users,natureMap); String msg = ""; if (result) { msg = "{"status":0}"; }else{ msg = "{"status":-1,"msg":"用户名或密码错误"}"; } respcontent(resp,msg); }
发送消息
private boolean sendMsg(Collection<User> users,NatureMap natureMap) { boolean result = true; String from = natureMap.getString("from"); String pwd = natureMap.getString("pwd"); try { String password = AuthFactory.getPassword(from); if (pwd!=null&&pwd.endsWith(password)) { String body = natureMap.getString("body"); String subject = natureMap.getString("subject"); Message message = new Message(); message.setType(Message.Type.chat); message.setBody(body); message.setFrom("公告@mvilplss");//目前不加from则会导致客户端不能自动获取离线消息,除主动获取。 message.setSubject(subject); PresenceManager presenceManager = webManager.getPresenceManager(); for (User user : users) { String username = user.getUsername(); message.setTo(username+"@mvilplss"); if(presenceManager.isAvailable(user)){ XMPPServer.getInstance().getRoutingTable().broadcastPacket(message, false); } else { if (!username.equals(from)) { XMPPServer.getInstance().getOfflineMessageStrategy().storeOffline(message); } } } } } catch (Exception e) { result=false; } return result; }
增加免登陆
private static final String SERVICE_NAME = "mybroadcast/broadcast";
public void destroy() { AuthCheckFilter.removeExclude(SERVICE_NAME); } public void init() throws ServletException { AuthCheckFilter.addExclude(SERVICE_NAME); }
结束
公告接口开发完毕,公告采用富文本形式编辑,为了手机端展示方便发送的公告广播为标题和公告html5的地址。