插件开发入门——过滤脏话
一、 简述
openfire为了扩展其他功能,适用于不同的需求,提供了插件的机制。
提前准备:把openfire源码导入到eclipse 或者 IDEA中。
二、说明
编写openfire插件,必须实现一个插件接口Plugin
,只要实现了这个接口,就会被openfire认为是插件。
public interface Plugin { /** * Initializes the plugin. * * @param manager the plugin manager. * @param pluginDirectory the directory where the plugin is located. */ void initializePlugin( PluginManager manager, File pluginDirectory ); /** * Destroys the plugin.* * Implementations of this method must release all resources held * by the plugin such as file handles, database or network connections, * and references to core Openfire classes. In other words, a * garbage collection executed after this method is called must be able * to clean up all plugin classes. */ void destroyPlugin();}
1. initializePlugin初始化插件
对数据库连接、rides等初始化。
2. destroyPlugin销毁插件
在这里必须释放所有用到的资源。
3. 插件启动
initializePlugin有三种情况会被调用,上传插件、重启插件、openfire启动时。
4. 插件目录结构
插件目录在:\src\plugins\
下,一个插件一个目录。
举例:fastpath插件目录结构介绍
目录结构:
\src\plugins\fastpath\src\plugins\fastpath\lib\src\plugins\fastpath\src\src\plugins\fastpath\logo_small.gif\src\plugins\fastpath\logo_large.gif\src\plugins\fastpath\changelog.html\src\plugins\fastpath\plugin.xml\src\plugins\fastpath\readme.html
- lib:引用的jar包
- src:src是源代码目录
- logo_large.gif和logo_small.gif表示的是插件的logo,也支持png格式的文件,大小分别是32_32和16_16
- changelog.html: 是发布日志,记录插件各个版本的变化情况。
- plugin.xml:插件的配置文件。这个文件非常重要,openfire需要读取插件信息,例如插件的启动类是哪一个,需要在plugin.xml中定义
- readme.html:插件的介绍和使用
三、编写过滤脏话插件
过滤脏话,就需要获取到消息内容,这个插件就要实现对数据包Packet拦截,必须要实现PacketInterceptor接口,这个接口就是包拦截器接口。
public interface PacketInterceptor { /** * Invokes the interceptor on the specified packet. The interceptor can either modify * the packet, or throw a PacketRejectedException to block it from being sent or processed * (when read).* * An exception can only be thrown when processed is false which means that the read * packet has not been processed yet or the packet was not sent yet. If the exception is thrown * with a "read" packet then the sender of the packet will receive an answer with an error. But * if the exception is thrown with a "sent" packet then nothing will happen.
* * Note that for each packet, every interceptor will be called twice: once before processing * is complete (processing==true) and once after processing is complete. Typically, * an interceptor will want to ignore one or the other case. * * @param packet the packet to take action on. * @param session the session that received or is sending the packet. * @param incoming flag that indicates if the packet was read by the server or sent from * the server. * @param processed flag that indicates if the action (read/send) was performed. (PRE vs. POST). * @throws PacketRejectedException if the packet should be prevented from being processed. */ void interceptPacket(Packet packet, Session session, boolean incoming, boolean processed) throws PacketRejectedException;}interceptPacket这个函数会在有packet传输到openfire的时候被调用。
1. 创建插件文件夹
仿照上面介绍的目录创建。添加src、plugin.xml等。
2. 将插件添加到Java Build Path中
创建了上面的文件夹,不添加到Java Build Path中是不能编译的。
3. 创建MessageFilterPlugin.java
package com.lwenhao;import java.io.File;import org.jivesoftware.openfire.container.Plugin;import org.jivesoftware.openfire.container.PluginManager;import org.jivesoftware.openfire.muc.MUCEventDispatcher;import org.jivesoftware.openfire.muc.MUCEventListener;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.xmpp.packet.Message;import com.group.action.GroupMessage;import com.muc.interceptor.MUCEventListenerImpl;/** * 插件的入口类,负责注入这个插件的功能 * @author liuwenhao * */public class MessageFilterPlugin 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() { // 插件卸载时,记得将拦截器从系统中移出。 //当插件被卸载的时候,主要通过openfire管理控制台卸载插件时,被调用。 //注意interceptorManager的addInterceptor和removeInterceptor需要成对调用。 interceptorManager.removeInterceptor(this); } // PacketInterceptor的接口,包处理函数,对包的处理,在这里进行。 public void interceptPacket(Packet packet, Session session, boolean read, boolean processed) throws PacketRejectedException { //processed为false,表示本条消息没有被openfire处理过。 if (false == incoming && processed) { // packet可能是IQ、Presence、Message,这里当packet是message的时候,进行处理。 if (packet instanceof Message) { // 将packet强制转换为Message Message msg = (Message)packet; // 取得message中的body内容,就是消息正文 String body = msg.getBody(); // 如果内容中包含fuck,则拒绝处理消息 if(body != null && body.contains("fuck")){ //这里通过抛出异常的方式,来阻止程序流程继续执行下去。 PacketRejectedException rejectedException = new PacketRejectedException(); rejectedException.setRejectionMessage("fuck is error"); throw rejectedException; } } } }}
4. 创建或者修改plugin.xml
class:插件的启动类name:插件名称description:描述author:作者version:版本date:日期minServerVersion:这个插件需要在openfire为4.2.2以上的版本运行 com.lwenhao.MessageFilterPlugin MessageFilterPlugin Message Filter Plugin liuwenhao 0.0.1 09/03/2018 4.2.2
5.编译插件
在\build\build.properties.template
修改
## Directory where the jar files will be deployed (see the deployjar task)#deploy.jar.dir=plugin = MessageFilterPlugin## Directory where plugin development is done. This is assumed to be the# root directory:## /home/joeuser/java/myplugins/ <- Point to this directory# |- fooplugin/# |- barplugin/#plugin.dev.dir= MessageFilter## Path to your Install4j installation. Typically this is c:\Program Files\install4j# This property is set by default in the build.xml file as c:\Program Files\install4j so# if you used the standard location you won't need to edit the property below.## installer.install4j.home=## Path to a bundled JRE you wish to use with the installer.rpm ant target#jre.bundle.location=
Eclipse->Window->Show View->Othre->Ant->Ant
双击 plugins编译插件,即可在目录\target\openfire\plugins中找到插件
6.运行插件
上传到openfire控制台就可以了