XMPP离线处理

本文介绍了在Openfire中如何处理XMPP客户端的离线情况,包括正常离线和非正常离线的处理机制。通过MINA框架的idle检测功能,实现了对客户端连接状态的监测。此外,通过创建包过滤器和触发器,可以拦截并处理Presence消息,以实现特定的业务需求。文中还展示了如何创建和管理触发器,以及触发器响应的实现方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

XMPP离线管理

发布者:JECON

一、前提:

在Openfire 中,客户端登出的状态分为正常离线和断线,正常离线会发送presence消息通知。非正常离线的时候,openfire自带的心跳包会检测客户端的响应,如果客户端长时间无响应,Openfire无法接收到客户端的presence消息的时候,mina框架会在OF的ConnectionHandler的sessionClosed()方法中进行后续的处理。

二、离线检测:

MINA框架本身提供了idle检测功能,这项功能可检测客户端建立的TCP/IP连接,却不发送任何消息的状况。

在ClientConnectionHandler的sessionidle方法中判断当前的idle次数大于1时将关闭客户端的连接。如果设置了idle time之后在这个idle的检测发生在达到一半时间和达到指定的时间,每次检测都会将idle的次数加1,也就是我们一旦设定了这个时间长,mina框架就会在这个时长的一半时间内,客户端仍未发送消息时触发一次sessionidle事件,然后在到达指定的时长,客户端仍未发送消息时再触发一次。

触发做法:第一次触发sessionidle时发送一次ping,强迫客户端进行响应。

三、业务需求:

既然明白了OF的离线做法,我们何不使用包的过滤机制,来过滤presnece的消息通知包。那么就让我们来实践下这种机制:

1、创建包过滤器,使用包过滤器。可以将presence的状态拦下,之后对其做处理,代码如下:

/**

 * @see 拦截presence,触发openfire 的离线用户事件

 * @author root

 *

 */

public class PresenceInterceptor implements PacketInterceptor  {

@Override

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

boolean processed) throws PacketRejectedException {

if(!processed && packet instanceof Presence && incoming){

Presence myPresence =(Presence)packet;

System.out.println("presence unavlilate"+packet.toXML());

}

}

}

我们使用了Spark测试,当用户下线的时候,发送了一次presence,当用户上线的时候,发送一次presence,结果呈现如图1-1所示:

图1-1 所示 Presence状态处理

按照以上方式,我们可以为其匹配些业务触发器。现在让我来介绍下各个触发器的实现:

1、创建触发器:

/**

 * @see tigger包:该模块的主要业务为:

 * 

 */

package org.jivesoftware.openfire.tigger;

import java.util.ArrayList;

import java.util.List;

/**

 * @see 创建触发器

 * @author root

 *

 */

public abstract class Tigger {

private static ClassLoader loader=null;

public static TiggerManager tiggerMangerGlobal=null;

//创建触发器

List<TiggerManager> tiggerList = new ArrayList<TiggerManager>();

boolean changed = false;

public Tigger(){

super();

}

/**

 * @see 添加tigger

 * @param tiggerManager触发管理器

 */

public void addTigger(String tiggerManagerModule){

Class<?> isTiggerManageClass=null;;

Object tiggerManager=null;

loader = Thread.currentThread().getContextClassLoader();

try {

isTiggerManageClass = loader.loadClass(tiggerManagerModule);

tiggerManager=(TiggerManager)isTiggerManageClass.newInstance();

System.out.println("实例化对象="+tiggerManager);

tiggerMangerGlobal=(TiggerManager) tiggerManager;

if(tiggerManager == null){

System.out.println("触发器为空");

}synchronized(this){

//如果触发器和容器中的触发器不相等,则

if(!tiggerList.contains(tiggerManager)){

tiggerList.add((TiggerManager) tiggerManager);

}

}

} catch (ClassNotFoundException e) {

e.printStackTrace();

} catch (InstantiationException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

}

}

/**

 * @see 清空状态

 */

protected void clearChanged(){

changed=false;

}

/**

 * 计算触发器的数量

 */

protected int countTigger(){

return tiggerList.size();

}

/**

 * @see 删除触发器

 */

protected synchronized void deleteTigger(){

tiggerList.clear();

}

/**

 * @see 判断触发器的状态

 * 

 */

protected boolean hasChanged(){

return changed;

}

/**

 * @触发响应

 */

protected void setChanged(){

changed=true;

}

/**

 * @触发事件

 */

public void notifyTigger(Object data) {

int size = 0;

TiggerManager[] arrays = null;

synchronized (this) {

if (hasChanged()) {

clearChanged();

size = tiggerList.size();

arrays = new TiggerManager[size];

tiggerList.toArray(arrays);

}

}

if (arrays != null) {

for (TiggerManager tigger : arrays) {

tigger.update(this, data);

}

}

}

/**

 * @see 触发事件,根据key和value做索引

 */

public void notifyTiggerKey(String key,String value) {

for(int i=0; i<tiggerList.size(); i++){

TiggerManager tigger = tiggerList.get(i);

tigger.update(key,value);

}

}

/**

 * @see 触发事件,根据key和value做索引

 */

public void notifyTigger() {

for(int i=0; i<tiggerList.size(); i++){

TiggerManager tigger = tiggerList.get(i);

tigger.update();

}

}

/**

 * @see 触发事件,根据key和value做索引

 */

public void notifyTiggerKey(Object obj) {

for(int i=0; i<tiggerList.size(); i++){

TiggerManager tigger = tiggerList.get(i);

tigger.update(obj);

}

}

}

2、

2、触发器管理类:

/**

 * @see tigger包:该模块的主要业务为:

 * 

 */

package org.jivesoftware.openfire.tigger;

/**

 * @see 触发事件的管理器

 * @author root

 *

 */

public interface TiggerManager {

/**

 * 

 * @param tigger 触发器源头

 * @param data   触发器对象

 * @return

 */

 boolean  update(Tigger tigger, Object data);

 /**

  * @see 触发数据抓取

  * @param key 关键索引

  * @param value 关键索引值

  * @return

  */

 boolean update(String key,String value);

 /**

  * @see 普通触发事件

  * @return

  */

 boolean update();

 /**

  * @see 触发事件

  */

 boolean update(Object obj);

}

3、基础触发器:

/**

 * @see tigger包:该模块的主要业务为:

 */

package org.jivesoftware.openfire.tigger;

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

/**

 * @see 处理TiggerSourceBase事件。

 * @author root

 *

 */

public abstract class TiggerSolutionManager implements TiggerManager {

private static ClassLoader loader=null;

/**

 * @see 初始化触发器响应事件(通过反射添加tigger),添加触发器

 * @param classResouceTigger 添加被观察者

 * @param tigger

 * @return 

 */

private static TiggerManager initlize(String classResouceTigger,String tiggerMethodModule){

TiggerManager isTiggerManage=null;

loader = Thread.currentThread().getContextClassLoader();

Object tigger = null;

try {                                   

Class<?> tiggerCls = loader.loadClass(classResouceTigger);

tigger=(Tigger)tiggerCls.newInstance();

Method method = tiggerCls.getDeclaredMethod("addTigger",new Class[]{String.class});

method.setAccessible(true);

String[] argments = new String[1];

argments[0] =tiggerMethodModule ;

method.invoke(tigger,argments);

isTiggerManage=Tigger.tiggerMangerGlobal;

} catch (SecurityException e) {

e.printStackTrace();

} catch (IllegalArgumentException e) {

e.printStackTrace();

} catch (InstantiationException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

} catch (ClassNotFoundException e) {

e.printStackTrace();

} catch (NoSuchMethodException e) {

e.printStackTrace();

} catch (InvocationTargetException e) {

e.printStackTrace();

}

return isTiggerManage;

}

/**

 * @see 使用反射调用触发器

 * @param tiggerMethodModule:触发器响应体

 * @param

 */

public static void createTiggerMethodKey(String classResouceTigger,String tiggerMethodModule,String key,String value){

TiggerManager isTiggerSolution=null;

try{

if(isTiggerSolution == null){

isTiggerSolution= initlize(classResouceTigger,tiggerMethodModule);

//即时响应

isTiggerSolution.update(key,value);

}

}catch(Exception e){

e.printStackTrace();

}

}

/**

 * @see 使用反射调用触发器

 * @param tiggerMethodModule:触发器响应体

 */

public static void createTiggerMethod(String classResouceTigger,String tiggerMethodModule){

TiggerManager isTiggerSolution=null;

try{

if(isTiggerSolution == null){

isTiggerSolution= initlize(classResouceTigger,tiggerMethodModule);

//即时响应

isTiggerSolution.update();

}

}catch(Exception e){

e.printStackTrace();

}

}

/**

 * @see 使用反射调用触发器

 * @param tiggerMethodModule:触发器响应体

 */

public static void createTiggerMethod(String classResouceTigger,String tiggerMethodModule,String value){

TiggerManager isTiggerSolution=null;

try{

if(isTiggerSolution == null){

isTiggerSolution= initlize(classResouceTigger,tiggerMethodModule);

//即时响应

isTiggerSolution.update(value);

}

}catch(Exception e){

e.printStackTrace();

}

}

public abstract boolean update(Tigger tigger, Object data);

public abstract boolean update(String key, String value);

public abstract boolean update();

}

4、触发器响应:

/**

 * @see tigger包:该模块的主要业务为:

 */

package org.jivesoftware.openfire.tigger;

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

/**

 * @see 处理TiggerSourceBase事件。

 * @author root

 *

 */

public abstract class TiggerSolutionManager implements TiggerManager {

private static ClassLoader loader=null;

/**

 * @see 初始化触发器响应事件(通过反射添加tigger),添加触发器

 * @param classResouceTigger 添加被观察者

 * @param tigger

 * @return 

 */

private static TiggerManager initlize(String classResouceTigger,String tiggerMethodModule){

TiggerManager isTiggerManage=null;

loader = Thread.currentThread().getContextClassLoader();

Object tigger = null;

try {                                   

Class<?> tiggerCls = loader.loadClass(classResouceTigger);

tigger=(Tigger)tiggerCls.newInstance();

Method method = tiggerCls.getDeclaredMethod("addTigger",new Class[]{String.class});

method.setAccessible(true);

String[] argments = new String[1];

argments[0] =tiggerMethodModule ;

method.invoke(tigger,argments);

isTiggerManage=Tigger.tiggerMangerGlobal;

} catch (SecurityException e) {

e.printStackTrace();

} catch (IllegalArgumentException e) {

e.printStackTrace();

} catch (InstantiationException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

} catch (ClassNotFoundException e) {

e.printStackTrace();

} catch (NoSuchMethodException e) {

e.printStackTrace();

} catch (InvocationTargetException e) {

e.printStackTrace();

}

return isTiggerManage;

}

/**

 * @see 使用反射调用触发器

 * @param tiggerMethodModule:触发器响应体

 * @param

 */

public static void createTiggerMethodKey(String classResouceTigger,String tiggerMethodModule,String key,String value){

TiggerManager isTiggerSolution=null;

try{

if(isTiggerSolution == null){

isTiggerSolution= initlize(classResouceTigger,tiggerMethodModule);

//即时响应

isTiggerSolution.update(key,value);

}

}catch(Exception e){

e.printStackTrace();

}

}

/**

 * @see 使用反射调用触发器

 * @param tiggerMethodModule:触发器响应体

 */

public static void createTiggerMethod(String classResouceTigger,String tiggerMethodModule){

TiggerManager isTiggerSolution=null;

try{

if(isTiggerSolution == null){

isTiggerSolution= initlize(classResouceTigger,tiggerMethodModule);

//即时响应

isTiggerSolution.update();

}

}catch(Exception e){

e.printStackTrace();

}

}

/**

 * @see 使用反射调用触发器

 * @param tiggerMethodModule:触发器响应体

 */

public static void createTiggerMethod(String classResouceTigger,String tiggerMethodModule,String value){

TiggerManager isTiggerSolution=null;

try{

if(isTiggerSolution == null){

isTiggerSolution= initlize(classResouceTigger,tiggerMethodModule);

//即时响应

isTiggerSolution.update(value);

}

}catch(Exception e){

e.printStackTrace();

}

}

public abstract boolean update(Tigger tigger, Object data);

public abstract boolean update(String key, String value);

public abstract boolean update();

}

好了,以上是触发器的功能,现在我们可以将这些触发器匹配各自的业务:

1、RosterTigger:用于匹配当好友下线或在线时的触发事件

2、TranslateTigger:用于匹配发送文件时,对方下线时的触发事件

注意:

Openfire中判断当前用户是否在线,则使用以下方式:

User user =  XMPPServer.getInstance().getUserManager().getUser(route.bar seID());

XMPPServer.getInstance().getPresenceManager().isAvailable(user)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值