最近工作中用到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,欢迎修改、指证
附件中包括核心三个类
相关推荐
在Openfire中,消息记录存储插件扮演着关键角色,它负责收集、存储以及检索用户的聊天记录,这对于企业级通信管理和合规性审计至关重要。 首先,我们要了解Openfire的消息记录功能。Openfire内置了消息记录管理,但...
openfire插件,本插件直接在openfire里安装即可,集成消息在线和离线的存储、查询接口,图片、表情、语音文件的上传和下载对外接口,因此,不需要修改openfire源码即可满足聊天的实用功能,对外提供3个接口,一消息...
openfire防止消息丢失插件,防止丢包插件
openfire shell插件
这个"openfire聊天记录插件"是为了增强Openfire服务器的功能,提供聊天记录的存储和检索能力,使得用户可以回顾和查找之前的对话历史,这对于企业内部沟通、客户服务或者团队协作都是非常有价值的。 首先,我们要...
NULL 博文链接:https://bsr1983.iteye.com/blog/2240070
"openfire聊天记录插件"就是为了解决这个问题而设计的。 这个插件的核心功能是存储和检索Openfire服务器上的聊天记录。它允许管理员或用户查看过去的对话,这对于客户服务、项目回顾或者解决争议都有极大的帮助。`...
为了解决这个问题,"openfire丢包插件"应运而生。 这个"openfire丢包插件"被描述为"完美版",意味着它可能经过优化,能够更有效地处理丢包问题,确保通信的顺畅。丢包通常发生在网络不稳定或服务器负载过重时,可能...
5. **使用Openfire API**:Openfire提供了丰富的API供插件开发者使用,例如,你可以通过`AdminManager`来管理用户和群组,或者通过`PacketRouter`来发送和接收XMPP消息。理解并熟练运用这些API是开发高效插件的关键...
《Openfire企业版插件详解及应用》 Openfire是一款基于XMPP协议的企业级即时通讯服务器,它提供了高效、安全的实时通信解决方案。在Openfire的生态系统中,插件扮演着扩展服务器功能的重要角色,使得Openfire能够...
Openfire是一款开源、基于XMPP协议的实时协作服务器,它允许用户进行即时消息传递、音频/视频聊天以及群组聊天等操作。在企业或团队环境中,聊天记录的保存对于工作协同、问题排查以及合规审计具有重大意义。 这款...
3. **事件驱动编程**:Openfire采用事件驱动架构,当收到新的聊天消息时,会触发相应的事件,插件通过监听这些事件来处理和存储聊天记录。 4. **多线程和并发控制**:由于Openfire需要处理大量的并发连接,因此聊天...
在【标题】"openfire 聊天记录插件(单聊群聊)"中,我们看到的是一个针对Openfire服务器定制的插件,它的主要功能是记录用户的聊天记录,不仅涵盖了传统的单人聊天,还包括了多人参与的群聊记录。这对于企业管理、...
openfire服务器在进行消息转发时,如果接收者网络断开,服务器检测不到接收者已下线,转发后消息会丢失,为解决消息丢失,有四种解决方案: 1.发送之前“发送心跳” 2.发送之前“发自定义结构” 3.客服端收到消息...
2. 编写插件的 Java 代码,在插件启动时和关闭时,在控制台打印出消息。 3. 使用 Eclipse 进行编译和打包。 本文详细介绍了 Openfire 的安装和配置过程,并探讨了如何使用 Eclipse 进行插件开发。Openfire 是一个...
本教程将引导初学者了解如何开发第一个Openfire插件,从而深入理解Openfire的架构和插件开发流程。 1. **Openfire插件体系结构** Openfire插件是Java编写的独立模块,它们通过Openfire提供的API与核心服务交互。每...
这是一个基本的示例插件,用于展示如何创建Openfire服务器插件。 通过以上步骤,你就成功创建了一个基础的Openfire插件,可以在此基础上根据需求扩展功能,比如添加数据库交互、Servlet服务或者Web管理界面。 在...
对Openfire进行扩展,支持在线指定聊天室和全部在线人员的查看。