SpringBoot Starter终极指南:从入门到精通

这是一份非常详细、实用、通俗易懂,权威、全面的Spring Boot Starter 的指南。

目录

  1. Spring Boot Starter 是什么?

    • 1.1 核心目标:简化依赖管理和配置
    • 1.2 传统 Spring 应用配置的痛点
    • 1.3 Starter 如何解决痛点:约定大于配置
    • 1.4 Starter 的本质:依赖的聚合器
  2. Spring Boot Starter 的工作原理

    • 2.1 自动配置 (Auto-Configuration) 的核心地位
    • 2.2 spring-boot-autoconfigure 模块
    • 2.3 @EnableAutoConfiguration 注解
    • 2.4 META-INF/spring.factories 文件:自动配置的注册表
    • 2.5 条件注解 (Conditional Annotations):按需配置的魔法
      • @ConditionalOnClass
      • @ConditionalOnMissingBean
      • @ConditionalOnProperty
      • @ConditionalOnWebApplication
      • 其他条件注解
    • 2.6 配置属性 (Configuration Properties):@ConfigurationProperties
  3. 如何使用官方提供的 Spring Boot Starter

    • 3.1 在 pom.xml 中添加 Starter 依赖
    • 3.2 理解 Starter 带来的依赖传递
    • 3.3 自动配置生效的验证
    • 3.4 覆盖自动配置:自定义 Bean 和属性配置
    • 3.5 禁用特定的自动配置类
  4. 创建自定义 Spring Boot Starter

    • 4.1 明确 Starter 的目的和功能
    • 4.2 创建独立的 Starter 模块项目
    • 4.3 定义 Starter 的核心功能库 (autoconfigure 模块最佳实践)
    • 4.4 编写自动配置类 (AutoConfiguration)
      • 使用条件注解控制配置生效
      • 定义需要自动创建的 Bean
      • 绑定配置属性 (@ConfigurationProperties)
    • 4.5 注册自动配置类:创建 META-INF/spring.factories
    • 4.6 提供 Starter 模块:聚合核心库和依赖
    • 4.7 可选:提供额外的元数据 (spring-configuration-metadata.json)
    • 4.8 打包和发布 Starter
  5. 最佳实践

    • 5.1 Starter 设计原则:单一职责、开箱即用
    • 5.2 谨慎使用自动配置:避免魔法过多
    • 5.3 提供清晰、灵活的配置选项
    • 5.4 完善的文档和示例
    • 5.5 良好的命名规范 (xxx-spring-boot-starter)
  6. 实战案例 1:集成 Redis Starter

    • 6.1 添加 spring-boot-starter-data-redis 依赖
    • 6.2 配置 Redis 连接 (application.properties)
    • 6.3 自动注入 RedisTemplateStringRedisTemplate
    • 6.4 编写示例代码:存储和读取数据
    • 6.5 完整可运行代码示例
  7. 实战案例 2:集成 Spring Security Starter

    • 7.1 添加 spring-boot-starter-security 依赖
    • 7.2 默认安全配置的行为
    • 7.3 自定义用户、密码和角色 (内存、JDBC、LDAP)
    • 7.4 自定义安全配置 (@EnableWebSecurity, WebSecurityConfigurerAdapter)
    • 7.5 示例:配置基于表单的登录和简单授权规则
    • 7.6 完整可运行代码示例 (简化版)
  8. 实战案例 3:创建自定义 Starter - 简易短信发送 Starter

    • 8.1 项目结构规划 (sms-spring-boot-starter, sms-spring-boot-autoconfigure)
    • 8.2 sms-spring-boot-autoconfigure 模块开发
      • 定义配置属性类 SmsProperties
      • 编写自动配置类 SmsAutoConfiguration
      • 创建 SmsSender 接口和默认实现 DefaultSmsSenderImpl
      • 注册自动配置 (META-INF/spring.factories)
    • 8.3 sms-spring-boot-starter 模块开发 (依赖 autoconfigure 和必要的库)
    • 8.4 在另一个 Spring Boot 项目中使用自定义 Starter
      • 添加自定义 Starter 依赖
      • 配置短信参数 (application.yml)
      • 自动注入 SmsSender 并发送短信
    • 8.5 完整可运行代码示例 (包含 Starter 和使用项目)

1. Spring Boot Starter 是什么?

1.1 核心目标:简化依赖管理和配置 Spring Boot Starter 是 Spring Boot 框架的核心组件之一,其核心目标是极大地简化基于 Spring 框架的应用开发。它主要通过以下两种方式实现:

  • 简化依赖管理: 将特定功能所需的一系列相关依赖库打包成一个可传递的依赖项。开发者只需引入这一个 Starter,即可获得开发该功能所需的所有常规库。
  • 简化配置: 基于"约定大于配置"的理念,提供合理的默认配置。开发者通常只需要提供少量的必要配置(如数据库连接字符串),甚至零配置,就能让功能正常工作。

1.2 传统 Spring 应用配置的痛点 在传统的 Spring 应用开发中,集成一个新的功能(如数据库访问、安全、Web MVC)通常需要:

  1. 查找并添加多个相关的依赖到构建文件 (pom.xmlbuild.gradle),必须注意版本兼容性。
  2. 编写大量的 XML 配置文件或 Java 配置类 (@Configuration),定义各种 Bean(如 DataSource, EntityManagerFactory, TransactionManager, DispatcherServlet 等)。
  3. 手动配置这些 Bean 的属性。 这个过程繁琐、容易出错,且大量重复劳动。

1.3 Starter 如何解决痛点:约定大于配置 Spring Boot Starter 解决了这些问题:

  • 依赖打包: Starter 本身通常不包含代码,它只是一个 POM 文件 (pom.xml),声明了实现某个功能所需的一组依赖库及其兼容的版本。例如,spring-boot-starter-web 包含了 Spring MVC, Tomcat, Jackson 等开发 Web 应用所需的所有库。
  • 自动配置: 这是 Starter 背后的魔法引擎。当 Starter 被引入到项目中,Spring Boot 的自动配置机制会根据项目中存在的类路径、已定义的 Bean 和其他设置,自动地 配置 Spring 应用上下文。例如,如果类路径下有 DataSource 类,并且你没有自己定义一个 DataSource Bean,Spring Boot 会自动配置一个基于内存数据库(如 H2)或连接池(如 HikariCP)的 DataSource(取决于依赖和配置)。

1.4 Starter 的本质:依赖的聚合器 简单来说,Starter 就是一个预定义好的、针对特定功能的依赖项集合。 它让你只需声明一次"我想要 Web 功能"或"我想要 JPA 功能",Spring Boot 就会为你准备好所有必要的库和默认配置。这极大地降低了入门门槛和配置复杂度。

2. Spring Boot Starter 的工作原理 Starter 的强大功能主要依赖于 Spring Boot 的自动配置机制。

2.1 自动配置 (Auto-Configuration) 的核心地位 自动配置是 Spring Boot 的核心特性。它尝试基于你添加的 jar 依赖和你的代码配置,自动配置你的 Spring 应用。例如:

  • 如果 H2 数据库在类路径上,并且你没有配置自己的 DataSource Bean,那么 Spring Boot 会自动配置一个内存数据库。
  • 如果 Spring MVC 在类路径上,Spring Boot 会自动配置一个 DispatcherServlet 和默认的 MVC 组件(视图解析器、消息转换器等)。

2.2 spring-boot-autoconfigure 模块 这个模块包含了 Spring Boot 为各种常见场景提供的自动配置实现。它内部定义了大量的 XxxAutoConfiguration 类。每个 Starter 通常都会依赖于这个模块,并可能提供自己特定的自动配置类。

2.3 @EnableAutoConfiguration 注解 Spring Boot 应用的入口类通常使用 @SpringBootApplication 注解。这个注解是一个组合注解,包含了 @EnableAutoConfiguration。正是 @EnableAutoConfiguration 启用了自动配置机制。它告诉 Spring Boot 去扫描类路径下的 META-INF/spring.factories 文件,查找并加载其中声明的自动配置类。

2.4 META-INF/spring.factories 文件:自动配置的注册表 这是自动配置的关键注册表文件。它位于 jar 包的 META-INF 目录下。文件内容遵循 Java 的 Properties 格式。其中最重要的键是:

properties 复制代码
org.springframework.boot.autoconfigure.EnableAutoConfiguration

该键的值是一个逗号分隔的、完全限定名的自动配置类列表。例如,spring-boot-autoconfigure jar 中的 spring.factories 包含大量条目:

properties 复制代码
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
... // 很多很多其他配置类

当 Spring Boot 启动时,它会读取所有 jar 包中这个文件,收集所有的自动配置类。

2.5 条件注解 (Conditional Annotations):按需配置的魔法 Spring Boot 不会简单地加载 spring.factories 中列出的所有配置类。它使用条件注解 来决定一个配置类(或配置类中的一个 @Bean 方法)是否应该生效。这确保了配置只在满足特定条件时被应用。常用的条件注解包括:

  • @ConditionalOnClass :只有当指定的类存在于类路径上时,配置才生效。例如,DataSourceAutoConfiguration 可能只在检测到 DataSource 类存在时才生效。
  • @ConditionalOnMissingBean :只有当 Spring 应用上下文中不存在指定类型的 Bean 时,配置才生效。这让你可以轻松地提供自己的实现来覆盖自动配置。例如,自动配置的 DataSource 可能只在没有用户定义的 DataSource Bean 时创建。
  • @ConditionalOnProperty :只有当指定的环境属性(通常在 application.propertiesapplication.yml 中)存在、缺失或具有特定值时,配置才生效。这提供了灵活的配置开关。例如,@ConditionalOnProperty(name = "spring.datasource.url") 确保只有配置了数据库 URL 时才尝试配置数据源。
  • @ConditionalOnWebApplication:只有当应用是一个 Web 应用(基于 Servlet 或 Reactive)时,配置才生效。
  • @ConditionalOnNotWebApplication:与上面相反。
  • @ConditionalOnExpression:基于 SpEL 表达式的结果进行条件判断。
  • @ConditionalOnJava:基于运行时的 Java 版本。
  • @ConditionalOnResource:基于特定资源文件是否存在。
  • @ConditionalOnSingleCandidate :当某个类型的 Bean 存在且是唯一候选(或主要候选)时生效。 这些注解通常组合使用在一个自动配置类或其 @Bean 方法上,精确控制配置的生效时机。

2.6 配置属性 (Configuration Properties):@ConfigurationProperties 自动配置通常需要读取外部配置(如 application.properties)。Spring Boot 提供了 @ConfigurationProperties 注解,用于将配置文件中的属性绑定到 Java Bean 上。这些属性 Bean 通常由自动配置类注入并使用。例如:

java 复制代码
@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceProperties {
    private String url;
    private String username;
    private String password;
    // ... getters and setters
}

在自动配置类中:

java 复制代码
@AutoConfiguration
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceAutoConfiguration {
    @Bean
    @ConditionalOnMissingBean(DataSource.class)
    public DataSource dataSource(DataSourceProperties properties) {
        // 使用 properties.getUrl(), properties.getUsername() 等创建 DataSource
        return ...;
    }
}

这样,用户只需在 application.properties 中设置 spring.datasource.url=...,这些值就会自动注入到 DataSourceProperties,进而用于创建 DataSource Bean。

3. 如何使用官方提供的 Spring Boot Starter

3.1 在 pom.xml 中添加 Starter 依赖 使用官方 Starter 非常简单。只需要在你的 Spring Boot 项目的 pom.xml 文件的 <dependencies> 部分添加所需的 Starter。命名约定通常是 spring-boot-starter-*。例如:

XML 复制代码
<!-- 添加 Web 功能 (MVC, Tomcat, Jackson...) -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- 添加 JPA 和 Hibernate (假设使用 Hibernate) -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<!-- 添加嵌入式 H2 数据库 -->
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>runtime</scope>
</dependency>

Spring Boot 的依赖管理 (spring-boot-starter-parentspring-boot-dependencies BOM) 会确保这些 Starter 及其传递依赖的版本是兼容的。

3.2 理解 Starter 带来的依赖传递 使用 mvn dependency:tree 命令可以查看添加 Starter 后引入的所有传递依赖。理解这些依赖有助于排查问题。

3.3 自动配置生效的验证 Spring Boot 应用启动时,会在日志中输出自动配置报告。将日志级别设置为 DEBUG (在 application.properties 中设置 logging.level.root=DEBUG) 可以查看更详细的报告。报告会列出:

  • 评估了哪些自动配置类 (AutoConfiguration classes)。
  • 哪些通过了条件注解 (Condition),因此被应用 (Positive matches)。
  • 哪些没有通过条件注解 (Condition),因此没有被应用 (Negative matches)。
  • 哪些因为排除等原因未被评估 (Exclusions)。 这是理解自动配置行为的重要工具。

3.4 覆盖自动配置:自定义 Bean 和属性配置 自动配置不是不可变的。你有两种主要方式来覆盖它:

  1. 定义自己的 Bean: 如果你在配置类 (@Configuration) 中定义了一个与自动配置打算创建的 Bean 类型相同的 Bean,并且该 Bean 满足条件注解(如 @ConditionalOnMissingBean)的条件,那么你的 Bean 将优先被使用,自动配置的 Bean 将不会被创建。
  2. 使用外部配置属性:application.propertiesapplication.yml 中设置属性值,这些值会通过 @ConfigurationProperties 绑定到自动配置使用的属性对象上,从而改变自动配置的行为。例如,设置 spring.datasource.url=jdbc:mysql://localhost/mydb 会覆盖默认的内存数据库配置。

3.5 禁用特定的自动配置类 如果你完全不想要某个自动配置生效,可以使用 @SpringBootApplication@EnableAutoConfigurationexclude 属性来禁用特定的自动配置类:

java 复制代码
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, SecurityAutoConfiguration.class})
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

或者在 application.properties 中:

properties 复制代码
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration

4. 创建自定义 Spring Boot Starter 当你开发了一个可重用的 Spring 组件或集成库,并且希望它像官方 Starter 一样提供开箱即用的体验时,可以创建自定义 Starter。

4.1 明确 Starter 的目的和功能 清晰定义你的 Starter 要解决的问题、提供的核心功能以及所需的配置项。

4.2 创建独立的 Starter 模块项目 通常建议将 Starter 拆分成两个模块(使用 Maven 或 Gradle):

  • yourmodule-spring-boot-autoconfigure :包含自动配置类 (XxxAutoConfiguration)、配置属性类 (XxxProperties)、条件注解(如果需要)以及核心功能接口/抽象。这是实现自动配置逻辑的地方。 它依赖 spring-boot-autoconfigurespring-boot-configuration-processor (可选,用于元数据生成)。
  • yourmodule-spring-boot-starter :这是一个空的仅包含少量代码 的模块。它的主要作用是提供一个方便的依赖项,用户只需引入这一个依赖。它依赖于 yourmodule-spring-boot-autoconfigure 模块,以及你的 Starter 功能所需的其他第三方库 。命名遵循 xxx-spring-boot-starter 约定。 这种分离的好处是:
    • 用户可以选择只依赖 autoconfigure 模块(如果他们需要更精细的控制)。
    • 核心的自动配置逻辑与 Starter 的依赖管理解耦。

4.3 定义 Starter 的核心功能库 (autoconfigure 模块最佳实践)autoconfigure 模块中,定义你的 Starter 需要自动配置的核心功能。这通常包括:

  • 一个或多个自动配置类 (XxxAutoConfiguration)。
  • 一个或多个配置属性类 (XxxProperties)。
  • 提供核心功能的 Service 接口和默认实现类。
  • 相关的工具类。

4.4 编写自动配置类 (AutoConfiguration) 这是 Starter 的核心。

  • 类注解: 使用 @AutoConfiguration 注解标记你的类。这个注解继承自 @Configuration,并表明这是一个 Spring Boot 自动配置类。通常放在 xxx.auto 包下。
  • 使用条件注解: 在类级别或 @Bean 方法级别大量使用条件注解 (@ConditionalOnClass, @ConditionalOnMissingBean, @ConditionalOnProperty 等) 来控制配置的生效条件。确保你的配置只在合适的环境下激活。
  • 定义需要自动创建的 Bean: 在配置类中使用 @Bean 方法创建你的 Starter 需要提供的 Bean(如服务类、连接工厂、模板类等)。这些 Bean 通常是单例的。
  • 绑定配置属性 (@ConfigurationProperties):
    • 创建一个配置属性类,使用 @ConfigurationProperties(prefix = "your.prefix") 注解,并定义与你的配置项对应的字段及其 getter/setter。
    • 在你的自动配置类上使用 @EnableConfigurationProperties(XxxProperties.class) 来启用该属性类。
    • @Bean 方法中,将 XxxProperties 作为参数注入,并使用其中的值来配置你创建的 Bean。
java 复制代码
@AutoConfiguration // Spring Boot 2.7+ 推荐,替代 @Configuration
@ConditionalOnClass(SmsService.class) // 当 SmsService 在类路径上才生效
@EnableConfigurationProperties(SmsProperties.class) // 启用属性绑定
public class SmsAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean // 只有当用户没有自定义 SmsSender 时才创建
    public SmsSender smsSender(SmsProperties properties) {
        // 使用 properties 中的配置 (如 apiKey, endpoint) 创建并配置一个默认的 SmsSender 实现
        DefaultSmsSenderImpl sender = new DefaultSmsSenderImpl();
        sender.setApiKey(properties.getApiKey());
        sender.setEndpoint(properties.getEndpoint());
        return sender;
    }
}

4.5 注册自动配置类:创建 META-INF/spring.factories 为了让 Spring Boot 发现你的自动配置类,你需要在 autoconfigure 模块的 src/main/resources/META-INF/ 目录下创建一个名为 spring.factories 的文件。 文件内容如下:

properties 复制代码
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.yourcompany.autoconfigure.sms.SmsAutoConfiguration

将你的自动配置类的全限定名添加到 EnableAutoConfiguration 键的值列表中。如果有多个,用逗号分隔。

4.6 提供 Starter 模块:聚合核心库和依赖 创建 yourmodule-spring-boot-starter 模块。它的 pom.xml 应该:

  • 依赖 yourmodule-spring-boot-autoconfigure 模块。
  • 依赖你的 Starter 功能实现所需的所有其他第三方库。这些库会被传递到使用 Starter 的项目中。
  • 通常不包含代码或只包含极少的胶水代码。
XML 复制代码
<!-- yourmodule-spring-boot-starter/pom.xml -->
<dependencies>
    <dependency>
        <groupId>com.yourcompany</groupId>
        <artifactId>yourmodule-spring-boot-autoconfigure</artifactId>
        <version>${project.version}</version>
    </dependency>
    <!-- 依赖实际发送短信的 SDK 或库 -->
    <dependency>
        <groupId>com.example.sms</groupId>
        <artifactId>sms-sdk</artifactId>
        <version>1.0.0</version>
    </dependency>
</dependencies>

4.7 可选:提供额外的元数据 (spring-configuration-metadata.json) 为了在用户使用 IDE(如 IntelliJ IDEA)或在 application.properties 中输入配置时获得自动补全和文档提示,你可以为你的配置属性生成元数据。

  • autoconfigure 模块中添加依赖:

    XML 复制代码
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <optional>true</optional> <!-- 避免传递 -->
    </dependency>
  • XxxProperties 类上使用 @ConfigurationProperties,并确保字段有 Javadoc 注释。

  • 构建项目 (mvn clean package)。构建过程会生成 target/classes/META-INF/spring-configuration-metadata.json 文件。将这个文件包含在你的 autoconfigure jar 包中。 这个 JSON 文件描述了配置属性的名称、类型、描述、默认值等信息。

4.8 打包和发布 Starter 像发布普通库一样,将 autoconfigure 模块和 starter 模块打包 (mvn clean installmvn clean deploy 到 Maven 仓库)。用户只需要在他们的项目中依赖 yourmodule-spring-boot-starter 即可使用你的功能。

5. 最佳实践

  • 5.1 单一职责: 一个 Starter 应该只负责集成一个特定的技术或提供一个特定的功能集。避免创建"大而全"的 Starter。
  • 5.2 开箱即用: 提供合理的默认配置,使得用户在引入 Starter 后,仅需最少(甚至零)配置就能使用基本功能。默认配置应该适用于常见场景。
  • 5.3 谨慎使用自动配置: 虽然自动配置很强大,但要避免"过度魔法"。确保你的配置逻辑清晰,并且用户能够轻松地理解、覆盖或禁用它。大量使用条件注解是控制的关键。
  • 5.4 提供清晰、灵活的配置选项: 通过 @ConfigurationProperties 暴露足够的配置项,让用户能够定制 Starter 的行为。提供详尽的配置属性文档。
  • 5.5 完善的文档和示例: 为你的 Starter 编写清晰的 README 文件,说明如何引入、基本用法、配置项列表以及常见问题。提供简单的示例项目。
  • 5.6 良好的命名规范: 遵循社区约定,将你的 Starter 命名为 xxx-spring-boot-starter。将自动配置模块命名为 xxx-spring-boot-autoconfigure

6. 实战案例 1:集成 Redis Starter 目标: 在 Spring Boot 项目中快速集成 Redis,使用 RedisTemplate 操作数据。

6.1 添加依赖 (pom.xml)

XML 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 如果需要连接池 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

6.2 配置 Redis (application.properties)

properties 复制代码
# Redis 服务器地址
spring.redis.host=localhost
# Redis 服务器端口
spring.redis.port=6379
# Redis 数据库索引 (默认为0)
spring.redis.database=0
# 连接池配置 (使用 commons-pool2)
spring.redis.lettuce.pool.enabled=true # 如果使用 Lettuce (默认)
spring.redis.lettuce.pool.max-idle=8
spring.redis.lettuce.pool.min-idle=0
spring.redis.lettuce.pool.max-active=8
spring.redis.lettuce.pool.max-wait=-1ms
# 或者 Jedis (需要排除 Lettuce 依赖或配置 Jedis)
# spring.redis.jedis.pool.enabled=true
# ... 类似配置

6.3 自动注入 RedisTemplateStringRedisTemplate Spring Boot 的自动配置已经创建了这两个 Bean。

java 复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/redis")
public class RedisController {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate; // 操作对象

    @Autowired
    private StringRedisTemplate stringRedisTemplate; // 操作字符串
}

6.4 示例代码:存储和读取数据

java 复制代码
@PostMapping("/set")
public String setValue(@RequestParam String key, @RequestParam String value) {
    // 使用 StringRedisTemplate 存储字符串
    stringRedisTemplate.opsForValue().set(key, value);
    return "Value set successfully for key: " + key;
}

@GetMapping("/get")
public String getValue(@RequestParam String key) {
    // 使用 StringRedisTemplate 读取字符串
    String value = stringRedisTemplate.opsForValue().get(key);
    return (value != null) ? value : "Key not found: " + key;
}

// 使用 RedisTemplate 存储对象 (需要对象可序列化)
@PostMapping("/setUser")
public String setUser(@RequestParam String key, @RequestBody User user) {
    redisTemplate.opsForValue().set(key, user);
    return "User set successfully for key: " + key;
}

@GetMapping("/getUser")
public User getUser(@RequestParam String key) {
    return (User) redisTemplate.opsForValue().get(key);
}

注意: User 类需要实现 Serializable 接口。

6.5 完整可运行代码示例 (片段) 假设一个简单的 Spring Boot 应用入口:

java 复制代码
@SpringBootApplication
public class RedisDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(RedisDemoApplication.class, args);
    }
}

结合上面的 RedisControllerUser 类,运行应用后,可以使用 Postman 或 curl 测试 /redis/set, /redis/get, /redis/setUser, /redis/getUser 等端点。确保本地或配置的 Redis 服务器正在运行。

7. 实战案例 2:集成 Spring Security Starter 目标: 快速为 Spring Boot Web 应用添加基本的安全认证和授权。

7.1 添加依赖 (pom.xml)

XML 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

7.2 默认安全配置的行为 引入 Starter 后,Spring Security 自动配置生效:

  • 所有 HTTP 端点都需要认证。
  • 自动生成一个随机密码的用户(用户名 user),密码打印在控制台日志中。
  • 提供基于表单的登录和 HTTP Basic 认证。
  • 提供注销功能。
  • 保护 CSRF 攻击。
  • 会话管理。
  • 等等。

7.3 自定义用户、密码和角色 方法 1:内存用户 (演示用)application.properties 中配置:

properties 复制代码
# 配置内存用户 (实际项目用数据库或LDAP)
spring.security.user.name=admin
spring.security.user.password=admin123
spring.security.user.roles=ADMIN,USER

方法 2:自定义 UserDetailsService (更灵活) 创建一个配置类实现 UserDetailsService

java 复制代码
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    @Override
    public UserDetailsService userDetailsService() {
        // 内存用户存储 (InMemoryUserDetailsManager)
        UserDetails user = User.withDefaultPasswordEncoder()
                .username("user")
                .password("password")
                .roles("USER")
                .build();
        UserDetails admin = User.withDefaultPasswordEncoder()
                .username("admin")
                .password("adminpass")
                .roles("USER", "ADMIN")
                .build();
        return new InMemoryUserDetailsManager(user, admin);
    }
    // 注意:`withDefaultPasswordEncoder` 仅用于演示,生产环境必须使用加密!
}

7.4 自定义安全配置 (@EnableWebSecurity, WebSecurityConfigurerAdapter) 要自定义 URL 访问规则、登录页面等,需要扩展 WebSecurityConfigurerAdapter

java 复制代码
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/", "/home", "/public/**").permitAll() // 公共访问
                .antMatchers("/admin/**").hasRole("ADMIN") // ADMIN 角色访问
                .antMatchers("/user/**").hasRole("USER") // USER 角色访问
                .anyRequest().authenticated() // 其他请求需要认证
                .and()
            .formLogin()
                .loginPage("/login") // 自定义登录页路径
                .permitAll() // 允许所有人访问登录页
                .and()
            .logout()
                .permitAll(); // 允许所有人注销
    }

    // ... 上面的 userDetailsService() Bean 定义 ...
}

7.5 示例:配置基于表单的登录和简单授权规则 结合上面的 SecurityConfig,创建一个简单的登录页面 (login.html - 需要 Thymeleaf 或其他模板引擎):

html 复制代码
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Login</title>
</head>
<body>
    <div th:if="${param.error}">Invalid username or password.</div>
    <form th:action="@{/login}" method="post">
        <label>Username: <input type="text" name="username"/></label>
        <label>Password: <input type="password" name="password"/></label>
        <button type="submit">Login</button>
    </form>
</body>
</html>

创建一个 HomeController 提供 /home, /login 等视图映射。

7.6 完整可运行代码示例 (简化版)

java 复制代码
@SpringBootApplication
public class SecurityDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(SecurityDemoApplication.class, args);
    }
}

@Controller
public class HomeController {
    @GetMapping({"/", "/home"})
    public String home() {
        return "home"; // home.html
    }
    @GetMapping("/login")
    public String login() {
        return "login"; // login.html
    }
    @GetMapping("/admin")
    @ResponseBody
    public String adminPage() {
        return "Admin Page";
    }
    @GetMapping("/user")
    @ResponseBody
    public String userPage() {
        return "User Page";
    }
}

// SecurityConfig 如上所示 (包含内存用户和 HTTP 安全配置)

运行应用,访问 /admin 会重定向到 /login。使用 admin/adminpass 登录后可以访问 /admin/user。使用 user/password 登录后只能访问 /user。访问 /home 无需登录。

8. 实战案例 3:创建自定义 Starter - 简易短信发送 Starter 目标: 创建一个 Starter,让用户只需添加依赖并配置 API key/endpoint,就能自动注入一个 SmsSender Bean 用于发送短信。

8.1 项目结构 使用 Maven 创建两个模块:

  • sms-spring-boot-autoconfigure (实现自动配置)
  • sms-spring-boot-starter (依赖 autoconfigure 和短信 SDK)

8.2 sms-spring-boot-autoconfigure 模块开发

  • pom.xml :

    XML 复制代码
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <!-- 假设我们有一个简单的短信发送接口定义在这个模块里 -->
    </dependencies>
  • SmsProperties.java (配置属性绑定):

    java 复制代码
    @ConfigurationProperties(prefix = "sms")
    public class SmsProperties {
        private String apiKey;
        private String endpoint = "https://api.smsprovider.com/send"; // 默认值
        // ... getters and setters
    }
  • SmsSender.java (服务接口):

    java 复制代码
    public interface SmsSender {
        boolean send(String phoneNumber, String message);
    }
  • DefaultSmsSenderImpl.java (默认实现 - 模拟):

    java 复制代码
    public class DefaultSmsSenderImpl implements SmsSender {
        private String apiKey;
        private String endpoint;
        // ... getters and setters for apiKey and endpoint
        @Override
        public boolean send(String phoneNumber, String message) {
            // 模拟发送逻辑,打印日志
            System.out.println("Sending SMS to " + phoneNumber + ": " + message);
            System.out.println("Using API Key: " + apiKey + ", Endpoint: " + endpoint);
            return true; // 模拟成功
        }
    }
  • SmsAutoConfiguration.java (自动配置类):

    java 复制代码
    @AutoConfiguration
    @ConditionalOnClass(SmsSender.class) // 当 SmsSender 在类路径 (即本模块) 时生效
    @EnableConfigurationProperties(SmsProperties.class)
    public class SmsAutoConfiguration {
        @Bean
        @ConditionalOnMissingBean // 用户没有自定义时才创建
        public SmsSender smsSender(SmsProperties properties) {
            DefaultSmsSenderImpl sender = new DefaultSmsSenderImpl();
            sender.setApiKey(properties.getApiKey());
            sender.setEndpoint(properties.getEndpoint());
            return sender;
        }
    }
  • src/main/resources/META-INF/spring.factories :

    properties 复制代码
    org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
    com.example.sms.autoconfigure.SmsAutoConfiguration

8.3 sms-spring-boot-starter 模块开发

  • pom.xml :

    XML 复制代码
    <dependencies>
        <dependency>
            <groupId>com.example.sms</groupId>
            <artifactId>sms-spring-boot-autoconfigure</artifactId>
            <version>1.0.0</version> <!-- 匹配 autoconfigure 版本 -->
        </dependency>
        <!-- 如果 DefaultSmsSenderImpl 使用了真实的 SDK,这里依赖它 -->
        <!-- <dependency>
            <groupId>com.real.sms</groupId>
            <artifactId>sms-sdk</artifactId>
            <version>2.0.1</version>
        </dependency> -->
    </dependencies>

    注意: 在这个例子中,DefaultSmsSenderImpl 是我们自己写的模拟类,放在 autoconfigure 模块里了。如果使用第三方 SDK,需要在这里依赖它。

8.4 在另一个 Spring Boot 项目中使用自定义 Starter

  • 添加依赖 (pom.xml) :

    XML 复制代码
    <dependency>
        <groupId>com.example.sms</groupId>
        <artifactId>sms-spring-boot-starter</artifactId>
        <version>1.0.0</version>
    </dependency>
  • 配置参数 (application.yml) :

    yaml 复制代码
    sms:
      api-key: "your_real_api_key_here" # 替换成真实 key
      # endpoint: "https://custom.endpoint.com" # 可选,覆盖默认
  • 自动注入 SmsSender 并发送短信 :

    java 复制代码
    @Service
    public class OrderService {
        private final SmsSender smsSender;
        @Autowired
        public OrderService(SmsSender smsSender) { // 自动注入
            this.smsSender = smsSender;
        }
        public void placeOrder(Order order) {
            // ... 处理订单逻辑
            // 发送短信通知
            smsSender.send(order.getCustomerPhone(), "Your order #" + order.getId() + " has been placed!");
        }
    }

    测试类:

    java 复制代码
    @SpringBootTest
    public class SmsStarterTest {
        @Autowired
        private SmsSender smsSender;
        @Test
        void testSendSms() {
            boolean sent = smsSender.send("+1234567890", "Hello from Spring Boot Starter!");
            assertTrue(sent);
            // 控制台会打印模拟发送的信息
        }
    }

8.5 完整可运行代码示例 由于涉及多个模块的完整代码较长,这里提供关键部分的代码框架。你需要:

  1. 创建父 Maven 项目 (可选)。
  2. 创建 sms-spring-boot-autoconfigure 模块,包含上述 SmsProperties, SmsSender, DefaultSmsSenderImpl, SmsAutoConfigurationspring.factories
  3. 创建 sms-spring-boot-starter 模块,依赖 autoconfigure
  4. 创建一个新的 Spring Boot 应用项目 (sms-user-demo),依赖 sms-spring-boot-starter
  5. sms-user-demoapplication.yml 中配置 sms.api-key
  6. sms-user-demo 中编写一个 @Service (如 OrderService) 或 @RestController 注入 SmsSender 并使用它。
  7. 编写单元测试 SmsStarterTest 注入 SmsSender 并测试发送。 运行 sms-user-demo 应用或执行测试,观察控制台输出,验证自定义 Starter 是否按预期工作。

这份指南涵盖了 Spring Boot Starter 的核心概念、工作原理、使用方法、自定义开发以及实战案例,力求做到详细、实用、通俗易懂且可直接运行。希望对你有所帮助!

相关推荐
独断万古他化2 小时前
【Spring 事务】事务隔离级别与事务传播机制:从理论到业务落地实操
java·后端·spring·事务隔离·事务传播
苏涵.2 小时前
三种工厂设计模式
java
lly2024062 小时前
HTML DOM 访问
开发语言
落羽的落羽2 小时前
【Linux系统】文件IO:理解文件描述符、重定向、缓冲区
linux·服务器·开发语言·数据结构·c++·人工智能·机器学习
嗯嗯**2 小时前
Neo4j学习3:Java连接图库并执行CQL
java·学习·spring·neo4j·图数据库·驱动·cql
洛阳纸贵2 小时前
JAVA高级工程师--Springboot集成ES、MySQL同步ES的方案、ES分片副本、文档及分片规划
java·spring boot·elasticsearch
.小墨迹2 小时前
apollo中速度规划的s-t图讲解【针对借道超车的问题】
开发语言·数据结构·c++·人工智能·学习
小龙报2 小时前
【数据结构与算法】单链表的综合运用:1.合并两个有序链表 2.分割链表 3.环形链表的约瑟夫问题
c语言·开发语言·数据结构·c++·算法·leetcode·链表
阿猿收手吧!2 小时前
【C++】C++原子类型隐式转换解析
java·c++