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

Spring控制器类变量未重新初始化问题咨询

Spring控制器类变量未重新初始化问题咨询

Hey Lee, 我来帮你理清楚这个问题的根源~

你之所以遇到和预期不符的情况,核心原因是Spring中@RestController默认是单例模式——也就是说,你的LoginController只会被创建一次,在整个应用的生命周期里都会复用这同一个实例。而你定义的sessionMap作为类的成员变量,自然也是全局共享的,不会在每次调用API时重新初始化。

结合你的操作场景具体分析:

  • 当你第一次调用/login?name=Jay时,当前请求会话的ID被作为key,Jay作为value存入了这个全局的sessionMap中;
  • 之后调用/myName时,用同一个会话ID去map中取值,自然能拿到之前存储的Jay,所以接口返回了这个值。

而你期望/myName返回null,本质是误以为每次请求都会新建一个LoginController实例,导致sessionMap被重新初始化(变成空集合),但实际Spring的控制器实例并不会随请求重建。

解决方案推荐

其实你已经在方法中注入了HttpSession,完全可以直接利用它来存储会话级别的用户信息,不需要自己维护sessionMap,代码修改如下:

package com.example.study;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpSession;

@RestController
public class LoginController {

    @GetMapping("/login")
    public String login(HttpSession session, @RequestParam String name){
        // 直接将名字存入当前会话
        session.setAttribute("name", name);
        return "saved";
    }

    @GetMapping("/myName")
    public String myName(HttpSession session){
        // 从当前会话中取出名字
        String myName = (String) session.getAttribute("name");
        return myName;
    }
}

这样每个会话的信息都是相互隔离的,Spring会自动帮你管理会话的生命周期,既安全又省心。

如果一定要自己维护全局map(非常不推荐,因为单例环境下多线程并发访问会有线程安全问题,还会导致内存占用持续增加),那你需要手动清空sessionMap或者处理键值对的过期逻辑,但这种做法完全没必要,用HttpSession是更符合SpringWeb设计的方案。

备注:内容来源于stack exchange,提问作者Lee Soobin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.22 12:09:37