Spring MVC会话作用域问题:多HTTP会话共享列表异常求助
排查与解决Spring MVC会话作用域Bean共享问题
嘿,我之前也踩过这个坑!你的思路完全没问题——用session作用域实现会话间数据隔离、会话内控制器共享,但问题出在Spring没有正确为会话作用域Bean创建代理,导致它被当成单例Bean处理了,所以所有请求共用同一个实例。
问题根源
默认情况下,当你给@Component标注的类设置@Scope("session")时,如果不指定代理模式,Spring不会为它生成代理对象。而你的SessionController默认是单例的(即使加了@Scope("request")也没必要,控制器单例完全安全),单例控制器注入的Bean会被缓存,导致所有会话都拿到同一个MySession实例,自然列表就共享了。
修改方案
只需要两步就能解决:
1. 给MySession添加代理模式配置
修改MySession类,指定proxyMode = ScopedProxyMode.TARGET_CLASS,让Spring为会话作用域Bean生成CGLIB代理,这样每次调用都会获取当前会话的实例:
@Component @Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS) public class MySession { // 建议初始化列表,避免空指针异常 public List<String> mylist = new ArrayList<>(); }
2. 优化控制器的作用域配置
控制器不需要设置@Scope("request"),Spring MVC的控制器默认是单例的,而且单例控制器注入代理后的会话Bean完全安全,去掉这个多余配置:
@Controller public class SessionController { @Autowired private MySession mySession; @RequestMapping("/updateSession") public ModelAndView updateSession(@RequestParam("id") int id) { // 示例操作:添加元素到当前会话的列表 mySession.mylist.add("操作ID: " + id); // 其他增删操作... return new ModelAndView("result"); } }
验证方法
- 用不同的浏览器(或同一个浏览器的隐私模式)发起请求,每个浏览器代表一个独立的HTTP会话,此时各自的列表应该是独立的。
- 同一个浏览器内多次请求,列表会持续更新,而其他浏览器的列表不受影响。
内容的提问来源于stack exchange,提问作者monkey
相关产品推荐
相关产品推荐

