Wicket集成Spring Session Redis后AJAX请求返回Ajax-Location触发全页跳转问题
问题根因分析
你调试到的freshPage=true、component为null的核心表现是:Wicket无法从当前会话中获取到请求对应的原有页面实例,只能重新生成全新的页面实例,此时Wicket对AJAX请求的默认处理逻辑就是返回Ajax-Location响应头,触发前端全页重定向到新页面的地址。
可能的触发原因
- Wicket页面及依赖对象序列化失败:Wicket的有状态页面实例默认存储在会话属性中,Spring Session将会话写入Redis时需要对所有属性做序列化。如果你的页面类、页面内引用的组件、自定义Model等存在未实现
Serializable接口的非transient属性,序列化过程会报错(部分场景下异常会被框架吞掉,不会直接终止请求),导致页面实例没有被成功存入Redis,后续请求从Redis反序列化会话时拿不到原有页面实例,只能新建。你另一个正常运行的应用大概率所有页面相关对象都满足序列化要求。 - Wicket页面存储配置异常:如果当前应用配置的会话页面缓存数量过小,或者开启了页面自动过期清理,也会导致后续请求无法找到历史页面实例。
- Spring Session序列化兼容性问题:Spring Session默认使用JDK序列化,对Wicket内部类的序列化兼容性存在一定概率的问题,可能出现序列化后无法正常反序列化的情况,导致页面实例丢失。
排查思路
- 开启日志排查异常:开启
org.apache.wicket.pageStore和org.springframework.session的DEBUG级别日志,搜索是否存在序列化失败、反序列化异常、页面实例未找到的相关报错,这是最直接的定位手段。 - 排除会话序列化问题:临时关闭Spring Session,改用应用服务器默认的本地会话,若问题不再复现,可100%确认是Redis会话序列化/反序列化环节导致的页面实例丢失。
- 对比两个应用的Wicket配置:重点检查当前异常应用的
WebApplication初始化逻辑,是否有修改页面过期策略、页面存储大小、无状态页面默认配置的相关代码。 - 校验Redis会话内容:在首次页面加载完成后,直接查询Redis中对应的SESSION数据,确认Wicket页面相关的会话属性是否被正常写入;在第二次AJAX请求触发时,确认对应属性是否能被正常读取反序列化。
解决方案
- 修复序列化问题:排查所有有状态页面、组件、自定义Model类,确保所有非
transient属性都实现Serializable接口;不可序列化的属性必须添加transient关键字,并重写readObject()方法在反序列化后完成属性的重新初始化。 - 调整Wicket页面配置:在
WebApplication的init()方法中添加配置getPageSettings().setRecreateBookmarkablePagesAfterExpiry(false),该配置关闭页面过期后自动新建的逻辑,页面实例丢失时会直接抛出PageExpiredException,方便定位具体触发过期的场景。 - 更换Spring Session序列化器:改用Kryo等兼容性更好的序列化器替换默认的JDK序列化,提升Wicket对象序列化的成功率。
- 调大Wicket页面缓存容量:在
WebApplication的init()方法中调整页面存储的缓存数量,例如getStoreSettings().setInmemoryCacheSize(50),避免因为缓存过小导致历史页面被提前清理。
内容的提问来源于stack exchange,提问作者Diane Megan Harris
相关产品推荐
相关产品推荐

