基于Spring的MVC模式正确实现及新增Service层后404错误排查
问题根因
从启动日志和给出的代码判断,Spring上下文未正确初始化、Controller未被Spring容器托管是404的核心原因,具体问题点如下:
- 组件扫描范围配置错误:现有配置类的
@ComponentScan(basePackages = " name.web.controller")仅扫描了controller包,新增的UserServiceImpl(service包)、UserImpl(dao/repo包)都不在扫描范围内,Spring无法识别@Service、@Repository注解的Bean,直接导致Controller依赖的UserService实例缺失,Controller无法完成初始化。 - 重复注册Bean冲突:既在
UserImpl类上加了@Repository注解,又在配置类中通过@Bean手动注册了UserRepo实例,同类型重复Bean会触发依赖注入冲突,仅输出常规启动日志是因为未开启debug级别的日志,看不到错误信息。 - 代码语法错误:
- Controller中
us.ad(users)方法名拼写错误,UserService中定义的方法名为add - Controller中
@GetMapping("/new")对应的方法名用了Java关键字new,编译阶段就会报错 - UserImpl的
getByName方法中UseriModel类名拼写错误,多了字符i
- Controller中
- Spring MVC初始化配置缺失:日志提示
No Spring WebApplicationInitializer types detected on classpath,说明没有配置Spring MVC的前端控制器DispatcherServlet,所有请求都不会被Spring MVC处理。 - 部署路径不匹配:日志显示Tomcat把项目部署到了
ROOT目录,上下文根路径为/,访问带/bookProject/前缀的地址自然找不到资源。
修正方案
1. 调整组件扫描范围
修改配置类的@ComponentScan注解,扫描项目根包(示例中假设项目根包为name),确保所有加了Spring注解的类都能被识别:
@ComponentScan(basePackages = "name")
2. 删除重复的Bean注册
删掉配置类中手动注册UserRepo、BookRepo的两个@Bean方法,@Repository注解已经会让Spring自动注册对应实例,重复注册会导致冲突。
3. 修复所有语法错误
- 把Controller中的
us.ad(users)改为us.add(users) - 把
@GetMapping("/new")对应的方法名从new改为newUser等合法名称,避免使用Java关键字 - 把UserImpl中的
UseriModel改为UserModel
4. 补充Spring MVC启动配置
新增初始化类注册DispatcherServlet,示例如下:
public class SpringMvcInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return new Class[]{你的配置类类名.class}; } @Override protected Class<?>[] getServletConfigClasses() { return null; } @Override protected String[] getServletMappings() { return new String[]{"/"}; } }
5. 补充视图解析器配置
在配置类中添加视图解析器,确保返回的逻辑视图名能正确映射到页面文件:
@Bean public InternalResourceViewResolver viewResolver() { InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setPrefix("/WEB-INF/views/"); // 改成实际的页面存放路径 resolver.setSuffix(".jsp"); return resolver; }
6. 适配部署路径
如果需要保留/bookProject访问前缀,把项目打包为bookProject.war放到Tomcat的webapps目录下部署;如果不需要前缀,直接访问http://localhost:8080/new测试接口即可。
内容的提问来源于stack exchange,提问作者helloJava
相关产品推荐
相关产品推荐

