高级自定义 > 服务和基础结构自定义 > 开发服务器逻辑 > 服务事件管理
  
服务事件管理
直接开展点对点合作与协作是服务间通信的一种方式。无需任何特殊机制来支持此类通信,原因在于已将其定义为显式调用。
但是,通过即插即用体系结构,服务变得更加独立,而与其他服务不相关。为了便于在这些自治服务之间进行服务间通信,需要常规机制来在这些服务之间传递信息并管理取消排序的同步通信。
每个服务负责指定当服务中发生其他服务可能关注的重要事件时可以激发的服务事件。此外,每个服务必须建立针对其他服务事件的监听程序,以便收到系统内发生的其他重大事件的通知并作出反应。
服务事件注册
服务可以在启动时向 wt.services.StandardManager 注册其事件。在启动时注册服务事件可使进程了解事件,例如访问控制。以下示例说明了如何在已覆盖的 wt.properties.StandardManager 的 registerEvents 方法中为版本控制服务注册事件:
* 
注册事件的一种更隐式的方法是不采用 registerEvents 方法注册事件,而是允许在首次激发事件时对其进行注册。发生这种情况后,将通知所有订阅此事件的监听程序。
服务事件订阅
为了通知服务系统内发生的事件,必须订阅所关注的每个特定服务事件。要执行此操作,必须调用 wt.services.ManagerService.addEventListener 方法,其中包含监听程序和标识所关注事件的键。
订阅期间指定的监听程序必须实现 wt.events.KeyedEventListener 接口。其可定义 notifyEvent 和 notifyVetoableEvent 方法。Wt.properties ServiceEventListenerAdapter 类作为实用程序提供,监听程序可对其进行扩展并仅覆盖通知所需的方法。notifyEvent 是可在所有订阅情况下使用的常规方法。notifyVetoableEvent 方法更专业;其预期用途是提供一种通过异常否决事件的方法。
通常,事件监听程序是使用内部类的匿名实例或命名实例实现的。这允许在不实现 wt.events.KeyedEventListener 接口的情况下设计外部类。这将使外部类保持为纯类,原因在于其类型直接反映其目的,而无需实现监听程序接口。以下示例将说明如何覆盖 performStartupProcess 方法以及定义和添加特定事件的监听程序:
服务事件通知
订阅特定事件的所有监听程序的列表由 ManagerService 维护。此列表以无序方式进行遍历,并使用同步 Java 方法调用依次执行每个监听程序。监听程序通知方法在与事件发射器相同的线程和数据库事务处理中执行。这意味着,由监听程序响应通知调用而执行的数据库操作包括在事件发射器的事务中。以下示例显示了诸如 PersistenceManagerEvent.PREPARE_FOR_MODIFICATION 之类事件的发送:
服务事件异常处理
当监听程序否决事件时,会通过抛出异常来执行此操作。抛出异常时,此事件已通知的每个监听程序都可以通过以下方式处理该异常:传递异常、捕获并重新抛出异常以进行清理,或者通过实现 "finally" 子句进行清理。
如前所述,事件通知在与事件发射器相同的线程和事务处理框架内进行发送。这意味着,如果有其他监听程序否决,则事件发射器必须回滚已进行的任何数据库更新。以下示例说明了此指南。如果否决 POST_STORE 事件,则控制将传输到 "finally" 子句,其中的事务处理将会回滚,原因在于从未到达将事务处理设置为空的行。
服务事件约定
任何特定服务事件的含义都由事件的设计者来处理。事件应包括事件监听程序进行后续处理所需的所有信息。wt.events 包包括基本事件类 wt.events.KeyedEvent,可以对其进行扩展以创建新的事件类型。
公用事件设计模式包括预事件和后事件。预事件用于向监听程序指示事件即将开始。这些事件通常旨在为监听程序提供验证和可能拒绝事件的机会。后事件用于通知监听程序事件已完成。当服务由于事件而需要执行某种后处理时,这类事件最有用。并非所有事件都必须是预事件或后事件。事件的单数定义可用于指示某些特殊具体值 (可能已发生也可能尚未发生)。