Spring MVC控制器中使用EntityManager时触发NullPointerException
嘿,我来帮你搞定这个问题~ 你遇到的NPE本质上是因为直接使用的UserService(或者LoginController)没有被Spring容器管理,导致依赖的EntityManager没被注入,而手动创建ClassPathXmlApplicationContext的方式能正常运行,是因为你手动启动了Spring容器,它帮你完成了所有依赖的注入工作。
下面给你一步步的解决方案,让你不用手动创建context也能正常使用UserService:
1. 确保你的类都被Spring容器管理
首先,要让LoginController和UserService都成为Spring的bean:
- 给LoginController添加
@Controller注解,告诉Spring这是一个控制器类 - 给UserService添加
@Service注解,标记这是一个业务逻辑类
示例代码:
@Controller public class LoginController { // 后续会注入UserService private UserService userService; // 登录处理方法 public String handleLogin(String username, String password) { boolean isValid = userService.validate(username, password); // 后续登录逻辑... return isValid ? "success" : "error"; } }
@Service public class UserService { // 注入EntityManager @PersistenceContext private EntityManager entityManager; public boolean validate(String username, String password) { // 这里调用entityManager.createQuery就不会NPE了 Query query = entityManager.createQuery("SELECT u FROM User u WHERE u.username = :username AND u.password = :password"); query.setParameter("username", username); query.setParameter("password", password); return query.getResultList().size() > 0; } }
2. 配置Spring的组件扫描
在你的applicationContext.xml里添加组件扫描配置,让Spring能找到这些带注解的类:
<context:component-scan base-package="com.yourpackage"/>
把com.yourpackage换成你实际存放Controller、Service类的包路径(比如com.example.login)。
3. 通过依赖注入获取UserService实例
在LoginController里用@Autowired或者@Resource注解来注入UserService,这样Spring会自动把容器里的UserService实例赋值给这个字段,不用你手动创建:
@Controller public class LoginController { @Autowired private UserService userService; // 登录处理方法... }
为什么手动创建Context能正常运行?
当你手动创建ClassPathXmlApplicationContext时,Spring会加载配置文件,初始化所有被管理的bean,并且自动完成依赖注入——把EntityManager注入到UserService,再把UserService注入到LoginController。而如果你直接自己new LoginController(),这个实例不在Spring容器的管控范围内,UserService字段会是null,调用userService.validate()自然就会抛出NPE,EntityManager同理。
只要按照上面的步骤配置,你在Spring MVC的请求处理方法里直接使用UserService就完全没问题啦!
内容的提问来源于stack exchange,提问作者dstiven

