这一章主要讲插件的实际和使用.
对插件的剖析
插件是提供某些方法的组件.这些方法供当前事件上下文(eventContext)(
类型为MachII.framework.EventContext的对象)在请求的生命周期的不同点调用:
1. preProcess() –
在每个请求的开始被调用:eventContext将当前事件放入事件队列,但getCurrentEvent()
不会返回这个事件(见处理请求里的第一个事件一节).
2. preEvent() – 在执行相关事件句柄标签前立即调用各个事件:eventContext包含当前事件(那个将被触发的事件).
3. preView() – 在执行相关页面标签前立即调用各个页面:eventContext包含当前页面(那个将被触发的页面).
4. postView() - 在执行相关页面标签后立即调用各个页面:eventContext包含当前页面(那个执行完毕的页面).
5. postEvent() - 在执行相关事件句柄标签后立即调用各个事件:eventContext包含当前事件(那个执行完毕的事件).
6. postProcess() - 在每个请求的结束被调用:eventContext将不再包含当前事件.
7. handleException() – 在异常被抛回框架时调用: eventContext包含当前事件(如果有的话).这个插件方法同样传递给异常对象(类型为MachII.util.Exception).
插件在需要的时候可以定义configure()方法来实现初始化—这将被框架自动调用.和Mach-II框架的其他部件一样,插件也被储存在application域,所以它们的实例变量是有效的application域变量.
最简单的插件像这样子:
<cfcomponent extends="MachII.framework.Plugin">
<cffunction name="configure" returntype="void" access="public" output="false">
<!--- perform any initialization --->
</cffunction>
<cffunction name="preEvent" returntype="void" access="public" output="false">
<cfargument name="eventContext" type="MachII.framework.EventContext" required="yes" />
<!--- perform processing prior to every event being handled --->
</cffunction>
</cfcomponent>
这个插件重写了preEvent()方法,其实它可以重写以上七种方法的任何一种.
插件被声明在mach-ii.xml
的<plugins> .. </plugins>
标签里:
<plugin name="pluginName" type="Path.To.YourPlugin" />
你也可以为插件定义变量:
<plugin name="pluginName" type="Path.To.YourPlugin">
<parameters>
<parameter name="param1" value="value1" />
<parameter name="param2" value="value2" />
</parameters>
</plugin>
这样可以为param1
和 param2
提供默认参数(分别是value1
和 value2
).
handleException()
插件指针
你可以使用异常事件或者单一的事件句柄来触发异常.对于很多程序而言,这是是可以完全可行的.你也可以通过在插件上实现handleException()方法的方式,添加自定义异常.这个插件指针是在框架遭遇异常之后,通告和触发异常事件之前,被执行.在执行这个插件指针之后,事件队列将被清除,特定的异常事件(定义在mach-ii.xml的<properties>部分)被通告和触发.
不可以在handleException()中抛出异常或使用abortEvent()—这两种操作会导致未被触发的异常,并显示给终端用户.不可以通告新的事件(因为事件队列在handleException()被执行后已经被清除).你可以可以添加信息给当前事件对象,它们以后可以被异常事件句柄接收到.
<cfif arguments.eventContext.hasCurrentEvent()>
<cfset arguments.eventContext.getCurrentEvent().setArg("argName",argValue) />
</cfif>
在遭遇异常的时候,这样做可以设置事件变量argName值为argValue,如果有一个事件被定义的话.
在异常事件句柄内部,当前事件是带有以下变量的异常事件本身:
- exception - MachII.util.Exception对象,包含了原始异常的详细信息;
- exceptionEvent - MachII.framework.Event对象,在异常抛出时被触发(这仅出现在异常发生时存在被定义的事件的情况下).
你可以在事件句柄里使用<event-mapping>
来对异常事件提供更精细的操作.
处理请求里的第一个事件
因为”当前事件”没有在preProess()执行阶段被调用,不容易看出如何在每个请求里处理第一个事件
:
cffunction name="preProcess" returntype="void">
<cfargument name="eventContext" type="MachII.framework.EventContext" />
<!--- peek at the first event in the queue: --->
<cfset var firstEvent = arguments.eventContext.getNextEvent() />
<!--- ...process firstEvent here... --->
</cffunction>
注意:在
1.0.9
之前,以上对getNextEvent()
的调用会从队列里清除第一个事件!