You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从Java Servlet控制器向ZK MVVM模型转发事件/信息

从Java Servlet向ZK MVVM转发事件/信息的实现方案

由于无法使用ZK事件队列/全局命令(依赖当前执行环境)且无第三方事件队列,可采用以下两种轻量方案实现:

方案一:Desktop属性存储 + 客户端轮询

利用ZK的Desktop对象存储Servlet传递的数据,通过ZK页面定时轮询检查数据并触发MVVM处理逻辑,实现简单且兼容性强。

步骤与代码示例

  1. 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);
    }
}
  1. 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桌面");
}
  1. 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的指定方法,无需轮询,效率更高。

代码示例

  1. 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客户端");
}
  1. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 06:35:33