SpringBoot(01): 初识SpringBoot,从Spring的痛点说起

SpringBoot(01): 初识SpringBoot,从Spring的痛点说起

你有没有过这种体验?接手一个 SSM 项目,光是搞清楚配置文件就花了两三天。web.xml 配 Servlet,applicationContext.xml 配数据源,spring-mvc.xml 配视图解析,mybatis-config.xml 配 Mapper。等这些 XML 都搞定,才能开始写第一行业务代码。

SpringBoot 就是来解决这些问题的。这篇文章我们从 Spring 的痛点出发,手动搭建第一个 SpringBoot 项目,再深入理解自动配置原理和配置文件体系。


一、SpringBoot 到底解决了什么问题?

1.1 先说说 Spring 生态

很多人分不清 Spring、SpringMVC、SpringBoot 的关系,先理清楚:

  • Spring Framework 是底层基础设施,提供 IoC 容器(控制反转)、DI(依赖注入)、AOP(面向切面编程)这些核心能力
  • SpringBoot 是建立在 Spring Framework 之上的快速开发框架,帮你自动配置、内嵌服务器、管理依赖版本
  • Spring Cloud 基于 SpringBoot,提供微服务架构的各种组件(注册中心、配置中心、网关等)

打个比方:Spring Framework 是毛坯房,啥都有但啥都得自己装;SpringBoot 是精装房,拎包入住;Spring Cloud 是小区,提供物业、安保、停车等配套服务。

1.2 传统 SSM 开发有多痛?

用 SSM(Spring + SpringMVC + MyBatis)框架开发一个 Web 项目,大概要走这么个流程:

左边的步骤,一个都不能少。而且每一步都可能出问题:

配置地狱:光 XML 配置文件就要写四五个,Servlet 3.0 之前连 web.xml 都不能省。数据源、事务管理器、视图解析器、MyBatis SqlSessionFactory,全都得手动配。

版本冲突 :Spring 5.x 要配 MyBatis 3.5.x,MyBatis 要配 mybatis-spring 2.x,数据库驱动、连接池、日志框架......一个版本对不上,运行时就给你报 ClassNotFoundExceptionNoSuchMethodError。排查起来费时费力。

部署繁琐:项目要打成 WAR 包,丢到外部 Tomcat 的 webapps 目录下。Tomcat 版本、JDK 版本、操作系统环境,每个环节都可能出幺蛾子。开发环境和生产环境不一致的问题,困扰了不少人。

启动慢:Tomcat 启动要加载所有组件,项目稍微大点,启动就得二三十秒。开发调试的时候反复重启,体验很差。

1.3 SpringBoot 怎么解决的?

SpringBoot 对上面这些痛点,逐一给出了方案:

痛点 SSM 方案 SpringBoot 方案
配置繁琐 手写多个 XML 自动配置,零 XML
依赖管理 手动管理版本,容易冲突 Starter 自动管理版本
部署方式 WAR 包 + 外部 Tomcat JAR 包 + 内嵌服务器
项目搭建 手动创建项目结构 Spring Initializr 一键生成
监控能力 需要自己集成 Actuator 开箱即用

SpringBoot 的设计理念就四个字:约定优于配置 。它预先定好了一套约定,你照着来就行,大部分东西不用配。比如你引入了 spring-boot-starter-web,它就自动帮你配好内嵌 Tomcat、DispatcherServlet、JSON 序列化。

想自定义?没问题。SpringBoot 只是给个合理的默认值,你随时可以通过配置文件覆盖。

1.4 SpringBoot 的核心特性

总结下来,SpringBoot 有这几个核心特性:

自动配置(Auto-Configuration) :根据 classpath 中的类和已有的 Bean,自动配置 Spring 应用。你引入什么依赖,它就自动配什么。

起步依赖(Starter) :把一组相关的依赖打包成一个 Starter POM。比如 spring-boot-starter-web 一个依赖就包含了 Spring MVC、Tomcat、Jackson 这些。

内嵌服务器 :不需要外部部署 Servlet 容器,应用自带 Tomcat(也支持 Jetty、Undertow),java -jar 直接运行。

Actuator:提供健康检查、指标监控、配置查看等生产级功能,运维特别好用。


二、5 分钟搭建你的第一个 SpringBoot 项目

2.1 环境准备

搭建之前,确保你本地有这些环境:

  • JDK 8+(推荐 JDK 8 或 JDK 11,生产环境用得最多)
  • Maven 3.6+(或者 Gradle,本文用 Maven)
  • 一个顺手的 IDE(IDEA 为佳)

验证一下环境:

shell 复制代码
java -version
# java version "1.8.0_371"

mvn -version
# Apache Maven 3.9.3

2.2 用 Spring Initializr 生成项目

最简单的方式是用 Spring Initializr,这是官方提供的项目生成工具。

打开页面后,做如下选择:

  • Project:Maven
  • Language:Java
  • Spring Boot:2.7.x(如果你用 JDK 8,选 2.7.x;JDK 17+ 可以选 3.x)
  • Group:com.example
  • Artifact:demo
  • Packaging:Jar
  • Java:8

然后点 "Add Dependencies",搜索并勾选 Spring Web

点 "Generate" 下载 zip 包,解压后用 IDEA 打开即可。

2.3 手动创建项目

如果你不想用网页工具,手动创建也很快。先看项目结构:

css 复制代码
springboot-demo/
├── pom.xml
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com/
│   │   │       └── example/
│   │   │           └── demo/
│   │   │               └── DemoApplication.java
│   │   └── resources/
│   │       ├── application.yml
│   │       ├── static/
│   │       └── templates/
│   └── test/
│       └── java/
│           └── com/
│               └── example/
│                   └── demo/
│                       └── DemoApplicationTests.java

pom.xml

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
         https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.18</version>
        <relativePath/>
    </parent>

    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>

    <properties>
        <java.version>1.8</java.version>
    </properties>

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

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

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

注意几个关键点:

  • spring-boot-starter-parent 做了依赖版本管理,你不用指定 Spring、Jackson、Tomcat 这些依赖的版本号
  • spring-boot-starter-web 一个依赖就引入了 Spring MVC + 内嵌 Tomcat + JSON 支持
  • spring-boot-maven-plugin 打包用的,把项目打成可执行的 fat jar

启动类

java 复制代码
package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {

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

@SpringBootApplication 是个组合注解,后面讲原理的时候会拆开分析。现在你只需要知道,加上这个注解,SpringBoot 就会自动帮你做三件事:标记配置类、开启自动配置、扫描组件。

2.4 写第一个接口

创建一个 Controller:

java 复制代码
package com.example.demo.controller;

import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api")
public class HelloController {

    @GetMapping("/hello")
    public String hello(@RequestParam(defaultValue = "World") String name) {
        return "Hello, " + name + "!";
    }

    @PostMapping("/user")
    public User createUser(@RequestBody User user) {
        user.setId(System.currentTimeMillis());
        return user;
    }

    public static class User {
        private Long id;
        private String name;
        private String email;

        public Long getId() { return id; }
        public void setId(Long id) { this.id = id; }
        public String getName() { return name; }
        public void setName(String name) { this.name = name; }
        public String getEmail() { return email; }
        public void setEmail(String email) { this.email = email; }
    }
}

在 IDEA 中运行 DemoApplication.main(),控制台会看到 Spring Boot 的 banner 和启动日志。默认端口是 8080。

测试一下:

java 复制代码
curl http://localhost:8080/api/hello
# "Hello, World!"

curl http://localhost:8080/api/hello?name=SpringBoot
# "Hello, SpringBoot!"

curl -X POST http://localhost:8080/api/user \
  -H "Content-Type: application/json" \
  -d '{"name":"张三","email":"zhangsan@example.com"}'
# {"id":1748325678901,"name":"张三","email":"zhangsan@example.com"}

就这么简单,不需要任何 XML 配置,不需要部署 Tomcat,一个 main() 方法就把 Web 服务跑起来了。

2.5 SpringBoot 项目结构解析

SpringBoot 的项目结构有明确的约定:

目录 用途
src/main/java/ Java 源代码,启动类放在根包下
src/main/resources/ 资源文件
src/main/resources/application.yml 配置文件
src/main/resources/static/ 静态资源(HTML、CSS、JS)
src/main/resources/templates/ 模板文件(Thymeleaf 等)
src/test/java/ 测试代码

启动类放在根包下是有讲究的。@SpringBootApplication 注解默认扫描当前类所在包及其子包下的所有组件。如果你把启动类放在 com.example 下,那 com.example.controllercom.example.servicecom.example.dao 这些包里的 @Component@Service@Repository 都会被自动扫描到。

如果你非要换启动类的位置,可以手动指定扫描范围:

java 复制代码
@SpringBootApplication(scanBasePackages = "com.example")

但除非有特殊需求,别这么干,按约定来就好。

2.6 常用 Starter 一览

SpringBoot 提供了一大堆官方 Starter,覆盖了大部分开发场景:

Starter 功能
spring-boot-starter-web Web 开发(Spring MVC + Tomcat)
spring-boot-starter-data-jpa JPA 数据库操作
spring-boot-starter-data-redis Redis 缓存
spring-boot-starter-security 安全认证
spring-boot-starter-amqp RabbitMQ 消息队列
spring-boot-starter-actuator 应用监控
spring-boot-starter-test 测试框架
spring-boot-starter-validation 参数校验
spring-boot-starter-mail 邮件发送
spring-boot-starter-aop AOP 切面编程

命名规则也简单:官方的叫 spring-boot-starter-*,第三方的叫 *-spring-boot-starter。比如 MyBatis-Plus 提供的 Starter 叫 mybatis-plus-boot-starter


三、一文搞懂 SpringBoot 自动配置原理

自动配置是 SpringBoot 最核心的特性,也是面试高频考点。

3.1 @SpringBootApplication 注解拆解

一切从 @SpringBootApplication 开始。看源码(SpringBoot 2.7.x):

java 复制代码
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
    @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
    @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class)
})
public @interface SpringBootApplication {
    // ...
}

它是由三个注解组合而成的:

@SpringBootConfiguration :本质上就是 @Configuration,表示当前类是一个配置类,可以声明 @Bean 方法。SpringBoot 把它单独拿出来,语义上更清晰。

@EnableAutoConfiguration :这是自动配置的入口注解,核心中的核心。它通过 @Import(AutoConfigurationImportSelector.class) 导入了一个选择器,这个选择器负责加载所有自动配置类。

@ComponentScan :开启组件扫描。默认扫描当前类所在包及其子包,把 @Controller@Service@Repository 这些注解标记的类注册为 Bean。excludeFilters 排除了一些不需要的类,避免自动配置类被重复扫描。

3.2 自动配置的完整流程

整个自动配置的过程,可以分成这几步:

详细说一下:

第一步:启动入口

java 复制代码
SpringApplication.run(DemoApplication.class, args);

这行代码做了两件事:创建 SpringApplication 实例,然后调用 run() 方法。

第二步:创建 SpringApplication 实例

java 复制代码
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
    // 推断应用类型:Servlet、Reactive 还是 None
    this.webApplicationType = WebApplicationType.deduceFromClasspath();
    // 加载 ApplicationContextInitializer
    setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
    // 加载 ApplicationListener
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    // 推断主配置类
    this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
}

这里已经在用 SpringFactoriesLoader 了------跟后面自动配置用的是同一个机制。

第三步:@EnableAutoConfiguration 触发自动配置

java 复制代码
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
    Class<?>[] exclude() default {};
    String[] excludeName() default {};
}

AutoConfigurationImportSelector 是自动配置的核心类。它的 selectImports() 方法会从 spring.factories 文件中读取所有自动配置类的全限定名。

第四步:读取 spring.factories

SpringFactoriesLoader 会扫描 classpath 下所有 jar 包的 META-INF/spring.factories 文件:

java 复制代码
# spring-boot-autoconfigure-2.7.18.jar
# /META-INF/spring.factories(部分内容)

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
...

这个文件列出了 130+ 个自动配置类(不同版本数量不同)。但并不意味着所有配置类都会生效。

第五步:条件注解过滤

这是关键一步。每个自动配置类上都有一堆条件注解,只有满足条件的才会被注册到容器中。

DataSourceAutoConfiguration 举例:

java 复制代码
@AutoConfiguration
@ConditionalOnClass(DataSource.class)
@ConditionalOnMissingBean(DataSource.class)
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({DataSourcePoolMetadataProvidersConfiguration.class,
         DataSourceInitializationConfiguration.class})
public class DataSourceAutoConfiguration {
    // ...
}

它的条件是:

  • @ConditionalOnClass(DataSource.class):classpath 中必须有 DataSource 类,也就是你引入了 JDBC 相关的依赖
  • @ConditionalOnMissingBean(DataSource.class):容器中还没有 DataSource Bean,如果你自己定义了,这个自动配置就跳过

如果你没引入 JDBC 依赖,DataSource 类不在 classpath 中,这个配置类直接被跳过。这就是 SpringBoot 的"智能"之处------你引入什么依赖,它就配什么;没引入的,它不会瞎配。

3.3 条件注解详解

SpringBoot 提供了一套丰富的条件注解,都在 org.springframework.boot.autoconfigure.condition 包下:

注解 生效条件
@ConditionalOnClass classpath 中存在指定的类
@ConditionalOnMissingClass classpath 中不存在指定的类
@ConditionalOnBean 容器中已存在指定的 Bean
@ConditionalOnMissingBean 容器中不存在指定的 Bean
@ConditionalOnProperty 配置文件中指定的属性满足条件
@ConditionalOnWebApplication 当前是 Web 应用
@ConditionalOnNotWebApplication 当前不是 Web 应用
@ConditionalOnExpression SpEL 表达式为 true
@ConditionalOnSingleCandidate 容器中指定类型的 Bean 只有一个
@ConditionalOnResource classpath 中存在指定的资源文件

其中用得最多的是 @ConditionalOnClass@ConditionalOnMissingBean@ConditionalOnProperty

@ConditionalOnMissingBean 的设计思路值得说一说。它允许开发者用自己的 Bean 覆盖 SpringBoot 的默认配置。比如你手动定义了一个 DataSource Bean,SpringBoot 就不会再自动创建。默认给你配好,你要自定义也行。

3.4 自动配置的"开"和"关"

有时候你可能不想让某个自动配置生效。SpringBoot 提供了几种排除方式:

方式一:@SpringBootApplication 的 exclude 属性

java 复制代码
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class DemoApplication {
    // ...
}

方式二:@EnableAutoConfiguration 的 exclude 属性

java 复制代码
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})

方式三:配置文件

java 复制代码
spring:
  autoconfigure:
    exclude: org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration

方式四:调试模式

如果你想知道到底哪些自动配置类生效了、哪些没生效,可以开启调试模式:

java 复制代码
debug: true

或者启动时加参数:

java 复制代码
java -jar demo.jar --debug

启动日志里会打印一份报告:

java 复制代码
============================
CONDITIONS EVALUATION REPORT
============================

Positive matches:(生效的自动配置)
-----------------
   DataSourceAutoConfiguration matched:
      - @ConditionalOnClass found required classes 'javax.sql.DataSource', 'org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType' (OnClassCondition)

Negative matches:(未生效的自动配置)
-----------------
   RedisAutoConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required class 'org.springframework.data.redis.core.RedisOperations' (OnClassCondition)

这个报告排查问题的时候非常有用。

3.5 以 WebMvcAutoConfiguration 为例走一遍

我们拿 WebMvcAutoConfiguration 来实际走一遍自动配置的过程,看看 SpringBoot 到底帮我们配了什么。

java 复制代码
@AutoConfiguration(after = ServletWebServerFactoryAutoConfiguration.class)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class})
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
public class WebMvcAutoConfiguration {
    // ...
}

条件分析:

  • 必须是 Servlet 类型的 Web 应用
  • classpath 中必须有 Servlet API、Spring MVC 的核心类
  • 容器中没有自定义的 WebMvcConfigurationSupport(如果你继承了 WebMvcConfigurationSupport,这个自动配置就失效了)

当这些条件都满足时,WebMvcAutoConfiguration 会帮你配置:

  • DispatcherServlet(前端控制器)
  • HttpMessageConverter(JSON/XML 序列化)
  • 静态资源处理(/static/public/resources/META-INF/resources
  • 错误页面(默认的白板错误页)
  • 日期格式化等

这就是为什么你加了 spring-boot-starter-web 依赖,不用写 web.xmlDispatcherServlet 就配好了。


四、application.yml 配置文件完全指南

4.1 两种配置文件格式

SpringBoot 支持两种配置文件格式:propertiesyml

application.properties

ini 复制代码
server.port=8080
spring.datasource.url=jdbc:mysql://localhost:3306/demo
spring.datasource.username=root
spring.datasource.password=123456

application.yml

yaml 复制代码
server:
  port: 8080
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/demo
    username: root
    password: 123456

两种格式功能完全等价,但 yml 的层级结构更清晰,可读性更好。实际项目中用 yml 的居多。

两个文件可以共存,同一属性以 properties 为准。但一般只保留一个,避免混乱。

4.2 YAML 语法基础

YAML 是一种缩进式的数据格式,有几个规则需要知道:

yaml 复制代码
# 基本键值对
server:
  port: 8080                    # 数字,不需要引号
  address: 0.0.0.0              # 字符串

# 列表
spring:
  mvc:
    view:
      suffixes: .html,.jsp      # 逗号分隔的列表

# 多行列表
server:
  tomcat:
    additional-tld-patterns:
      - *.tld
      - *.jar

# 布尔值
spring:
  main:
    lazy-initialization: false   # true 或 false

# 占位符
app:
  name: my-app
  description: ${app.name} is a demo project

# 多行文本
app:
  banner: |
    ========
    My App
    ========

注意几个坑:

  • yml 里缩进用空格,不能用 Tab
  • 冒号后面必须有一个空格
  • 字符串一般不需要引号,但包含特殊字符时要加引号

4.3 配置文件的加载优先级

SpringBoot 的配置来源非常多,不同来源有优先级之分。高优先级的配置会覆盖低优先级的:

最常用的几个:

命令行参数 :优先级最高。启动时通过 -- 传入:

css 复制代码
java -jar demo.jar --server.port=8081 --spring.profiles.active=prod

这在你需要临时改配置的时候特别有用,不用重新打包。

环境变量 :操作系统级别的环境变量也能被 SpringBoot 读取。比如 SERVER_PORT=8081 对应 server.port=8081。Docker/K8s 部署时常用这种方式注入配置。

jar 包外部的配置文件 :SpringBoot 会自动读取 jar 包同级目录和 config/ 子目录下的配置文件。这意味着你不用改 jar 包,只需要在旁边放一个 application.yml 就能覆盖默认配置。

arduino 复制代码
myapp/
├── config/
│   └── application.yml    ← 优先级高(外部 config 目录)
├── application.yml         ← 优先级中(外部同级目录)
└── demo.jar                ← jar 包内配置优先级最低

jar 包内部的配置文件 :就是打包进 jar 的 application.yml,优先级最低。

记住一个原则:外部配置覆盖内部配置,命令行参数覆盖一切

4.4 Profile 多环境配置

实际开发中,开发环境、测试环境、生产环境的配置肯定不同。SpringBoot 通过 Profile 机制来解决这个问题。

创建三个配置文件:

复制代码
application.yml           ← 公共配置
application-dev.yml       ← 开发环境
application-test.yml      ← 测试环境
application-prod.yml      ← 生产环境

公共配置 application.yml

yaml 复制代码
spring:
  profiles:
    active: dev            # 默认激活 dev 环境

app:
  name: springboot-demo

开发环境 application-dev.yml

yaml 复制代码
server:
  port: 8080

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/dev_db
    username: root
    password: root

logging:
  level:
    root: DEBUG

生产环境 application-prod.yml

yaml 复制代码
server:
  port: 80

spring:
  datasource:
    url: jdbc:mysql://10.0.1.100:3306/prod_db
    username: prod_user
    password: ${DB_PASSWORD}     # 从环境变量读取

logging:
  level:
    root: WARN

注意生产环境用了 ${DB_PASSWORD} 占位符,从环境变量读取密码,避免敏感信息写在配置文件里。

激活 Profile 的方式:

ini 复制代码
# 方式一:命令行参数
java -jar demo.jar --spring.profiles.active=prod

# 方式二:环境变量
export SPRING_PROFILES_ACTIVE=prod
java -jar demo.jar

# 方式三:JVM 参数
java -Dspring.profiles.active=prod -jar demo.jar

# 方式四:配置文件中指定(见上面的公共配置)

优先级也是命令行 > 环境变量 > JVM 参数 > 配置文件。

4.5 读取配置的方式

SpringBoot 提供了好几种读取配置值的方式:

方式一:@Value 注解

typescript 复制代码
@RestController
public class ConfigController {

    @Value("${server.port}")
    private int serverPort;

    @Value("${app.name:default-app}")
    private String appName;

    @GetMapping("/config")
    public Map<String, Object> getConfig() {
        Map<String, Object> map = new HashMap<>();
        map.put("serverPort", serverPort);
        map.put("appName", appName);
        return map;
    }
}

@Value 适合读取少量配置。${app.name:default-app} 中冒号后面是默认值,配置文件里没写的话就用这个默认值。

方式二:@ConfigurationProperties(推荐)

当配置项比较多的时候,用 @ConfigurationProperties 更优雅:

typescript 复制代码
@Component
@ConfigurationProperties(prefix = "app")
public class AppProperties {

    private String name;
    private String description;
    private int maxRetry = 3;        // 默认值
    private List<String> servers = new ArrayList<>();

    // getter 和 setter 必须有
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getDescription() { return description; }
    public void setDescription(String description) { this.description = description; }
    public int getMaxRetry() { return maxRetry; }
    public void setMaxRetry(int maxRetry) { this.maxRetry = maxRetry; }
    public List<String> getServers() { return servers; }
    public void setServers(List<String> servers) { this.servers = servers; }
}

对应的配置文件:

yaml 复制代码
app:
  name: my-app
  description: SpringBoot 配置演示项目
  max-retry: 5
  servers:
    - 10.0.0.1:8080
    - 10.0.0.2:8080
    - 10.0.0.3:8080

@ConfigurationProperties 的优势:

  • 类型安全,自动转换(String → int、String → List 等)
  • 支持松散绑定(配置文件写 max-retry,Java 里写 maxRetry,能自动对应)
  • 支持 JSR-303 校验(加 @Validated 注解)
  • 批量绑定,不用一个一个写 @Value

方式三:Environment 对象

typescript 复制代码
@Autowired
private Environment env;

@GetMapping("/env")
public String getEnv() {
    return env.getProperty("app.name", "unknown");
}

Environment 是 Spring 的核心接口,能访问所有配置来源(配置文件、环境变量、JVM 参数等)。适合需要动态获取配置的场景。

4.6 配置值的特殊用法

随机值:测试的时候经常需要随机端口、随机字符串,SpringBoot 内置了随机值生成:

yaml 复制代码
app:
  secret: ${random.value}                  # 随机字符串
  number: ${random.int}                    # 随机整数
  big-number: ${random.long}               # 随机长整数
  uuid: ${random.uuid}                     # 随机 UUID
  port: ${random.int[10000,19999]}         # 范围内的随机整数

多配置文件引用

yaml 复制代码
# application.yml
spring:
  profiles:
    include:
      - database           # 额外加载 application-database.yml
      - redis              # 额外加载 application-redis.yml

includeactive 的区别:active 会替换掉当前的 Profile,include 是在当前 Profile 的基础上额外加载。

配置文件中的占位符

bash 复制代码
app:
  base-url: http://localhost:8080
  api-url: ${app.base-url}/api/v1
  ws-url: ${app.base-url:ws://localhost:8080}/ws

第三个配置中 ${app.base-url:ws://localhost:8080} 的意思是:如果 app.base-url 有值就用它,没有就用冒号后面的默认值。


总结

这篇文章覆盖了 SpringBoot 的四个基础知识点:

  1. SpringBoot 解决的核心问题是配置繁琐部署复杂,通过自动配置、起步依赖、内嵌服务器三板斧来简化开发
  2. 搭建 SpringBoot 项目用 Spring Initializr 或者手动创建都很快,关键是理解项目结构约定和 Starter 机制
  3. 自动配置的原理是 @EnableAutoConfigurationSpringFactoriesLoaderspring.factories → 条件注解过滤,最终只有满足条件的配置类才会注册 Bean
  4. 配置文件支持 properties 和 yml 两种格式,通过 Profile 实现多环境管理,配置优先级遵循"外部覆盖内部"的原则

相关推荐
用户3169353811838 小时前
如何从零编写一个 Spring Boot Starter
spring boot
程序员晓琪1 天前
约定大于配置:基于 Java 包名自动生成 API 版本路由的最佳实践
java·spring boot·后端
Flittly1 天前
【AgentScope Java新手村系列】(11)中断与恢复
java·spring boot·spring
用户3521802454752 天前
🎆从 Prompt 到 Skill:让 Spring AI Agent 学会"装新技能"
人工智能·spring boot·ai编程
用户3521802454755 天前
当 Prompt 学会"热更新":Spring Boot × Nacos3 AI 实战
java·spring boot·ai编程
昵称为空C5 天前
手撸一个动态 SQL 执行引擎:不重启服务,在线增删改查任意数据库
spring boot·后端
霸道流氓气质6 天前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
于先生吖6 天前
SpringBoot对接大模型开发AI命理测算系统:八字排盘与AI解析接口源码全解
人工智能·spring boot·后端