Spring MVC多@ControllerAdvice类引发session作用域异常问题咨询
问题原因与解决方案
嗨,这个问题其实和「能不能有多个@ControllerAdvice」无关,核心原因是你把控制器职责、全局增强职责、session作用域这几个东西混在一起了,导致Spring初始化时出了问题,具体拆解下:
为什么会报错?
@ControllerAdvice是全局增强类,Spring在应用启动阶段就会初始化所有标注了这个注解的类——因为它要提前准备好,给所有控制器做全局的切面处理(比如全局@ModelAttribute、全局异常处理)。- 而你给这两个类设置了
@Scope(WebApplicationContext.SCOPE_SESSION),session作用域的Bean只有在HTTP请求进来、当前线程有活跃的Session时才能被实例化。 - 当Spring启动初始化你的
@ControllerAdvice类时,当前线程根本没有激活的Session,自然就会抛出「当前线程的session作用域未激活」的错误。
之前只给UserGapsController加@ControllerAdvice时可能没触发报错,大概率是那个类的初始化逻辑刚好没用到Session相关的依赖,或者Spring的初始化顺序巧合绕过了,但本质上这种写法是有问题的。
怎么解决?
核心思路是拆分职责,把全局增强逻辑和session作用域的控制器逻辑分开:
1. 单独创建全局增强类
新建一个只负责全局@ModelAttribute的类,只标注@ControllerAdvice,不需要加@Controller和session作用域(默认单例作用域即可):
@ControllerAdvice public class GlobalModelAttributeAdvice { // 直接在@ModelAttribute方法参数里注入HttpSession,Spring会自动传入当前请求的Session @ModelAttribute("commonAttr") public String getCommonAttribute(HttpSession session) { return (String) session.getAttribute("commonAttr"); } }
2. 控制器类回归本职
你的UserGapsController和RegistrationBaseController只保留@Controller和session作用域,专注处理请求逻辑即可,不用再加@ControllerAdvice:
@Controller @Scope(WebApplicationContext.SCOPE_SESSION) public class UserGapsController { @Autowired private HttpSession session; // 这里写你的@RequestMapping请求处理方法 @RequestMapping("/user/gaps") public String userGaps() { // 业务逻辑 return "user/gaps"; } } @Controller @Scope(WebApplicationContext.SCOPE_SESSION) public class RegistrationBaseController { @Autowired private HttpSession session; @RequestMapping("/register/base") public String registerBase() { // 业务逻辑 return "register/base"; } }
这样拆分后,Spring启动时初始化@ControllerAdvice类(单例,不依赖Session),而session作用域的控制器只有在请求进来时才会被实例化,完美避开了启动时没有Session的问题,同时多个控制器的全局@ModelAttribute逻辑也能正常生效。
内容的提问来源于stack exchange,提问作者Shweta Priyadarshani
相关产品推荐
相关产品推荐

