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
相关产品推荐
相关产品推荐

