1. 概述

本篇文章主要探讨标准 Spring 框架与 Spring Boot 的区别。

我们将重点分析在使用核心 Spring 和使用 Spring Boot 时,Spring 的各个模块(如 MVC、Security)的配置差异。

2. 什么是 Spring?

简单来说,Spring 框架为开发 Java 应用提供了全面的基础设施支持。

它包含了许多强大的特性,例如依赖注入(Dependency Injection),以及一系列开箱即用的模块:

  • Spring JDBC
  • Spring MVC
  • Spring Security
  • Spring AOP
  • Spring ORM
  • Spring Test

这些模块可以显著减少应用程序的开发时间。

举个例子,在早期的 Java Web 开发中,为了向数据库插入一条记录,我们通常需要写大量样板代码。而通过使用 Spring JDBC 模块中的 JdbcTemplate,只需少量配置和几行代码就可以完成同样的功能。

3. 什么是 Spring Boot?

Spring Boot 是 Spring 框架的一个扩展,它消除了搭建 Spring 应用所需的大量样板配置

它对 Spring 平台持“约定优于配置”的理念,从而打造了一个更快速、高效的开发环境。

Spring Boot 提供了以下关键特性:

  • Opinionated(预设最佳实践)的“starter”依赖项,简化构建和配置
  • 内嵌服务器,避免部署复杂性
  • 提供监控指标、健康检查和外部化配置
  • 自动配置 Spring 功能(尽可能地)

接下来我们逐步了解这两个框架。

4. Maven 依赖

首先来看一下使用 Spring 创建一个 Web 应用所需的最小依赖:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>5.3.5</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.3.5</version>
</dependency>

相比之下,Spring Boot 只需要一个依赖就能让 Web 应用跑起来:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.4.4</version>
</dependency>

构建时,其他所有依赖都会自动添加到最终的归档文件中。

再比如测试库。我们通常会使用 Spring Test、JUnit、Hamcrest 和 Mockito 等库。在 Spring 项目中,我们需要手动添加这些依赖。

而在 Spring Boot 中,只需引入一个测试 starter 依赖即可自动包含这些库。

Spring Boot 提供了多个针对不同 Spring 模块的 starter 依赖。 最常用的几个包括:

  • spring-boot-starter-data-jpa
  • spring-boot-starter-security
  • spring-boot-starter-test
  • spring-boot-starter-web
  • spring-boot-starter-thymeleaf

完整 starter 列表可参考 Spring 官方文档

5. MVC 配置

下面来看一下使用 Spring 和 Spring Boot 创建 JSP Web 应用所需的配置。

5.1. Spring 的配置方式

Spring 需要手动定义 DispatcherServlet、映射关系以及其他支持配置。可以通过 web.xmlInitializer 类来实现:

public class MyWebAppInitializer implements WebApplicationInitializer {
 
    @Override
    public void onStartup(ServletContext container) {
        AnnotationConfigWebApplicationContext context
          = new AnnotationConfigWebApplicationContext();
        context.setConfigLocation("com.baeldung");
 
        container.addListener(new ContextLoaderListener(context));
 
        ServletRegistration.Dynamic dispatcher = container
          .addServlet("dispatcher", new DispatcherServlet(context));
         
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/");
    }
}

还需要在 @Configuration 类上添加 @EnableWebMvc 注解,并定义一个视图解析器来处理控制器返回的视图:

@EnableWebMvc
@Configuration
public class ClientWebConfig implements WebMvcConfigurer { 
   @Bean
   public ViewResolver viewResolver() {
      InternalResourceViewResolver bean
        = new InternalResourceViewResolver();
      bean.setViewClass(JstlView.class);
      bean.setPrefix("/WEB-INF/view/");
      bean.setSuffix(".jsp");
      return bean;
   }
}

5.2. Spring Boot 的配置方式

相比之下,Spring Boot 只需添加 Web starter 后配置几个属性即可完成设置:

spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp

✅ 上述所有 Spring 配置都通过一个叫 auto-configuration(自动配置) 的机制被自动包含进来。

这意味着 Spring Boot 会根据项目中的依赖、属性和 Bean 来自动完成配置。

当然,如果你需要自定义配置,Spring Boot 的自动配置会主动让位。

5.3. 模板引擎配置

接下来我们看看如何在 Spring 和 Spring Boot 中配置 Thymeleaf 模板引擎。

Spring 中的配置

需要添加 thymeleaf-spring5 依赖并进行一些视图解析器配置:

@Configuration
@EnableWebMvc
public class MvcWebConfig implements WebMvcConfigurer {

    @Autowired
    private ApplicationContext applicationContext;

    @Bean
    public SpringResourceTemplateResolver templateResolver() {
        SpringResourceTemplateResolver templateResolver = 
          new SpringResourceTemplateResolver();
        templateResolver.setApplicationContext(applicationContext);
        templateResolver.setPrefix("/WEB-INF/views/");
        templateResolver.setSuffix(".html");
        return templateResolver;
    }

    @Bean
    public SpringTemplateEngine templateEngine() {
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(templateResolver());
        templateEngine.setEnableSpringELCompiler(true);
        return templateEngine;
    }

    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        ThymeleafViewResolver resolver = new ThymeleafViewResolver();
        resolver.setTemplateEngine(templateEngine());
        registry.viewResolver(resolver);
    }
}

Spring Boot 中的配置

Spring Boot 1 只需引入 spring-boot-starter-thymeleaf 依赖即可启用 Thymeleaf。

由于 Thymeleaf 3.0 的新特性,在 Spring Boot 2 中还需添加 thymeleaf-layout-dialect 依赖。或者,也可以直接使用 spring-boot-starter-thymeleaf,它会自动处理这些依赖。

依赖配置完成后,只需将模板文件放入 src/main/resources/templates 目录下,Spring Boot 就会自动识别并渲染。

6. Spring Security 配置

为了简化说明,我们来看看如何在这两个框架中启用默认的 HTTP Basic 认证。

Spring 中的配置

Spring 需要引入以下两个依赖来启用安全功能:

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-config</artifactId>
</dependency>

然后创建一个配置类,定义 SecurityFilterChain Bean 并使用 @EnableWebSecurity 注解:

@Configuration
@EnableWebSecurity
public class CustomWebSecurityConfigurerAdapter {
 
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
          .withUser("user1")
            .password(passwordEncoder()
            .encode("user1Pass"))
          .authorities("ROLE_USER");
    }
 
    @Bean
     public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.authorizeRequests()
          .anyRequest().authenticated()
          .and()
          .httpBasic();
        return http.build();
    }
    
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

这里使用了 inMemoryAuthentication 来配置认证。

Spring Boot 中的配置

Spring Boot 同样需要上述依赖,但只需引入一个 starter 即可:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

✅ 这个 starter 会自动将所有相关依赖加入 classpath。

配置方式与 Spring 完全一致。

关于 JPA 的配置方式,可以参考我们的文章 A Guide to JPA with Spring

7. 应用启动方式

Spring 和 Spring Boot 在应用启动方式上的主要区别在于 Servlet 的引导机制。

7.1. Spring 的启动方式

Spring 支持传统的 web.xml 启动方式和基于 Servlet 3+ 的方式。

web.xml 启动流程

  1. 容器读取 web.xml
  2. 实例化 web.xml 中定义的 DispatcherServlet
  3. DispatcherServlet 根据 WEB-INF/{servletName}-servlet.xml 创建 WebApplicationContext
  4. 最后注册应用上下文中的 Bean

Servlet 3+ 启动流程

  1. 容器查找并执行实现了 ServletContainerInitializer 的类
  2. SpringServletContainerInitializer 查找所有实现 WebApplicationInitializer 的类
  3. WebApplicationInitializer 使用 XML 或 @Configuration 类创建上下文
  4. 创建 DispatcherServlet 并绑定上下文

7.2. Spring Boot 的启动方式

Spring Boot 应用的入口是带有 @SpringBootApplication 注解的类:

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

默认情况下,Spring Boot 使用内嵌容器运行应用。此时通过 public static void main 方法启动内嵌 Web 服务器。

它还会自动将应用上下文中的 ServletFilterServletContextInitializer 绑定到内嵌容器。

另一个亮点是:✅ Spring Boot 会自动扫描主类所在包及其子包下的所有组件。

此外,Spring Boot 还支持打包为 WAR 并部署到外部容器。此时需要继承 SpringBootServletInitializer

@SpringBootApplication
public class Application extends SpringBootServletInitializer {
    // ...
}

此时外部容器会从 WAR 的 META-INF 文件中查找主类,而 SpringBootServletInitializer 负责绑定 ServletFilterServletContextInitializer

8. 打包与部署

最后我们来看打包与部署方式。两个框架都支持 Maven 和 Gradle,但在部署方面有显著差异。

例如,Spring Boot Maven Plugin 提供了对 Maven 的支持,可以打包为可执行的 jar 或 war,并支持“原地运行”。

✅ Spring Boot 相比 Spring 在部署方面的优势包括:

  • ✅ 内嵌容器支持
  • ✅ 通过 java -jar 独立运行 jar
  • ✅ 可排除依赖以避免外部容器中的 jar 冲突
  • ✅ 支持部署时指定 active profiles
  • ✅ 集成测试时支持随机端口生成

9. 总结

本文对比了 Spring 与 Spring Boot 的关键差异。

一句话总结:Spring Boot 是 Spring 的扩展,旨在让开发、测试和部署更加便捷高效。


原始标题:A Comparison Between Spring and Spring Boot