Spring 与 Spring Boot 的对比

更新于 2025-12-30

baeldung 2024-05-11

1. 概述

在本教程中,我们将探讨标准 Spring 框架与 Spring Boot 之间的区别。

我们将重点关注并讨论 Spring 的各个模块(如 MVC 和 Security)在核心 Spring 与 Spring Boot 中使用时的差异。

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 平台采取“约定优于配置”(opinionated)的理念,从而打造一个更快、更高效的开发生态系统。

以下是 Spring Boot 的一些主要特性:

  • 提供“约定式”的 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 应用所需的配置。

在 Spring 中,我们需要定义 DispatcherServlet、映射以及其他辅助配置。这可以通过 web.xml 文件或一个 Initializer 类实现:

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 注解,并定义一个视图解析器(view resolver)来解析控制器返回的视图:

@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;
   }
}

相比之下,Spring Boot 在引入 Web Starter 后,只需配置几个属性即可:

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

上述所有 Spring 配置都通过 Spring Boot 的 自动配置(auto-configuration)机制自动完成。

这意味着 Spring Boot 会根据应用中存在的依赖、属性和 Bean 自动启用相应的配置。

当然,如果我们希望添加自定义配置,Spring Boot 的自动配置会自动退让。

5.1 模板引擎配置

现在我们来看看如何在 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-starter-thymeleaf 依赖,即可在 Web 应用中启用 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 中启用 Security 所需的依赖和配置。

Spring 需要同时引入 spring-security-webspring-security-config 依赖。

接着,我们需要创建一个配置类,定义 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-security,它会自动将所有相关依赖加入 classpath。

Spring Boot 中的安全配置与上述代码完全相同。

关于 JPA 在 Spring 与 Spring Boot 中的配置方式,可参考我们的文章《A Guide to JPA with Spring》。

7. 应用启动方式

Spring 与 Spring Boot 在应用启动方式上的主要区别在于 Servlet 的初始化机制。Spring 可以使用 web.xmlSpringServletContainerInitializer 作为启动入口点。

而 Spring Boot 仅使用 Servlet 3+ 的特性来启动应用。下面我们详细说明。

7.1 Spring 如何启动?

Spring 同时支持传统的 web.xml 方式和较新的 Servlet 3+ 方式。

使用 web.xml 的流程如下:

  1. Servlet 容器(服务器)读取 web.xml
  2. 容器实例化 web.xml 中定义的 DispatcherServlet
  3. DispatcherServlet 通过读取 WEB-INF/{servletName}-servlet.xml 创建 WebApplicationContext
  4. 最后,DispatcherServlet 注册应用上下文中定义的 Bean。

使用 Servlet 3+ 的流程如下:

  1. 容器搜索实现了 ServletContainerInitializer 的类并执行。
  2. SpringServletContainerInitializer 找到所有实现了 WebApplicationInitializer 的类。
  3. WebApplicationInitializer 使用 XML 或 @Configuration 类创建上下文。
  4. WebApplicationInitializer 使用已创建的上下文初始化 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 Bean 绑定到内嵌的 Servlet 容器中。

此外,Spring Boot 会自动扫描主类所在包及其子包中的所有组件类。

Spring Boot 还支持将应用打包为 WAR 文件部署到外部容器中。此时,我们需要继承 SpringBootServletInitializer

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

在这种情况下,外部 Servlet 容器会从 WAR 包的 META-INF 中查找主类,而 SpringBootServletInitializer 会负责将 ServletFilterServletContextInitializer 绑定到容器。

8. 打包与部署

最后,我们来看看应用的打包与部署方式。两个框架都支持 Maven 和 Gradle 等常见构建工具,但在部署方面存在显著差异。

例如,Spring Boot Maven 插件为 Maven 提供了 Spring Boot 支持,允许打包成可执行的 JAR 或 WAR 文件,并支持“原地”运行应用。

Spring Boot 在部署方面相比传统 Spring 具有以下优势:

  • 提供内嵌容器支持
  • 支持通过 java -jar 命令独立运行 JAR 文件
  • 可排除某些依赖,避免在外部容器中部署时发生 JAR 冲突
  • 支持在部署时指定激活的 profile
  • 为集成测试自动生成随机端口

9. 结论

本文介绍了 Spring 与 Spring Boot 之间的主要区别。

简而言之,Spring Boot 是 Spring 框架的扩展,旨在使开发、测试和部署更加便捷高效。