openfire消息回执插件

最近工作中用到openfire,做聊天应用服务器,环境塔建没有问题,但当手机客户端网络异常时,却仍显示用户在线,导致有一部分消息对方会收不到。在网上找了半天,也没找到好的解决方案。参考N多文章及询问群友,终决定加个消息回执插件,来保证 消息是否收到 的准确性。

具体如下:

插件基本上是在别人基础上改的

基于开源 Openfire 聊天服务器 - 开发Openfire聊天记录插件

http://www.cnblogs.com/hoojo/archive/2013/03/29/openfire_plugin_chatlogs_plugin_.html

1、核心插件类ChatLogPlugin(偷懒了,直接用别人的)

public void interceptPacket(Packet packet, Session session, boolean incoming, boolean processed) 

throws PacketRejectedException {

//System.out.println("chat...........session."+session);

   if (session != null) {

           debug(packet, incoming, processed, session);

       }

   JID recipient = packet.getTo();

       if (recipient != null) {

           String username = recipient.getNode();

           // 广播消息或是不存在/没注册的用户.

           if (username == null || !UserManager.getInstance().isRegisteredUser(recipient)) {

               return;

           } else if (!XMPPServer.getInstance().getServerInfo().getXMPPDomain().equals(recipient.getDomain())) {

               // 非当前openfire服务器信息

               return;

           } else if ("".equals(recipient.getResource())) {

           }

       }

       this.doAction(packet, incoming, processed, session);

}

private void doAction(Packet packet, boolean incoming, boolean processed, Session session) {

        Packet copyPacket = packet.createCopy();

        System.out.println("=================1===================="+(packet instanceof IQ));

        System.out.println("================2====================="+(packet instanceof Message));

        

        if (packet instanceof Message) {

            Message message = (Message) copyPacket;

           

            // 一对一聊天,单人模式

            if (message.getType() == Message.Type.chat) {

                log.info("单人聊天信息:{}", message.toXML());

                debug("单人聊天信息:" + message.toXML());

                debug("单人聊天信息:" + message.getID()+":"+message.getTo());

                

                // 程序执行中;是否为结束或返回状态(是否是当前session用户发送消息)

                if (processed || !incoming) {

                    return;

                }

                if(IsUserOnLine(message.getTo().toString())==1){

                //原代码

                //logsManager.add(this.get(packet, incoming, session));

                logsManager.insertOffline(message);

               

                }

                

            // 群聊天,多人模式

            } else if (message.getType() ==  Message.Type.groupchat) {

                List<?> els = message.getElement().elements("x");

                if (els != null && !els.isEmpty()) {

                    log.info("群聊天信息:{}", message.toXML());

                    debug("群聊天信息:" + message.toXML());

                } else {

                    log.info("群系统信息:{}", message.toXML());

                    debug("群系统信息:" + message.toXML());

                }

                

            // 其他信息

            } else {

                log.info("其他信息:{}", message.toXML());

                debug("其他信息:" + message.toXML());

            }

        } else if (packet instanceof IQ) {

            IQ iq = (IQ) copyPacket;

            debug("IQ:" + iq);

            debug("IQ0:" + iq.toXML());

            debug("IQ1:" + iq.getType());

            

            

            

            if (iq.getType() == IQ.Type.set && iq.getChildElement() != null && "session".equals(iq.getChildElement().getName())) {

                log.info("用户登录成功:{}", iq.toXML());

                debug("用户登录成功:" + iq.toXML());

            }

            else if (iq.getType() == IQ.Type.set && iq.getElement() != null ) {//判断回执

            Element el= iq.getElement().element("message");

                String type1=el.attributeValue("type");

                Element el2=el.element("item");

                String type2=el2.attributeValue("id");

                debug("IQ2:" + type1);

                debug("IQ3:" + type2);

                if("receipt".equals(type1)&&type2!=null){//回执

                logsManager.delById(type2);

                }

               

            }

        } else if (packet instanceof Presence) {

            Presence presence = (Presence) copyPacket;

            if (presence.getType() == Presence.Type.unavailable) {

                log.info("用户退出服务器成功:{}", presence.toXML());

                debug("用户退出服务器成功:" + presence.toXML());

            }

        } 

    }

方法说明:做消息拦截,执行doAction方法,首先判断哪种聊天方式,这里我只实现了单对单的。然后判断用户是否在线,如果在线,用户发的消息存到ofoffline表中,不在线就不管了,由openfire本身的离线机制去处理,它也是存到ofoffline表中。现在存到表中的数据其实不是真实的离线数据,这时候就要去判断客户端的回执了,客户端收到消息后需要封装个IQ回来,然后得到收到消息的id.因为ofoffline表中没存messageId ,原来的自增长的,需要在表中新加字段receipt_id,varchar型,即保存消息时,将messageId 存到这个字段中。得到ID后,就可以调数据处理类的删除方法,将这条信息从表中删除了。这样就简单的实现了异常掉线的消息处理。</p>

另:判断用户在线需安装presence插件。

ps:本人刚接触openfire,欢迎修改、指证

附件中包括核心三个类

猜你喜欢

转载自xrb2008.iteye.com/blog/1972738