Spring Boot Starter 入门指南

更新于 2025-12-30

baeldung 2016-07-14

1. 概述

依赖管理是任何复杂项目中的关键环节。手动进行依赖管理并不是理想的做法——你花在依赖管理上的时间越多,用于项目其他重要方面的时间就越少。

Spring Boot Starter 正是为了应对这一问题而设计的。Starter POM 是一组便捷的依赖描述符,你可以直接将其包含到你的应用程序中。通过使用 Starter,你无需四处查找示例代码、复制粘贴大量依赖项,就能一站式获取所需的所有 Spring 及相关技术依赖。

目前我们有超过 30 个 Spring Boot Starter 可供使用,接下来我们将逐一介绍其中一些常用 Starter。


2. Web Starter

首先,让我们看看如何开发一个 REST 服务。通常我们会用到 Spring MVC、Tomcat 和 Jackson 等库——对于一个单一应用来说,这涉及大量的依赖项。

Spring Boot Starter 可以帮助我们大幅减少手动添加的依赖数量,只需引入一个 Starter 即可。例如:

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

现在我们可以创建一个 REST 控制器。为简化起见,这里不使用数据库,仅聚焦于 REST 控制器本身:

@RestController
public class GenericEntityController {
    private List<GenericEntity> entityList = new ArrayList<>();

    @RequestMapping("/entity/all")
    public List<GenericEntity> findAll() {
        return entityList;
    }

    @RequestMapping(value = "/entity", method = RequestMethod.POST)
    public GenericEntity addEntity(GenericEntity entity) {
        entityList.add(entity);
        return entity;
    }

    @RequestMapping("/entity/findby/{id}")
    public GenericEntity findById(@PathVariable Long id) {
        return entityList.stream()
                         .filter(entity -> entity.getId().equals(id))
                         .findFirst()
                         .get();
    }
}

GenericEntity 是一个简单的 Java Bean,包含一个 Long 类型的 id 和一个 String 类型的 value

就这样!启动应用后,访问 http://localhost:8080/entity/all 即可验证控制器是否正常工作。

我们仅用极少的配置就构建了一个完整的 REST 应用。


3. Test Starter

在测试时,我们通常会用到以下库:Spring Test、JUnit、Hamcrest 和 Mockito。虽然可以手动逐个引入这些依赖,但更高效的方式是使用 Spring Boot Test Starter:

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

注意:你无需指定每个依赖的版本号。Spring Boot 会自动推断应使用的版本——你只需在父 POM 中指定 spring-boot-starter-parent 的版本即可。日后如需升级 Spring Boot 及其依赖,只需更新一处版本号,其余依赖将自动同步。

接下来,我们对上一节创建的控制器进行测试。

测试控制器有两种方式:

  • 使用模拟环境(Mock Environment)
  • 使用内嵌的 Servlet 容器(如 Tomcat 或 Jetty)

本例中我们采用模拟环境:

@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = Application.class)
@WebAppConfiguration
public class SpringBootApplicationIntegrationTest {

    @Autowired
    private WebApplicationContext webApplicationContext;

    private MockMvc mockMvc;

    @BeforeEach
    public void setupMockMvc() {
        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
    }

    @Test
    public void givenRequestHasBeenMade_whenMeetsAllOfGivenConditions_thenCorrect()
      throws Exception {
        mockMvc.perform(MockMvcRequestBuilders.get("/entity/all"))
          .andExpect(MockMvcResultMatchers.status().isOk())
          .andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON))
          .andExpect(jsonPath("$", hasSize(4)));
    }
}

上述测试调用 /entity/all 端点,并验证返回的 JSON 响应包含 4 个元素。要使该测试通过,还需在控制器中初始化列表:

public class GenericEntityController {
    private List<GenericEntity> entityList = new ArrayList<>();

    {
        entityList.add(new GenericEntity(1L, "entity_1"));
        entityList.add(new GenericEntity(2L, "entity_2"));
        entityList.add(new GenericEntity(3L, "entity_3"));
        entityList.add(new GenericEntity(4L, "entity_4"));
    }
    //...
}

需要注意的是:@WebAppConfiguration 注解和 MockMvc 来自 spring-test 模块,hasSize 是 Hamcrest 的匹配器,@BeforeEach 是 JUnit 的注解——所有这些功能都通过引入单个 Starter 依赖即可获得。


4. Data JPA Starter

大多数 Web 应用都需要某种形式的数据持久化,而 JPA 是常见选择。

与其手动定义所有相关依赖,不如直接使用 Starter:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>runtime</scope>
</dependency>

开箱即用,Spring Boot 自动支持 H2、Derby 和 Hsqldb 等内存数据库。本例中我们使用 H2。

接下来创建实体的 Repository:

public interface GenericEntityRepository extends JpaRepository<GenericEntity, Long> {}

编写 JUnit 测试如下:

@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = Application.class)
public class SpringBootJPAIntegrationTest {
    @Autowired
    private GenericEntityRepository genericEntityRepository;

    @Test
    public void givenGenericEntityRepository_whenSaveAndRetreiveEntity_thenOK() {
        GenericEntity genericEntity = genericEntityRepository.save(new GenericEntity("test"));
        GenericEntity foundEntity = genericEntityRepository.findById(genericEntity.getId()).orElse(null);
        assertNotNull(foundEntity);
        assertEquals(genericEntity.getValue(), foundEntity.getValue());
    }
}

我们无需手动指定数据库厂商、连接 URL 或凭据。得益于 Spring Boot 的合理默认配置,一切开箱即用;当然,如有需要,这些配置仍可自定义。


5. Mail Starter

在企业级开发中,发送电子邮件是一项常见任务,而直接使用 Java Mail API 通常较为繁琐。

Spring Boot Starter 隐藏了这种复杂性,只需添加如下依赖:

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

现在我们可以直接使用 JavaMailSender。下面编写一个测试用例。

为便于测试,我们需要一个简单的 SMTP 服务器。本例使用 Wiser,可在 POM 中添加如下依赖:

<dependency>
    <groupId>org.subethamail</groupId>
    <artifactId>subethasmtp</artifactId>
    <version>3.1.7</version>
    <scope>test</scope>
</dependency>

最新版 Wiser 可在 Maven Central 仓库中找到。

测试代码如下:

@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = Application.class)
public class SpringBootMailIntegrationTest {
    @Autowired
    private JavaMailSender javaMailSender;

    private Wiser wiser;

    private final String userTo = "user2@localhost";
    private final String userFrom = "user1@localhost";
    private final String subject = "Test subject";
    private final String textMail = "Text subject mail";

    @BeforeEach
    public void setUp() {
        final int TEST_PORT = 8025;
        wiser = Wiser.port(TEST_PORT);
        wiser.start();
    }

    @AfterEach
    public void tearDown() {
        wiser.stop();
    }

    @Test
    public void givenMail_whenSendAndReceived_thenCorrect() throws Exception {
        SimpleMailMessage message = composeEmailMessage();
        javaMailSender.send(message);
        List<WiserMessage> messages = wiser.getMessages();

        assertThat(messages, hasSize(1));
        WiserMessage wiserMessage = messages.get(0);
        assertEquals(userFrom, wiserMessage.getEnvelopeSender());
        assertEquals(userTo, wiserMessage.getEnvelopeReceiver());
        assertEquals(subject, getSubject(wiserMessage));
        assertEquals(textMail, getMessage(wiserMessage));
    }

    private String getMessage(WiserMessage wiserMessage) throws MessagingException, IOException {
        return wiserMessage.getMimeMessage().getContent().toString().trim();
    }

    private String getSubject(WiserMessage wiserMessage) throws MessagingException {
        return wiserMessage.getMimeMessage().getSubject();
    }

    private SimpleMailMessage composeEmailMessage() {
        SimpleMailMessage mailMessage = new SimpleMailMessage();
        mailMessage.setTo(userTo);
        mailMessage.setReplyTo(userFrom);
        mailMessage.setFrom(userFrom);
        mailMessage.setSubject(subject);
        mailMessage.setText(textMail);
        return mailMessage;
    }
}

测试中,@BeforeEach@AfterEach 方法负责启动和停止邮件服务器。

注意:我们注入了 JavaMailSender Bean——该 Bean 由 Spring Boot 自动创建。

与 Spring Boot 的其他默认配置一样,邮件设置也可在 application.properties 中自定义:

spring.mail.host=localhost
spring.mail.port=25
spring.mail.properties.mail.smtp.auth=false

这里我们将邮件服务器配置为 localhost:25,且无需身份验证。


6. 结论

本文介绍了 Spring Boot Starter 的基本概念,解释了为何需要它们,并通过多个示例展示了如何在项目中使用。

使用 Spring Boot Starter 的主要优势包括:

  • 提升 POM 文件的可维护性
  • 提供生产就绪、经过测试且受支持的依赖配置
  • 显著减少项目整体配置时间

通过合理使用 Starter,开发者可以更专注于业务逻辑,而非繁琐的依赖和配置管理。