使用zkoss Web UI框架时,有没有一种方法检查会话超时或丢失连接?问题是,即使我关闭服务器,重新部署或重新启动它,UI仍将显示在浏览器中。
用户只有在尝试与用户界面进行互动时才会发现错误(例如点击按钮)。它会弹出会话超时信息或服务器无法访问的信息。
我正在寻找的是客户端上可以立即(或在合理的短时间内)通知用户的内容。当会话丢失,服务器出现故障或无法访问时,会出现一些弹出窗口,告诉用户出现问题(这样他就可以立即刷新或采取其他措施)。
我正在查看文档,但他们没有说明这个案例的具体内容。会话设置包括限制,保持活动以防止会话超时,但这就是它。
我正在考虑一些定期ping服务器的自定义javascript(可能是一个特殊的servlet,也可以让脚本知道会话超时),但我更喜欢zk框架的原生内容。当连接丢失时,zk计时器组件似乎停止运行,但它不会触发错误弹出。
答案 0 :(得分:3)
我将发布tommorow代码,告诉你如何为所有登录的客户端分发消息。
同时,这里是代码,您可以实现在会话超时激活之前通知用户(不是服务器重启):
public class SessionTimeOutExecListener implements ExecutionInit, UiLifeCycle {
private String timerId = "timeoutNotifyTimer";
public void init(Execution exec, Execution parent) throws Exception {
Timer timer = (Timer) exec.getDesktop().getAttribute(timerId);
if (timer != null) {
if (isSendbyMsgBox(timer, exec))
return;
timer.stop();
timer.start();
}
}
private boolean isSendbyMsgBox(Timer timer, Execution exec) {
HttpServletRequest hreq = (HttpServletRequest)exec.getNativeRequest();
for (int j = 0;; ++j) {
final String uuid = hreq.getParameter("uuid_"+j);
if (uuid == null)
break;
if (uuid.equals(timer.getUuid()))
return true;
}
return false;
}
public void afterComponentAttached(Component comp, Page page) {
}
public void afterComponentDetached(Component comp, Page prevpage) {
}
public void afterComponentMoved(Component parent, Component child,
Component prevparent) {
}
public void afterPageAttached(Page page, Desktop desktop) {
Object obj = desktop.getAttribute(timerId);
if (obj == null) {
int tmout = desktop.getWebApp().getConfiguration()
.getSessionMaxInactiveInterval();
final Timer timer = new Timer((tmout - 2) * 1000);
timer.addEventListener(Events.ON_TIMER, new EventListener() {
public void onEvent(Event event) throws Exception {
Messagebox.show("Your session are about to be expired",
"Information", Messagebox.OK,
Messagebox.INFORMATION, new EventListener() {
@Override
public void onEvent(Event event) throws Exception {
if (Messagebox.ON_OK.equals(event.getName())){
timer.start();
}
}
});
}
});
timer.setPage(page);
desktop.setAttribute(timerId, timer);
timer.start();
}
}
public void afterPageDetached(Page page, Desktop prevdesktop) {
}
}
<listener>
<listener-class>test.MyExecListener</listener-class>
</listener>
就像我说的,这是用于向所有活动会话发送消息的代码 首先是一个可以发送消息的简单页面。
<?xml version="1.0" encoding="UTF-8"?>
<window xmlns="http://www.zkoss.org/2005/zul" apply="org.zkoss.bind.BindComposer"
viewModel="@id('vm') @init('be.chillworld.MessageVM')" width="100%" height="100%">
<textbox value="@bind(vm.message)"/>
<button onClick="@command('sendMessage')" label="Send"/>
</window>
正如您所看到的,它是MVVM但不用担心,您也可以在MVC项目中插入它,因为我使用EventQueue
然后我们需要一个所有页面的监听器,因此最佳做法是创建一个抽象VM或扩展您使用的Composer。
package be.chillworld;
import org.zkoss.bind.annotation.Init;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.EventQueues;
import org.zkoss.zk.ui.util.Clients;
/**
*
* @author chillworld
*/
public abstract class AbstractVM {
@Init
public void abstractInit() {
EventQueues.lookup("globalMessage", EventQueues.APPLICATION, true).subscribe(new EventListener<Event>() {
public void onEvent(Event event) throws Exception {
if ("onSendMessage".equals(event.getName())) {
Clients.showNotification(String.valueOf(event.getData()));
}
}
});
}
}
因此,当我们得到活动时,这实际上就是我们要做的事情 如果你想制作一个基本的作曲家,你可以这样做:
package be.chillworld;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.EventQueues;
import org.zkoss.zk.ui.select.SelectorComposer;
import org.zkoss.zk.ui.util.Clients;
/**
*
* @author chillworld
*/
public class BasicComposer extends SelectorComposer<Component> {
@Override
public void doAfterCompose(Component comp) throws Exception {
super.doAfterCompose(comp);
EventQueues.lookup("globalMessage", EventQueues.APPLICATION, true).subscribe(new EventListener<Event>() {
public void onEvent(Event event) throws Exception {
if ("onSendMessage".equals(event.getName())) {
Clients.showNotification(String.valueOf(event.getData()));
}
}
});
}
}
不要忘记为每个视图延长BasicComposer
或AbstractVM
这就是为什么我问你是否使用pagetemplates,如果你有一个每个页面的主模板,你只需将它插入那里,每个页面都会有eventlistener的订阅,所以你不必使用{{1} }或BasicComposer
Oke,现在我们为message.zul创建了viewmodel。
AbstractVM
正如您所看到的,我会扩展package be.chillworld;
import org.zkoss.bind.annotation.Command;
import org.zkoss.bind.annotation.Init;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventQueues;
import org.zkoss.zk.ui.util.Clients;
/**
*
* @author chillworld
*/
public class MessageVM extends AbstractVM {
private String message;
@Init(superclass = true)
public void init(){}
@Command
public void sendMessage () {
if (message==null || message.trim().isEmpty()) {
Clients.showNotification("Please enter something to send.");
} else {
System.out.println("posting event");
EventQueues.lookup("globalMessage", EventQueues.APPLICATION, true).publish(new Event("onSendMessage", null, message));
}
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
,但 1部分甚至非常重要然后只是扩展它,即AbstractVM
正如您所看到的,我再次声明了一个init方法,但我在注释中说@Init
。
如果我们不这样做,那么来自abstractVM的init方法永远不会被触发!强>
对于BasicComposer,它是不同的,如果您覆盖superclass = true
方法,则始终调用doAfterCompose
以便始终执行。
您可以在1台电脑上使用多个会话进行测试,如下所示:
super
放入String.valueOf(Sessions.getCurrent())
)希望这可以帮助您解决问题。