XWiki支持通知(又名Observation Events),当一个文档被修改,一个文档对象被修改或者一个wiki被创建时可以做一些动作。查看Observation参考文档了解更多内容。
有几种方法来编写事件侦听器,以应对一些事件:
本教程将在几个不同的例子展示所有的技术。
我们的目标是监听DocumentCreatingEvent和DocumentUpdatingEvent事件(注意这些事件会在页面保存之前触发,因此我们代码不需要执行保存操作)。
使用一个wiki组件来实现这个例子。
本例使用{{groovy}}宏,因此需要编程权限。如果是在多租户下的一个wiki,那么意味着需要在main wiki要有编程权限。
按照下列步骤:
xcontext.method.output.value = new DocumentCreatingEvent(), new DocumentUpdatingEvent()
{{/groovy}}
当你保存EventListeners.DocumentSaveListener页面,你定义的组件(你的事件监听器)会自动注册和可用
你可以通过创建一个新的页面或者编辑一个现有的页面来验证它的效果,当你保存时,你应该看到一些额外的内容Some extra content...添加到你的页面底部。
在这个例子中,我们希望通过添加一个名为Main.Logs的页面来记录所有文件的改变。
通过在一个wiki页面使用Groovy来实现。
本例使用{{groovy}}宏,因此需要编程权限。如果是在多租户下的一个wiki,那么意味着需要在main wiki要有编程权限。
{{groovy}} import org.xwiki.observation.* import org.xwiki.observation.event.* import org.xwiki.bridge.event.* import org.xwiki.model.reference.* import org.xwiki.model.* import com.xpn.xwiki.web.* import com.xpn.xwiki.* class LoggingEventListener implements EventListener { def logReference = new EntityReference("Logs", EntityType.DOCUMENT, new EntityReference("Main", EntityType.SPACE)) String getName() { // The unique name of this event listener return "logging" } List<Event> getEvents() { // The list of events this listener listens to return new DocumentUpdatedEvent() } // Called by the Observation Manager when an event matches the list of events returned // by getEvents() void onEvent(Event event, Object source, Object context) { // Prevent infinite recursion since in this example we log to wiki page which // triggers a document change... :) if (source.fullName != "Main.Logs") { def xwiki = context.getWiki() def document = xwiki.getDocument(logReference, context) document.setContent("
如果你想监听其他的事件,你可以在getEvents返回列表中添加其他事件,例如:
...
return [new DocumentUpdateEvent(), new DocumentSaveEvent(), new DocumentDeleteEvent()]
...
我们使用Java来实现这个用例。
注意:我们要监听CommentAddedEvent事件,但是,如果你希望当一个对象被更新时接收通知,那么你应该监听XObjectUpdatedEvent事件(或者希望一个属性被更新时接收通知则监听XObjectPropertyUpdatedEvent事件)。
import java.util.Arrays;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.slf4j.Logger;
import org.xwiki.component.annotation.Component;
import org.xwiki.model.EntityType;
import org.xwiki.model.reference.EntityReference;
import org.xwiki.observation.EventListener;
import org.xwiki.observation.event.Event;
import com.xpn.xwiki.XWikiContext;
import com.xpn.xwiki.doc.XWikiDocument;
import com.xpn.xwiki.internal.event.XObjectAddedEvent;
import com.xpn.xwiki.objects.BaseObject;
import com.xpn.xwiki.plugin.mailsender.MailSenderPluginApi;
@Component
@Named("CommentEventListener")
@Singleton
public class CommentEventListener implements EventListener
{
@Inject
private Logger logger;
private EntityReference commentClassReference = new EntityReference("XWikiComments", EntityType.DOCUMENT,
new EntityReference("XWiki", EntityType.SPACE));
@Override public String getName()
{
return "CommentEventListener";
}
@Override public List<Event> getEvents()
{
return Arrays.<Event>asList(new XObjectAddedEvent());
}
@Override public void onEvent(Event event, Object source, Object data)
{
XWikiDocument document = (XWikiDocument) source;
BaseObject commentObject = document.getXObject(this.commentClassReference);
if (commentObject != null) {
try {
// Get comment
String comment = commentObject.getStringValue("comment");
// Send email
XWikiContext xcontext = (XWikiContext) data;
MailSenderPluginApi mailSender = (MailSenderPluginApi) xcontext.getWiki().getPluginApi("mailsender", xcontext);
mailSender.sendTextMessage("XWiki <xwiki@no-reply>", "john@doe.com",
"[XWiki] Comment added to " + document.toString(), comment);
} catch (Exception e) {
this.logger.error("Failure in comment listener", e);
}
}
}
}
如果你构建遇到一些问题,查看http://dev.xwiki.org/xwiki/bin/view/Community/Building
在测试之前,先确保在你的XWiki管理员后台已经设置Email相关属性。之后,在一个页面添加一条评论,你将会接收到一份邮件!
这个实现不是很好,因为邮件是在页面保存时发送,这是同步的,并且发送一封电子邮件需要一些时间。更好的方式是通过一个单独的线程来异步发送邮件,以便保存可以快速返回而不用等待邮件发送结束。这给我们亲爱的读者当作练习。
如果你使用的是旧版本的XWiki(早于2.0版本),那么你可以查看这个旧的通知教程。