如何从Java Servlet控制器向ZK MVVM模型转发事件/信息
从Java Servlet向ZK MVVM转发事件/信息的实现方案
由于无法使用ZK事件队列/全局命令(依赖当前执行环境)且无第三方事件队列,可采用以下两种轻量方案实现:
方案一:Desktop属性存储 + 客户端轮询
利用ZK的Desktop对象存储Servlet传递的数据,通过ZK页面定时轮询检查数据并触发MVVM处理逻辑,实现简单且兼容性强。
步骤与代码示例
- ZK页面加载时存储Desktop ID到HttpSession
在MVVM的初始化方法中,将当前Desktop的ID存入HttpSession,供Servlet定位目标桌面:
public class MyViewModel extends GenericViewModel { @Init public void init() { String desktopId = Executions.getCurrent().getDesktop().getId(); HttpSession httpSession = (HttpSession) Executions.getCurrent().getNativeSession(); httpSession.setAttribute("zkDesktopId", desktopId); } }
- Servlet中存储数据到目标Desktop
Servlet通过HttpSession获取Desktop ID,定位活跃的ZK Desktop并存储数据:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession httpSession = request.getSession(); String desktopId = (String) httpSession.getAttribute("zkDesktopId"); if (desktopId != null) { Desktop desktop = Sessions.getCurrent().getDesktop(desktopId); if (desktop != null && desktop.isAlive()) { // 自定义数据对象,需实现序列化(集群环境必备) ServletData data = new ServletData(); data.setContent("来自Servlet的业务数据"); // 线程安全操作Desktop属性 desktop.lock(); try { desktop.setAttribute("servletData", data); } finally { desktop.unlock(); } } } response.getWriter().write("数据已提交至ZK桌面"); }
- ZK页面轮询检查并处理数据
使用ZK的Timer组件定时触发MVVM命令,检查Desktop中的数据并处理:
<window viewModel="@id('vm') @init('com.example.MyViewModel')"> <!-- 每2秒轮询一次 --> <timer delay="2000" repeats="true" onTimer="@command('checkAndProcessData')"/> <!-- 展示处理结果 --> <label value="@load(vm.processedResult)"/> </window>
MVVM处理逻辑:
public class MyViewModel extends GenericViewModel { private String processedResult; @Command public void checkAndProcessData() { Desktop desktop = Executions.getCurrent().getDesktop(); desktop.lock(); ServletData data = null; try { data = (ServletData) desktop.getAttribute("servletData"); if (data != null) { // 执行业务处理逻辑 processedResult = "处理完成:" + data.getContent(); // 清空属性,避免重复处理 desktop.removeAttribute("servletData"); // 通知UI更新 BindUtils.postNotifyChange(null, null, this, "processedResult"); } } finally { desktop.unlock(); } } // Getter方法 public String getProcessedResult() { return processedResult; } }
方案二:AuEngine主动推送事件
通过ZK的AuEngine直接向客户端发送异步命令,触发MVVM的指定方法,无需轮询,效率更高。
代码示例
- Servlet中发送AuCommand到ZK客户端
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession httpSession = request.getSession(); String desktopId = (String) httpSession.getAttribute("zkDesktopId"); if (desktopId != null) { Desktop desktop = Sessions.getCurrent().getDesktop(desktopId); if (desktop != null && desktop.isAlive()) { ServletData data = new ServletData(); data.setContent("主动推送的业务数据"); // 构造调用MVVM命令的Au指令 AuCommand cmd = new AuCommand("onCommand", new String[]{"vm.processServletData"}, new Object[]{data}, desktop); // 发送指令到客户端 AuEngine auEngine = desktop.getAuEngine(); auEngine.addAuResponse(new AuResponse(cmd)); auEngine.flush(desktop); } } response.getWriter().write("事件已推送至ZK客户端"); }
- MVVM中接收并处理推送数据
public class MyViewModel extends GenericViewModel { private String processedResult; @Command public void processServletData(@BindingParam("data") ServletData data) { // 执行业务处理 processedResult = "主动推送处理完成:" + data.getContent(); BindUtils.postNotifyChange(null, null, this, "processedResult"); } public String getProcessedResult() { return processedResult; } }
注意事项
- Desktop生命周期检查:Servlet操作前需确认
desktop.isAlive(),避免操作已销毁的桌面。 - 线程安全:操作Desktop属性或AuEngine时,必须使用
desktop.lock()和desktop.unlock()保证线程安全。 - 序列化要求:自定义数据对象需实现
Serializable接口,适配ZK集群环境的数据存储与传输。
内容的提问来源于stack exchange,提问作者Mohammad Ali
相关产品推荐
相关产品推荐

