开发消息拦截器的步骤跟开发简单插件步骤一样,要开发消息拦截器插件,首先继承PacketInterceptor包拦截类,然后在initializelPlugin()方法中注册拦截器,就可以实现interceptPackage()方法中拦截包(即此方法中的packet参数)了。并且,可以通过入参incoming来判断是服务器发送的包还是接受的包(注:true为服务器接收的包;false为发出的包)。processed参数用处暂不明,猜想是对请求做了什么处理的标识,但不影响我们对包进行拦截和处理。

这个扩展方式与前一种相比的好处在于,这种方式不仅没有修改原注册流程的代码,而且最大程度的使用了原注册流程。这样可以避免一些不必要的风险。

  1. package com.bis.plugin.messageplugin;
  2.  
  3. import java.io.File;
  4.  
  5. import org.jivesoftware.openfire.container.Plugin;
  6. import org.jivesoftware.openfire.container.PluginManager;
  7. import org.jivesoftware.openfire.interceptor.InterceptorManager;
  8. import org.jivesoftware.openfire.interceptor.PacketInterceptor;
  9. import org.jivesoftware.openfire.interceptor.PacketRejectedException;
  10. import org.jivesoftware.openfire.session.Session;
  11. import org.xmpp.packet.Packet;
  12.  
  13. public class MessagePlugIn implements Plugin,PacketInterceptor {
  14. private static PluginManager pluginManager;
  15. private InterceptorManager interceptoerManager;
  16.  
  17.  
  18.  
  19. public MessagePlugIn() {
  20. interceptoerManager = InterceptorManager.getInstance();
  21. }
  22.  
  23. @Override
  24. public void initializePlugin(PluginManager manager, File pluginDirectory) {
    interceptoerManager = InterceptorManager.getInstance();
  25. pluginManager = manager;
  26. interceptoerManager.addInterceptor(this);
  27. System.out.println("加载插件成功!");
  28. }
  29.  
  30. @Override
  31. public void destroyPlugin() {
  32. interceptoerManager.removeInterceptor(this);
  33. System.out.println("销毁插件成功!");
  34. }
  35.  
  36. @Override
  37. public void interceptPacket(Packet packet, Session session,
  38. boolean incoming, boolean processed) throws PacketRejectedException {
  39. System.out.println("接收到的消息内容:"+packet.toXML());
  40. }
  41.  
  42. }

1、继承Plugin接口,就是在系统启动的时候会执行initializePlugin()方法,表示这是一个插件类

2、继承PacketInterceptor接口,表示这个类是一个拦截Message的消息类,当拦截的时候,会执行interceptPacket方法

关于openfire是如何管理消息拦截器的?

我们可以看看MessageRouter类的route(Message packet)方法

  1. public void route(Message packet) {
  2. if (packet == null) {
  3. throw new NullPointerException();
  4. }
  5. ClientSession session = sessionManager.getSession(packet.getFrom());
  6. try {
  7. // Invoke the interceptors before we process the read packet
  8. //系统的拦截器就是在这里调用的,遍历动态添加的所有拦截器
  9. InterceptorManager.getInstance().invokeInterceptors(packet, session, true, false);
  10. if (session == null || session.getStatus() == Session.STATUS_AUTHENTICATED) {
  11. JID recipientJID = packet.getTo();
  12.  
  13. // Check if the message was sent to the server hostname
  14. if (recipientJID != null && recipientJID.getNode() == null && recipientJID.getResource() == null &&
  15. serverName.equals(recipientJID.getDomain())) {
  16. if (packet.getElement().element("addresses") != null) {
  17. // Message includes multicast processing instructions. Ask the multicastRouter
  18. // to route this packet
  19. multicastRouter.route(packet);
  20. }
  21. else {
  22. // Message was sent to the server hostname so forward it to a configurable
  23. // set of JID's (probably admin users)
  24. sendMessageToAdmins(packet);
  25. }
  26. return;
  27. }
  28.  
  29. try {
  30. // Deliver stanza to requested route
  31. routingTable.routePacket(recipientJID, packet, false);
  32. }
  33. catch (Exception e) {
  34. log.error("Failed to route packet: " + packet.toXML(), e);
  35. routingFailed(recipientJID, packet);
  36. }
  37. }
  38. else {
  39. packet.setTo(session.getAddress());
  40. packet.setFrom((JID)null);
  41. packet.setError(PacketError.Condition.not_authorized);
  42. session.process(packet);
  43. }
  44. // Invoke the interceptors after we have processed the read packet
  45. //系统的拦截器就是在这里调用的,遍历动态添加的所有拦截器
  46. InterceptorManager.getInstance().invokeInterceptors(packet, session, true, true);
  47. } catch (PacketRejectedException e) {
  48. // An interceptor rejected this packet
  49. if (session != null && e.getRejectionMessage() != null && e.getRejectionMessage().trim().length() > 0) {
  50. // A message for the rejection will be sent to the sender of the rejected packet
  51. Message reply = new Message();
  52. reply.setID(packet.getID());
  53. reply.setTo(session.getAddress());
  54. reply.setFrom(packet.getTo());
  55. reply.setType(packet.getType());
  56. reply.setThread(packet.getThread());
  57. reply.setBody(e.getRejectionMessage());
  58. session.process(reply);
  59. }
  60. }
  61. }
  1. public void route(Message packet) {
  2. if (packet == null) {
  3. throw new NullPointerException();
  4. }
  5. ClientSession session = sessionManager.getSession(packet.getFrom());
  6. try {
  7. // Invoke the interceptors before we process the read packet
  8. //系统的拦截器就是在这里调用的,遍历动态添加的所有拦截器
  9. InterceptorManager.getInstance().invokeInterceptors(packet, session, true, false);
  10. if (session == null || session.getStatus() == Session.STATUS_AUTHENTICATED) {
  11. JID recipientJID = packet.getTo();
  12.  
  13. // Check if the message was sent to the server hostname
  14. if (recipientJID != null && recipientJID.getNode() == null && recipientJID.getResource() == null &&
  15. serverName.equals(recipientJID.getDomain())) {
  16. if (packet.getElement().element("addresses") != null) {
  17. // Message includes multicast processing instructions. Ask the multicastRouter
  18. // to route this packet
  19. multicastRouter.route(packet);
  20. }
  21. else {
  22. // Message was sent to the server hostname so forward it to a configurable
  23. // set of JID's (probably admin users)
  24. sendMessageToAdmins(packet);
  25. }
  26. return;
  27. }
  28.  
  29. try {
  30. // Deliver stanza to requested route
  31. routingTable.routePacket(recipientJID, packet, false);
  32. }
  33. catch (Exception e) {
  34. log.error("Failed to route packet: " + packet.toXML(), e);
  35. routingFailed(recipientJID, packet);
  36. }
  37. }
  38. else {
  39. packet.setTo(session.getAddress());
  40. packet.setFrom((JID)null);
  41. packet.setError(PacketError.Condition.not_authorized);
  42. session.process(packet);
  43. }
  44. // Invoke the interceptors after we have processed the read packet
  45. //系统的拦截器就是在这里调用的,遍历动态添加的所有拦截器
  46. InterceptorManager.getInstance().invokeInterceptors(packet, session, true, true);
  47. } catch (PacketRejectedException e) {
  48. // An interceptor rejected this packet
  49. if (session != null && e.getRejectionMessage() != null && e.getRejectionMessage().trim().length() > 0) {
  50. // A message for the rejection will be sent to the sender of the rejected packet
  51. Message reply = new Message();
  52. reply.setID(packet.getID());
  53. reply.setTo(session.getAddress());
  54. reply.setFrom(packet.getTo());
  55. reply.setType(packet.getType());
  56. reply.setThread(packet.getThread());
  57. reply.setBody(e.getRejectionMessage());
  58. session.process(reply);
  59. }
  60. }
  61. }

最后附上xmpp的相关协议:

  1. .openfire注册相关协议
  2. 1./*用户注册,原本的协议中没有province字段,这里为扩展*/
  3. <iq id="g0G4m-1" to="zhanglj" type="set">
  4. <query xmlns="jabber:iq:register">
  5. <username>re3</username>
  6. <email></email>
  7. <name></name>
  8. <password>1</password>
  9. <province>合肥</province>
  10. </query>
  11. </iq>
  12.  
  13. 2.用户注册成功
  14. <iq type="result" id="g0G4m-1" from="zhanglj" to="re3@zhanglj/Spark 2.6.3"/>
  15.  
  16. 3.用户注册失败
  17. i. 用户名为空:code='500"
  18. <iq type="error" id="g0G4m-1" from="zhanglj" to="re3@zhanglj/Spark 2.6.3">
  19. <query xmlns="jabber:iq:register">
  20. <username/>
  21. <email/>
  22. <name/>
  23. <password>1</password>
  24. <province>合肥</province>
  25. </query>
  26. <error code="500" type="wait">
  27. <internal-server-error xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>
  28. </error>
  29. </iq>
  30.  
  31. ii.密码为空:code='406"
  32. <iq type="error" id="g0G4m-1" from="zhanglj" to="re3@zhanglj/Spark 2.6.3">
  33. <query xmlns="jabber:iq:register">
  34. <username>r</username>
  35. <email/>
  36. <name/>
  37. <password/>
  38. </query>
  39. <error code="406" type="modify"><not-acceptable xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>
  40. </error>
  41. </iq>
  42.  
  43. iii.用户已存在:code='409"
  44. <iq id="g0G4m-1" to="re3@zhanglj/Spark 2.6.3" from="zhanglj" type="error">
  45. <query xmlns="jabber:iq:register">
  46. <username>re5</username>
  47. <email/>
  48. <name/>
  49. <province>合肥</province>
  50. <password>1</password>
  51. </query>
  52. <error code="409" type="CANCEL">
  53. <conflict xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>
  54. </error>
  55. </iq>

https://blog.csdn.net/zhonglunshun/article/details/84695804

开发openfire 消息拦截器插件PacketInterceptor的更多相关文章

  1. 系统开发中使用拦截器校验是否登录并使用MD5对用户登录密码进行加密

    项目名称:客户管理系统 项目描述: 项目基于javaEE平台,B/S模式开发.使用Struts2.Hibernate/Spring进行项目框架搭建.使用Struts中的Action 控制器进行用户访问 ...

  2. (转)C#制作一个消息拦截器

    首先,我们先要制作一个自定义Attribute,让他可以具有上下文读取功能,所以我们这个Attribute类要同时继承Attribute和IContextAttribute. 接口IContextAt ...

  3. 4_4.springboot之Web开发登录和拦截器

    1.登录处理 1).禁用模板引擎的缓存 # 禁用缓存 spring.thymeleaf.cache=false 2).页面修改完用ctrl+f9:重新编译: LoginController @Cont ...

  4. C#制作一个消息拦截器(intercept)1

    首先,我们先要制作一个自己定义Attribute,让他能够具有上下文读取功能,所以我们这个Attribute类要同一时候继承Attribute和IContextAttribute. 接口IContex ...

  5. C# 通过Attribute制作的一个消息拦截器

    首先,我们先要制作一个自己定义Attribute,让他能够具有上下文读取功能,所以我们这个Attribute类要同一时候继承Attribute和IContextAttribute. 接口IContex ...

  6. SpringBoot开发案例之拦截器注入Bean

    前言 由于业务需要,需要在拦截器中操作Redis缓存,按照 controller,service层配置发现无法注入,一直报空指针异常. 解决方案 @Configuration public class ...

  7. wepy 小程序开发(interceptor拦截器 && WXS)

    WePY全局拦截器可对原生API的请求进行拦截. import wepy from 'wepy'; export default class extends wepy.app { constructo ...

  8. 基于Bootstrap和Knockout.js的ASP.NET MVC开发实战 关于 拦截器的 学习 部分

    先贴一段: 下面贴代码: 上面这段代码呢,有几个点迷糊.可以找找看

  9. 小D课堂-SpringBoot 2.x微信支付在线教育网站项目实战_5-10.Springboot2.x用户登录拦截器开发实战

    笔记 10.Springboot2.x用户登录拦截器开发实战     简介:实战开发用户登录拦截器拦截器 LoginInterceptor                  1.实现接口 LoginI ...

随机推荐

  1. iOS 用自签名证书实现 HTTPS 请求的原理

    在16年的WWDC中,Apple已表示将从2017年1月1日起,所有新提交的App必须强制性应用HTTPS协议来进行网络请求.默认情况下非HTTPS的网络访问是禁止的并且不能再通过简单粗暴的向Info ...

  2. linux 下查看磁盘IO状态

    from:脚本之家 linux 查看磁盘IO状态操作 作者:佚名 字体:[增加 减小] 来源:互联网 时间:11-15 15:13:44我要评论 Linux系统出现了性能问题,一般我们可以通过top. ...

  3. [转]shell awk sed tr grep 语法汇总

    tr 基本语法 -c          # 用字符串1中字符集的补集替换此字符集,要求字符集为ASCII  -d          # 删除字符串1中所有输入字符  -s          # 删除所 ...

  4. POJ 2230 Watchcow (欧拉回路)

    Watchcow Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 5258   Accepted: 2206   Specia ...

  5. CGRectMake 延伸

    判断给定的点是否被一个CGRect包含,可以用CGRectContainsPoint函数 BOOLcontains=CGRectContainsPoint(CGRectrect,CGPointpoin ...

  6. 【C语言】字符串常量与指针

  7. RemoteDesktopManager 简单使用说明

    最近项目需要在多台window系统上,安装应用,没错,是window orz..没有了secureCRT putty等好用的窗体工具,真的挺难受的. 爱折腾的博主,百度了下,发现RemoteDeskt ...

  8. Linux 的僵尸(zombie)进程

    可能很少有人意识到,在一个进程调用了exit之后,该进程 并非马上就消失掉,而是留下一个称为僵尸进程(Zombie)的数据结构.在Linux进程的5种状态中,僵尸进程是非常特殊的一种,它已经放弃了几乎 ...

  9. 章节1:SQL语言简易入门

    一.增.删.改.查 1.增(向表格中插入数据): INSERT INTO tb_TableName(ColumnName1,ColumnName2) VALUES(ColumnValue1,Colum ...

  10. 浅谈Mysql 表设计规范(转)

    本文首先探讨下数据库设计的三大范式,因为范式只是给出了数据库设计的原则,并没有告诉我们实际操作中应该怎样操作,应该注意什么,所以我们还会谈下实际工作中需要注意的具体操作问题. 三大范式 首先放出三大范 ...