第六课、Openfire插件之拦截器PacketInterceptor

阅读:16348

1、详解openfire插件拦截器PacketInterceptor

2、openfire的interceptPacket函数详解

1、对openfire插件的进一步理解

前面我们讲了一个插件必须有一个类继承plugin,只有这样,它才被openfire认为是一个插件。

Openfie被设计成可以用添加插件的方式来扩展功能,那么什么是openfire插件呢?

这里,我们通俗的告诉大家什么是插件,其实任何软件的插件都是这个思路的。

2、插件原则一

以我们的净水器为例,如下图:

假设下面的净水滤芯就是插件,流进净水滤芯的是水,流出的也差不多是水。首先我们不要任何一个净水滤芯,从水龙头里流出来的水也是可以喝的,虽然不干净。所以得出插件设计的第一个原则:

Openfire插件原则一:不使用任何插件,都不应该影响openfire的基本功能。不写任何插件,openfire也能完成基本的聊天功能。

3、插件原则二

现在有一个人觉得水太脏,需要用碳过滤一下,那么ok,把插件一(碳滤芯)加上,流入插件一的是水,经过处理,就从水龙头中出来了。那么这个人喝到了更干净的水。这里得出第二个插件设计的原则:

Openfire插件原则二:插件可以做一些额外的事情,让整个系统的功能更丰富。例如可以让插件做如下的事情:

1、如果消息内容中有zhengzhi敏感的内容,那么可以通过插件将其过滤掉,不发送给用户。

2、如果插件中有黄色网站的信息,可以提示用户,该网站可能含有木马。QQ就是这样做的。

3、可以为每条消息加一个服务器时间,解决客户端时间不一致的情况。

4、可以在插件中实现推送,当用户不在线的时候,给用户推送信息。也许有的同学,不知道什么是推送,就是android或者苹果手机,经常从顶部从上往下滑下的消息提示。

4、插件原则三

现在有人在水里下了毒,插件二的功能就是当水有毒的时候,就不允许一滴水通过,它干脆让有毒的水直接流入下水道,不流入水龙头。这种情况下,水被抛弃了。这个例子有点高科技哦。不过它要告诉我们插件设计的第三个原则:

Openfire插件原则三:插件可以完全不允许任何数据通过,或者直接抛弃数据,在我们的openfire中,流过插件的数据是数据包Packet,这个数据包可以是Message,IQ、Presence。 我们可以在插件里直接将数据截断,让非法数据不再进入openfire的系统中。

4、插件原则四

最后一个插件是给水加点糖,因为这家人都喜欢喝农夫山泉,所以要加点糖,这个就是伟大的插件四,要卖5000元一个的滤芯呢。

现在问题来了,能不能把插件三放在插件一的位置,肯定不能的,我们总是希望用最干净的水,没有毒的水再放糖吧,有毒的水也放糖,他们家是有钱到用不完吗?所以这里得出插件的第四个原则,

插件原则四:插件是有顺序的,在编写插件的时候,可以给插件一个顺序,从0开始,到很大的整数都可以。0是放在最前面的插件。后面我们会讲一下,这个原则怎么用代码来设置。

5、净水器滤芯就是拦截器

上面的净水器滤芯就是插件,一个插件要实现数据包的Packet拦截,必须要实现PacketInterceptor接口,这个接口就是包拦截器接口,代码如下:

public interface PacketInterceptor {

    void interceptPacket(Packet packet, Session session, boolean incoming, boolean processed)
            throws PacketRejectedException;

}

PacketInterceptor只有一个接口函数interceptPacket,这个函数会在有packet传输到openfire的时候被调用。

那么怎么让openfire知道有一个新的包拦截器进入到openfire系统中了呢?需要向下面的代码一样,向openfire注册包拦截器。

public class ContentFilterPlugin implements Plugin, PacketInterceptor {
    // 拦截器管理器,所有的拦截器都在这里注册
    private InterceptorManager interceptorManager;
	
	// plugin的接口
	public void initializePlugin(PluginManager pManager, File pluginDirectory) {
	    // InterceptorManager是一个单例类
		interceptorManager = InterceptorManager.getInstance();
		// 将拦截器注册进来,这样有Packet来的时候,就会调用interceptPacket
        interceptorManager.addInterceptor(this);
    }

	// plugin的接口	
	public void destroyPlugin() {
	    // 插件卸载时,记得将拦截器从系统中移出。
        interceptorManager.removeInterceptor(this);
    }
	
	// PacketInterceptor的接口,包处理函数,对包的处理,在这里进行。
	public void interceptPacket(Packet packet, Session session, boolean read,
		boolean processed) throws PacketRejectedException {
		
	}
}

下面对代码进行详细解释

1、ContentFilterPlugin类实现了Plugin接口,上一节课说了,这个接口有2个函数initializePlugin和destroyPlugin,分别负责插件的初始化和销毁工作。

2、ContentFilterPlugin类还实现了PacketInterceptor接口,这个接口只有interceptPacket函数需要实现,用来对消息进行拦截。 我们后面的课程会将消息拦截的过程。

6、interceptPacket函数详解

上面的注释,基本写清楚了PacketInterceptor的使用了。下面来谈谈PacketInterceptor的interceptPacket函数,函数原型如下:

void interceptPacket(Packet packet, 
					Session session,
					boolean read,
					boolean processed)

(1)第一个参数packet是在openfire中流动的包,也是xmpp协议中的包。Packet有4种类型:Message、IQ、Presence和Route,Route是xmpp协议中定义的包,仅是openfire为了实现服务器集群中包的转发定义的类型。关于Message、IQ、Presence和Route是什么,我们后面会详细讲解,这里只需要知道他们是客户端与服务器通信的载体就可以了。

(2)参数session:sesison是会话的意思,在网站开发中出现得比较多。这里表示服务器与某个客户端之间的连接,或者服务器与服务器之间的连接。连接的那方就是消息过来的那方,或者消息将要发出去的那方。session这个参数非常有用,它里面存储了很多信息,例如用户的连接、用户的用户名等。

(3)参数read:是一个布尔值,其他版本的openfire中,可能是参数incoming,只是名字改了,但是意思没有变。它表示这条消息是从服务器进来还是从服务器出去。这个参数比较复杂,我们后面会有多节详细讲解。

(4)参数processed:表示这个包是否被openfire处理了。可能你现在对这个参数也比较迷惑,只有下一节课慢慢讲了。

ok,我们下一节课再见,88。

提问或评论

登陆后才可留言或提问哦:) 登陆 | 注册 登陆后请返回本课提问
用户名
密   码
验证码