首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网站开发 > Web前端 >

事件监听跟处理2

2012-11-12 
事件监听和处理2button labelStart Working Thread ??????? attribute nameonClick ???????????

事件监听和处理2

<button label="Start Working Thread">

??????? <attribute name="onClick">

?????????????? timer.start();

?????????????? Label label = test.WorkingThread.asyncCreate(desktop);

?????????????? main.appendChild(label);

?????????????? timer.stop();

??????? </attribute>

</button>

<timer id="timer" runing="false" delay="1000" repeats="true"/>

</window>


注意我们需要使用timer来真正恢复被挂起的事件监听器(onclick)。这看起来是多余的,但是归因于

http的限制:为了保持web页面在浏览器中的alive,当事件处理进程被挂起的时候我们必须返回回应。

然后,工作线程完成了工作,唤醒了事件监听器,http的请求已经gone了。因此,我们需要”piggyback

”这个结果,这就是timer被使用的原因。


更准确的来说,当工作进程唤醒了事件监听器,ZK只是把它加到一个等待队列中。当另一个http请求到

达的时候,监听器才真正的恢复。(在上面的例子中,是onTimer事件)


在这个简单里例子中,我们对onTimer事件什么都没做。对于一个sophisticated应用,你可以使用它来

返回处理的状态。


另一个事例:没有挂起和恢复

没有挂起和恢复来执行一个长时间的操作是可能的。当同步代码对于调试来说太复杂的情况下是有用的


主意很简单。工作进程在一个临时空间里保存结果,然后onTimer事件监听器将结果弹出到桌面。

//WorkingThread2

package test;

public class WorkingThread2 extends Thread

{

private static int _cnt;

private final Desktop _desktop;

private final List _result;

public WorkThread2(Desktop desktop,List result)

{

??????? _desktop = desktop;

??????? _result=result;

}

public void run(){

??????? _result.add(new Label("Execute "+ ++_cnt));

}

}


然后,在onTimer事件监听器上面追加labels

?

<window id = "main" title="working thread2">

<zscript>

int numpending = 0;

List result=Collections.synchronizedList(new LinkedList());

</zscript>

<button label="start working thread">

??????? <attribute name="onClick">

?????????????? ++numpending;

?????????????? timer.start()

?????????????? new test.workingthread2(desktop,result).start();

??????? </attribute>

</button>

<timer id="timer" running="false" delay="1000" repeats="true">

??????? <attribute name="onTimer">

?????????????? while(!result.isEmpty())

?????????????? {

????????????????????? main.appendChild(result.remove(0));

????????????????????? --numpending;

?????????????? }

?????????????? if(numpending==0)time.stop();

??????? </attribute>

</timer>

</window>


初始和清除事件处理线程
在处理每个事件之前初始化


一个事件监听器是在一个事件处理线程中执行的。有时,你不得不在处理所有事件之前初始该线程。


一个典型的例子是初始认证所使用的线程。一些j2ee或者web容器在thread local storage中存储着认证

信息,因此它们可以在需要时自动进行重复认证。


为了进行事件处理线程的初始化,你需要在web-inf/zk.xml文件注册一个继承自

org.zkoss.zk.ui.event.EventThreadInit接口的类。


一旦进行了注册,在开始一个事件处理线程之前,在主线程中一个指定类的实例就被创建了。然后在处

理其他事情之前,该实例的init方法在事件处理线程的上下文中被调用了。


注意那个构造体和init方法是在不同的线程中被调用的,因此开发者可以从一个线程获得线程独立的数

据发送到另一个线程。


下面是jboss的认证机制的例子。在这个例子中,我们在构造体中获得储藏在servlet线程中的信息。然

后,我们在init方法调用的时候初始事件处理线程。


import java.security.Principal;

import org.jboss.security.SecurityAssociation;

import org.zkoss.zk.ui.Component;

import org.zkoss.zk.ui.event.Event;

import org.zkoss.zk.ui.event.EventThreadInit;


public class JBossEventThreadInit implements EventThreadInit

{

?????? private final Principal _principal;

?????? private final Object _credential;


?????? public JBossEventThreadInit()

?????? {

????????????? _principal=SecurityAssociation.getPrincipal();

????????????? _credential=SecurityAssociation.getCredential();

?????? }


?????? public void init(Component comp,Event evt)

?????? {

????????????? SecurityAssociation.setPrincipal(_principal);

????????????? SecurityAssociation.setCredential(_credential);

?????? }

}


然后在web-inf/zk,xml中,如下进行注册:

<zk>

?????? <listener>

????????????? <listener-class>JBossEventThreadInit</listener-class>

?????? </listener>

</zk>


在处理完每个事件后清除
同样的,你可能不得不在处理完一个事件后清除一个事件处理进程。


典型的例子是关闭一个transaction,如果它没有被适当的关闭。


为了清除一个事件处理线程,你需要注册一个实现org.zkoss.zk.ui.event.EventThreadCleanup接口的

监听类,然后在web-inf/zk.xml中注册。


<zk>

?????? <listener>

????????????? <listener-class>my.MyEventThreadCleanup </listener-class>

?????? </listener>

</zk>

热点排行