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

Vaadin 21如何处理或修改服务器返回的无效JSON错误

Vaadin 21:解决跨浏览器登录导致的「Invalid JSON From server」错误问题

问题根源

当你在其他浏览器登录导致当前会话失效时,后端大概率直接重定向到了登录页面(返回HTML内容),但Vaadin客户端此时正期望接收JSON格式的响应,因此解析失败抛出「Invalid JSON From server」错误,而非触发你预设的会话过期系统消息。

解决思路与实现

1. 调整会话失效后的响应策略,避免直接返回HTML

在Spring Security配置中,针对Vaadin专属请求(框架内部请求、视图路由等),当会话失效时返回401状态码而非重定向到登录页,让Vaadin客户端触发会话过期处理逻辑:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()
            .requestMatchers(VaadinWebSecurity::isFrameworkInternalRequest).permitAll()
            .anyRequest().authenticated()
        .and()
        .sessionManagement()
            .invalidSessionStrategy((request, response) -> {
                // 判断是否为Vaadin的AJAX请求
                boolean isVaadinAjaxRequest = "application/json".equals(request.getHeader("Accept")) 
                        || "XMLHttpRequest".equals(request.getHeader("X-Requested-With"));
                if (isVaadinAjaxRequest) {
                    response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                    response.getWriter().write("{\"error\": \"Session expired\"}");
                } else {
                    // 非Vaadin请求正常重定向到登录页
                    response.sendRedirect(ConstantesRoutes.LOGIN_URL);
                }
            });
}

2. 修正SystemMessagesProvider的配置位置

VaadinService.setSystemMessagesProvider是全局配置,无需在每个会话初始化时重复设置,应直接在ServiceInitListener的serviceInit方法中完成配置:

@Component
public class ConfigureUIServiceInitListener implements VaadinServiceInitListener, SessionInitListener {

    @Override
    public void serviceInit(final ServiceInitEvent event) {
        // 全局配置系统消息
        event.getSource().setSystemMessagesProvider(systemMessagesInfo -> {
            final CustomizedSystemMessages messages = new CustomizedSystemMessages();
            messages.setInternalErrorCaption("内部服务器错误");
            messages.setInternalErrorMessage("系统发生异常,请联系管理员");
            messages.setInternalErrorNotificationEnabled(true);
            messages.setInternalErrorURL(ConstantesRoutes.LOGIN_URL);

            messages.setSessionExpiredCaption("会话已过期");
            messages.setSessionExpiredMessage("您的会话已失效,请重新登录");
            messages.setSessionExpiredNotificationEnabled(true);
            messages.setSessionExpiredURL(ConstantesRoutes.LOGIN_URL);
            return messages;
        });
        
        // 其他初始化逻辑
        event.getSource().addSessionInitListener(this);
    }

    // 其他方法保持不变...
}

3. 主动监听连接状态,兜底处理异常

在主视图的onAttach方法中注册连接状态监听器,手动捕获连接丢失场景并处理:

@Override
protected void onAttach(AttachEvent attachEvent) {
    super.onAttach(attachEvent);
    UI.getCurrent().getConnectionStatusHandler().addConnectionStatusListener(status -> {
        if (status == ConnectionStatus.CONNECTION_LOST && !SecurityUtils.isUserLoggedIn()) {
            Notification.show("会话已过期,请重新登录", 5000, Notification.Position.TOP_CENTER);
            UI.getCurrent().navigate(LoginView.class);
        }
    });
}

内容的提问来源于stack exchange,提问作者Robyn.D

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 05:15:38