如何在@Controller中访问@ControllerAdvice中的用户配置对象?
兄弟,我太懂你这种明明JSP里能正常拿到用户配置,结果在Controller里调用就抛空指针的憋屈了!咱们先搞清楚为啥会出现这种情况,再给你几个靠谱的解决办法:
问题根源
你在@ControllerAdvice里用@ModelAttribute添加的用户配置(比如profile),是请求级别的模型属性——它会被添加到每个请求的Model对象中,供后续的视图(比如JSP)渲染时使用。但@Controller是Spring容器管理的单例Bean,如果你直接在Controller的字段上引用这个profile,Spring根本不会把请求模型里的属性赋值给这个字段,因为两者的生命周期完全不搭:Controller实例是全局唯一的,而profile是每个请求单独生成/绑定的,所以你的Controller字段自然就是null啦。
靠谱的解决方案
方案1:在Controller方法参数中直接获取Model属性
既然profile存在于请求的Model里,那在Controller的处理方法里,直接把Model或者HttpServletRequest作为参数传入,然后从中取出profile就行:
@Controller public class YourController { @GetMapping("/your-path") public String handleRequest(Model model) { // 从Model中获取profile UserProfile profile = (UserProfile) model.getAttribute("profile"); // 接下来就可以正常使用profile了 return "your-view"; } // 或者用HttpServletRequest获取 @GetMapping("/another-path") public String anotherHandle(HttpServletRequest request) { UserProfile profile = (UserProfile) request.getAttribute("profile"); // 业务逻辑处理 return "another-view"; } }
方案2:把profile放到Session中,用@SessionAttribute获取
如果这个用户配置是登录用户的会话信息(比如用户登录后一直需要用到),那可以在@ControllerAdvice里把它存入Session,然后在Controller里用@SessionAttribute直接注入:
首先修改你的@ControllerAdvice类:
@ControllerAdvice public class GlobalControllerAdvice { @ModelAttribute public void addUserProfile(HttpSession session) { // 这里替换成你的用户配置获取逻辑 UserProfile profile = userProfileService.getCurrentUserProfile(); session.setAttribute("profile", profile); } }
然后在Controller里直接使用:
@Controller public class YourController { @GetMapping("/session-path") public String handleSessionRequest(@SessionAttribute("profile") UserProfile profile) { // 直接使用profile,不用再担心null问题 return "session-view"; } }
方案3:检查@ControllerAdvice的作用范围
最后别忘了检查你的@ControllerAdvice是不是被限定了作用范围!比如如果加了@ControllerAdvice(assignableTypes = SomeController.class),那只有SomeController能拿到这个属性,其他Controller自然就拿不到了。如果是全局生效的,直接用@ControllerAdvice不加任何参数就行。
避坑提醒
千万别在Controller的类字段上直接尝试注入profile!比如这种写法肯定会空指针:
@Controller public class BadController { // 这种写法绝对不行!Controller是单例,profile是请求级别的,永远拿不到值 private UserProfile profile; @GetMapping("/bad-path") public String badHandle() { profile.doSomething(); // 必抛NullPointerException return "bad-view"; } }
内容的提问来源于stack exchange,提问作者cape

