Spring Boot vs Spring MVC:五大核心差异详解与项目迁移实战指南
1.1 Spring MVC是否需要独立容器而Spring Boot自带?
Spring MVC作为基础的Web框架,本身并不包含服务器容器。开发时需要手动配置Tomcat/Jetty等容器,通过部署war包到独立服务器运行。曾经在项目中配置Tomcat插件浪费了半小时,只因为忘记在pom.xml中添加servlet-api依赖。
而Spring Boot直接把Tomcat/Jetty打成jar包内嵌其中。用main方法启动项目时,就像启动普通Java应用那样简单。这种设计让本地调试变得极其方便,不再需要频繁进行mvn package部署到外部容器。最近帮同事排查问题时发现,他们用Spring Boot写的接口可以直接在IDE里右键运行调试,省去了传统部署流程的麻烦。
1.2 配置方式有何本质不同?
传统Spring MVC项目中,web.xml里需要配置DispatcherServlet并指定配置文件路径,spring-servlet.xml里要声明视图解析器、组件扫描等二十多项基础配置。还记得三年前维护过的一个老项目,XML配置文件加起来超过800行,光是处理组件扫描路径冲突就花了三天时间。
Spring Boot改用JavaConfig和自动配置机制后,新建项目时application.properties只需要设置server.port和spring.thymeleaf.cache=false这样的关键参数。上周重构登录模块时,添加spring-boot-starter-data-jpa依赖后就直接能用JPA接口,完全不用手动配置EntityManagerFactory。
1.3 自动配置机制如何简化开发?
自动配置的核心在于条件化Bean创建。当classpath存在特定类时,Spring Boot会自动配置相关组件。比如项目中引入spring-boot-starter-web依赖后,默认会配置Jackson进行JSON序列化,省去了手动注册MappingJackson2HttpMessageConverter的步骤。
最近在开发消息推送模块时深有体会:添加spring-boot-starter-websocket依赖后,只需要写@EnableWebSocket注解,所有的WebSocket配置自动生效。这种智能装配机制让依赖管理变得轻松,但也需要注意排除不需要的自动配置,之前就碰到过Redis自动配置干扰本地测试的情况。
1.4 启动流程有哪些关键差异?
传统Spring MVC的启动过程分为容器初始化和应用初始化两个阶段。Servlet容器先加载web.xml,然后通过ContextLoaderListener创建根应用上下文,整个过程需要经历Servlet生命周期的各个阶段。
Spring Boot的启动入口是main方法里的SpringApplication.run()。启动时先创建内嵌Servlet容器,然后通过SpringFactoriesLoader加载自动配置类。这个过程中最明显的变化是日志输出,能看到Started Application in 2.5 seconds字样而不是传统的容器启动日志。
1.5 默认约定优于配置体现在哪些方面?
默认静态资源路径从/webapp下移到了/resources/static目录,这个改变让前后端分离部署更自然。视图解析器默认配置为从/templates加载模板文件,上周用Thymeleaf开发管理后台时,直接把html文件放在约定目录就自动识别了。
数据源配置的默认行为特别值得称赞。当检测到内存数据库依赖时,Spring Boot会自动配置H2控制台。上次做快速原型验证,添加h2依赖后直接访问/h2-console就能操作数据库,完全跳过了JDBC连接配置的繁琐步骤。
2.1 依赖管理需要怎样调整?
传统Spring MVC项目的pom.xml里通常堆积着spring-core、spring-webmvc等分散的依赖项。迁移时要把这些替换成spring-boot-starter-web,这个Starter会自动引入嵌入式Tomcat、Jackson以及Spring MVC核心组件。上周帮团队重构用户中心模块时,原本需要手动管理的15个依赖缩减到3个Starter。
注意处理版本冲突问题。Spring Boot的dependencyManagement会自动管理所有Starter版本,但老项目中可能有特定版本的MyBatis或Hibernate依赖。遇到这种情况时,在pom.xml里显式声明需要的版本号会覆盖Spring Boot默认版本。之前升级数据访问层时,用
2.2 web.xml配置如何转化?
那些在web.xml里声明的DispatcherServlet、Filter和Listener,现在要改写成Java配置类。用@SpringBootApplication注解的主类已经继承了SpringBootServletInitializer,自动处理了Servlet3.0+的容器初始化。之前配置的CharacterEncodingFilter,现在通过FilterRegistrationBean在配置类中注入。
XML配置迁移有个实用技巧:逐块转换而不是整体替换。把原spring-mvc.xml里的<mvc:annotation-driven>对应成@EnableWebMvc注解,组件扫描改成@ComponentScan配置。最近重构商品服务时,保留原有XML配置文件的同时,用@ImportResource逐步引入到Spring Boot环境,实现了平滑过渡。
2.3 视图解析器怎样配置更高效?
Spring Boot默认配置了Thymeleaf或FreeMarker的视图解析器,但老项目可能还在用JSP。添加spring-boot-starter-tomcat依赖后,在application.properties设置spring.mvc.view.prefix=/WEB-INF/views/就能继续支持JSP。上个月改造订单系统的报表模块时,发现只需要调整模板文件存放路径,原有JSTL标签完全兼容。
对于需要自定义视图解析的场景,创建配置类实现WebMvcConfigurer接口更灵活。通过重写configureViewResolvers方法,可以添加多个视图解析器并设置优先级。曾经在混合使用PDF导出和HTML模板的项目中,这种配置方式让不同格式的视图解析互不干扰。
2.4 如何保持原有MVC功能的同时使用Starter?
用@Configuration注解创建保留原有功能的配置类是关键。当Spring Boot的自动配置与现有配置冲突时,通过@ConditionalOnMissingBean注解控制Bean的加载顺序。上季度迁移审批流程模块时,原有XML里定义的HandlerMapping通过@Bean方式重新声明,成功与自动配置的RequestMappingHandlerMapping共存。
分阶段迁移策略能降低风险。先保持原有Controller和Service不变,仅替换数据访问层为Spring Data JPA。待核心功能验证通过后,再用@RestControllerAdvice逐步替换原有的HandlerExceptionResolver。这种渐进式改造让团队在三个月内完成了大型ERP系统的迁移。
2.5 测试策略需要哪些改变?
抛弃传统的SpringJUnit4ClassRunner,改用@SpringBootTest注解启动完整应用上下文。测试REST API时,自动配置的TestRestTemplate比手动构造的MockMvc更贴近真实环境。上星期测试支付回调接口,发现TestRestTemplate能正确处理SSL证书,这是旧测试框架做不到的。
多层测试体系变得更清晰。单元测试用Mockito验证Service层逻辑,集成测试用@DataJpaTest专注数据库操作,Web层测试用@WebMvcTest配合MockBean。重构用户权限模块时,这种分层测试策略让代码覆盖率从45%提升到78%,且测试用例运行时间缩短了60%。