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

Vaadin如何从JavaScript取值到Java?Leaflet地图边界框问题

Vaadin获取Leaflet地图getBounds()结果的正确方案

解决第一种方法的结果传递问题

第一种方法能拿到结果但无法带出lambda,本质是异步回调的执行时机问题——lambda是在JS结果返回后才执行的,主线程不会等待它。你需要把所有依赖该结果的逻辑都放在lambda内部,如果要操作Vaadin组件(比如更新UI),必须通过UI.access()确保线程安全:

String js = map.clientComponentJsAccessor();
PendingJavaScriptResult executeJs = UI.getCurrent().getPage().executeJs("return " + js + ".getBounds()");
executeJs.then(json -> {
    // 在这里处理拿到的bounds结果
    String boundsJson = json.toJson();
    System.out.println("Json: " + boundsJson);
    
    // 如果要更新UI组件,必须用UI.access保证线程安全
    UI.getCurrent().access(() -> {
        // 示例:更新标签内容
        boundsLabel.setText("当前地图边界:" + boundsJson);
        // 或执行业务逻辑,比如保存到数据库
        saveBoundsToDatabase(boundsJson);
    });
});

规避第二种方法的IllegalStateException

第二种方法用get()阻塞线程是Vaadin严格禁止的——UI线程持有Session锁,而JS结果返回需要发起新的请求,这个请求同样需要Session锁,会导致死锁。绝对不能在UI线程中阻塞等待异步结果,必须改用异步回调的方式处理(即上述第一种方法的正确用法)。

更优方案:使用@ClientCallable主动接收结果

如果需要在地图视图变化时自动获取边界(比如用户拖动地图后),可以通过Leaflet的事件监听,结合Vaadin的@ClientCallable注解,让前端主动把结果发送到服务端,无需主动调用executeJs:

1. 服务端代码

在你的View或Component中定义可被前端调用的方法:

@ClientCallable
public void onMapBoundsChanged(String boundsJson) {
    // 处理拿到的边界数据
    System.out.println("更新后的地图边界:" + boundsJson);
    // 执行UI更新或业务逻辑
    UI.getCurrent().access(() -> {
        // 这里写UI更新逻辑,比如刷新数据列表
    });
}

2. 前端JS代码

在Leaflet地图初始化后,监听moveend事件,触发时调用服务端方法:

// 假设你的Leaflet地图实例为map
map.on('moveend', function() {
    var bounds = map.getBounds();
    // 调用服务端的onMapBoundsChanged方法,传递边界的JSON字符串
    $0.server.onMapBoundsChanged(JSON.stringify(bounds));
});

这里的$0是Vaadin组件的客户端引用,也可以替换成你通过clientComponentJsAccessor()获取的变量。

这种方式更符合Vaadin的事件驱动模型,能自动捕获地图视图变化后的边界数据。

内容的提问来源于stack exchange,提问作者padmalcom

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 19:32:40