9. Tigase中的EventBus API

EventBus是一种自定义发布-订阅机制,它允许在Tigase服务器中使用事件监听器。有关EventBus及其功能的更详细概述,请访问 管理指南

9.1. EventBus API

要创建EventBus的实例,请使用以下代码:

EventBus eventBus = EventBusFactory.getInstance();

备注

请记住,EventBus是异步的。所有处理程序都在与最初触发事件的线程不同的线程中调用。

9.1.1. 事件

事件可以用两种方式定义:作为一个类 或作为XML元素(自8.2版起已弃用基于XML/元素的事件,并将在9.0 版中删除).

序列化事件类。

public class SampleSerializedEvent implements Serializable {
    private JID data;
    public JID getData() {
        return this.data;
    }
    public void setData(JID data) {
        this.data = data;
    }
}

事件类。

public class SampleEvent {
    private JID data;
    public JID getData() {
        return this.data;
    }
    public void setData(JID data) {
        this.data = data;
    }
}

XML元素事件(已弃用)

<EventName xmlns="tigase:demo">
  <sample_value>1</sample_value>
</EventName>

备注

定义为XML元素和实现 Serializable 接口的类的事件将分发到集群中的所有服务器。事件 SampleEvent 将仅在触发事件的同一实例中广播。

9.1.2. 基于类的事件的要求

  • 默认的、显式的、公共的、无参数的构造函数是强制性的。

  • 如果事件应该被传递到所有集群节点,那么它 必须 实现 Serializable 接口。

  • 变量序列化遵循 Serializable 语义,这意味着 finalstatictransient 字段将被跳过。更重要的是,具有 null 值的字段也不会被序列化。

9.1.3. 基于类的事件的序列化

基于类的事件被序列化(如果需要并且可能的话)到XML元素。 XML元素的名称取自类的全名:

基于类的事件序列化为XML。

<net.tigase.sample.SampleSerializedEvent>
    <data>[email protected]</data>
</net.tigase.sample.SampleSerializedEvent>

9.1.4. 触发事件

要触发事件,只需获取EventBus的实例并调用方法 fire()

触发序列化事件。

EventBus eventBus = EventBusFactory.getInstance();
SampleSerializedEvent event = new SampleSerializedEvent();
eventBus.fire(event)

触发简单事件。

EventBus eventBus = EventBusFactory.getInstance();
SampleEvent event = new SampleEvent();
eventBus.fire(event)

基于XML元素的触发事件(已弃用)

EventBus eventBus = EventBusFactory.getInstance();
Element event = new Element("tigase.eventbus.impl.Event1");
eventBus.fire(event)

9.1.5. 处理事件

要处理触发的事件,我们必须在EventBus中注册监听器。注册监听器后,EventBus会自动在集群中的所有实例中订阅此类事件。

取决于预期的事件类型,我们必须决定我们应该注册哪种类型的监听器。

处理基于类的事件

此选项仅用于基于类的事件。是否是序列化类都没有关系。

eventBus.addListener(SampleEvent.class, new EventListener<SampleEvent>() {

    @Override
    public void onEvent(SampleEvent event) {
    }
});

为了使注册监听器更容易,您可以使用EventBus中的方法 registerAll()。此方法注册给定类的所有方法,由 @HandleEvent 注释为声明为方法参数的事件的侦听器。

public class SomeConsumer {

    @HandleEvent
    public void event1(Event12 e) {
    }

    public void initialize() {
        eventBus.registerAll(this);
    }
}

处理XML事件

要处理XML事件,我们必须为特定事件包和名称注册侦听器。在我们的示例中,包是空的,因为事件名称没有声明包(另请参阅 过滤事件)。

eventBus.addListener("", "EventName", new EventListener<Element>() {
    @Override
    public void onEvent(Element event) {

    }
});
eventBus.addListener("tigase.eventbus.impl", "Event1", new EventListener<Element>() {
    @Override
    public void onEvent(Element event) {

    }
});

因为序列化的类事件,ale转换为XML元素,所以我们能够侦听基于类的事件的XML表示。为此,我们必须为特定的包和类名注册监听器:

eventBus.addListener("net.tigase.sample", "SampleSerializedEvent", new EventListener<Element>() {
    @Override
    public void onEvent(Element event) {

    }
});

重要

在其他集群节点上创建的XML事件,将属性 remote 设置为 true,属性 source 设置为事件创建者节点名称:

<EventName xmlns="tigase:demo" remote="true" source="node1.example">
  <sample_value>1</sample_value>
</EventName>

过滤事件

有时您可能希望使用同一个处理程序接收多种事件。 EventBus有非常简单的泛化机制:

eventBus.addListener("net.tigase.sample", null,  event -> {});
eventBus.addListener(null, null,  event -> {});
  • 将为具有给定包名称(基于XML或基于序列化类)的每个事件调用此侦听器。

  • 将为所有事件(基于XML或基于序列化类)调用此侦听器。

对于基于类的事件,EventBus正在检查类继承。

class MainEvent { }
class SpecificEvent extends MainEvent {}

eventBus.addListener(SpecificEvent.class, event -> {});
eventBus.addListener(MainEvent.class, event -> {});

eventBus.fire(new SpecificEvent());
  • 将被调用,因为这是 SpecificEvent 的严格监听器。

  • 将被调用,因为 SpecificEvent 扩展了 MainEvent