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)