目录
- [一、Spring Boot 概述](#一、Spring Boot 概述)
-
- [1.1 Spring Boot 的优势](#1.1 Spring Boot 的优势)
- [1.2 Spring Boot 应用场景](#1.2 Spring Boot 应用场景)
- [1.3 Spring Boot 核心特性](#1.3 Spring Boot 核心特性)
- [1.4 Spring Boot 版本选择](#1.4 Spring Boot 版本选择)
- [二、Spring Boot 环境搭建](#二、Spring Boot 环境搭建)
-
- [2.1 开发工具准备](#2.1 开发工具准备)
- [2.2 项目创建方式](#2.2 项目创建方式)
- [2.3 项目结构解析](#2.3 项目结构解析)
- [2.4 第一个 Spring Boot 程序](#2.4 第一个 Spring Boot 程序)
- [三、Spring Boot 自动配置原理](#三、Spring Boot 自动配置原理)
-
- [3.1 @SpringBootApplication 注解解析](#3.1 @SpringBootApplication 注解解析)
- [3.2 自动配置实现机制](#3.2 自动配置实现机制)
- [3.3 自定义自动配置](#3.3 自定义自动配置)
- [3.4 自动配置实战案例](#3.4 自动配置实战案例)
- [四、Spring Boot 配置文件](#四、Spring Boot 配置文件)
-
- [4.1 配置文件格式](#4.1 配置文件格式)
- [4.2 配置文件加载顺序](#4.2 配置文件加载顺序)
- [4.3 配置参数引用与占位符](#4.3 配置参数引用与占位符)
- [4.4 多环境配置](#4.4 多环境配置)
一、Spring Boot 概述
1.1 Spring Boot 的优势
Spring Boot 作为 Java 开发领域中极为流行的框架,在简化配置、快速开发、内置服务器等方面具备显著优势。
在传统的 Spring 开发中,开发者往往需要花费大量时间和精力在繁琐的 XML 配置或 Java 配置类上,以完成诸如数据源配置、事务管理配置、MVC 配置等。而 Spring Boot 采用 "约定优于配置" 的理念,许多常见的配置都有默认值,大大减少了开发人员手动配置的工作量。例如,在构建一个基于 Spring Boot 的 Web 应用时,只需引入spring-boot-starter-web依赖,Spring Boot 就能自动帮我们配置好 Spring MVC、Tomcat 等相关组件,无需像传统方式那样在 XML 文件中配置大量的 Servlet、Filter、Interceptor 等。
从快速开发角度来看,Spring Boot 提供的起步依赖(Starter)机制极大地提高了开发效率。起步依赖本质上是 Maven 或 Gradle 的依赖描述符,它将项目所需的一系列依赖进行整合。比如开发一个 Web 应用,引入spring-boot-starter-web起步依赖,就自动包含了 Spring Web MVC、Tomcat 等依赖,无需逐个去查找和添加依赖。此外,Spring Boot 还支持热部署,借助 Spring DevTools 工具,开发者修改代码后无需重启应用就能看到效果,这在开发迭代过程中能节省大量的时间。
Spring Boot 内置了诸如 Tomcat、Jetty、Undertow 等服务器,使得应用可以独立运行。以一个简单的 Spring Boot 应用为例,通过mvn spring-boot:run或java -jar命令就能直接启动应用,无需将应用部署到外部的 Servlet 容器中,极大地简化了部署过程。这种方式不仅方便了开发和测试,在生产环境中也能更灵活地进行部署和管理。同时,开发者还可以根据项目需求轻松切换内置服务器,比如将默认的 Tomcat 切换为 Jetty,只需在pom.xml文件中调整依赖即可。
1.2 Spring Boot 应用场景
Spring Boot 在多个领域都有广泛的应用,其中微服务架构和快速原型开发是较为典型的场景。
在微服务架构中,每个微服务都是一个独立的、可部署的单元,Spring Boot 的特性使其非常适合构建微服务。以一个电商系统为例,它可能包含用户服务、商品服务、订单服务等多个微服务。使用 Spring Boot 可以快速搭建每个微服务,利用其自动配置和起步依赖机制,减少每个服务的基础配置工作。同时,Spring Boot 与 Spring Cloud 等微服务治理框架集成良好,能够方便地实现服务注册与发现(如使用 Eureka、Consul)、服务间通信(如通过 Feign 实现声明式调用)、负载均衡(如使用 Ribbon)等功能,提高整个微服务架构的稳定性和可维护性。
对于快速原型开发,时间是关键因素。Spring Boot 能够帮助开发者在短时间内搭建起项目框架,并快速实现基本功能。比如在一个创业项目中,需要快速验证业务想法,使用 Spring Boot 可以迅速创建一个包含用户管理、数据存储等基本功能的原型。通过引入相应的起步依赖,如spring-boot-starter-data-jpa用于数据库操作,spring-boot-starter-web用于 Web 接口开发,配合简洁的配置文件,开发者可以将更多的精力放在业务逻辑的实现上,快速迭代和优化原型,为项目的后续发展打下基础。
1.3 Spring Boot 核心特性
Spring Boot 的核心特性包括自动配置、起步依赖、Actuator 监控,这些特性相辅相成,共同提升了开发和运维的效率。
自动配置是 Spring Boot 的一大亮点。当 Spring Boot 应用启动时,会扫描类路径下的所有 jar 包,根据类路径中的依赖和配置文件(如application.properties或application.yml),结合META-INF/spring.factories文件中声明的自动配置类,自动配置项目所需的 Bean。例如,如果项目中引入了spring-boot-starter-jdbc依赖,Spring Boot 会自动配置数据源、JdbcTemplate 等相关 Bean,开发者无需手动编写配置代码。同时,自动配置类使用了@Conditional系列注解(如@ConditionalOnClass、@ConditionalOnMissingBean、@ConditionalOnProperty等)来控制配置的生效条件,只有当满足特定条件时,对应的自动配置才会生效,这使得配置更加灵活和智能。
起步依赖在前面已经提及,它是 Spring Boot 简化依赖管理的重要手段。通过起步依赖,开发者可以以一种简单的方式引入项目所需的各种依赖。不同的起步依赖对应不同的功能模块,除了常见的spring-boot-starter-web、spring-boot-starter-data-jpa,还有spring-boot-starter-mail用于邮件发送功能集成,spring-boot-starter-security用于安全认证和授权功能等。这种方式避免了手动管理大量依赖带来的版本冲突等问题,使项目的依赖管理更加清晰和便捷。
Actuator 监控是 Spring Boot 提供的用于监控和管理应用程序的模块。它提供了一系列的端点(Endpoints),通过这些端点可以获取应用的运行状态、性能指标等信息。例如,/actuator/health端点用于检查应用的健康状态,当应用依赖的数据库、缓存等服务不可用时,该端点会返回相应的错误信息;/actuator/metrics端点可以提供应用的各种性能指标,如内存使用情况、CPU 使用率、HTTP 请求计数等;/actuator/info端点可以返回一些自定义的应用信息,如版本号、构建时间等。这些监控信息对于运维人员及时了解应用的运行状况,进行性能优化和故障排查非常有帮助。同时,Actuator 还支持通过 HTTP、JMX 等方式进行访问,方便与其他监控系统集成。
1.4 Spring Boot 版本选择
截至 2024 年 7 月,Spring Boot 的最新稳定版本为 3.x 系列,同时 2.7.x 系列作为长期支持(LTS)版本仍然被广泛使用。
选择 Spring Boot 版本时,需要综合考虑项目的需求和技术栈。如果项目追求最新的特性、更好的性能优化以及对新的 Java 版本和其他框架的支持,那么 Spring Boot 3.x 是一个不错的选择。Spring Boot 3.x 对 Java 17 及以上版本有更好的支持,并且增强了对 Spring Framework 6 的集成,在云原生开发、微服务架构等方面有更多的改进和优化。例如,在云原生环境中,Spring Boot 3.x 对容器化部署的支持更加完善,与 Kubernetes 等容器编排工具的集成更加紧密。
对于一些对稳定性要求较高,且项目依赖的第三方库或组件对 Spring Boot 3.x 兼容性不佳的情况,Spring Boot 2.7.x 作为 LTS 版本是更合适的选择。它在未来一段时间内仍然会得到官方的安全更新和维护,能够满足项目对稳定性和安全性的需求。同时,Spring Boot 2.7.x 对 Java 8、11、17 等主流 JDK 版本都有很好的兼容性,可以在不同的 Java 开发环境中稳定运行,并且与许多现有的 Spring 生态系统中的项目(如 Spring Security、Spring Data 等)能够很好地集成。
在确定版本后,还需要关注版本的兼容性。在升级 Spring Boot 版本时,要仔细阅读官方的版本迁移指南,确保项目中的依赖与新版本的 Spring Boot 兼容。例如,某些第三方库可能在 Spring Boot 3.x 中需要升级到特定版本才能正常使用,否则可能会出现兼容性问题,导致应用无法启动或功能异常。
二、Spring Boot 环境搭建
2.1 开发工具准备
在开发 Spring Boot 项目时,IntelliJ IDEA 是一款功能强大且广泛使用的集成开发环境(IDE)。为了更好地支持 Spring Boot 开发,我们需要安装并配置相关的插件和构建工具。
IDEA 对 Spring Boot 有良好的支持,其 Ultimate 版本甚至集成了 Spring Boot 插件,若你使用的是 Community 版本,则需手动安装。打开 IDEA,点击菜单栏中的 "File",选择 "Settings"(在 Mac 系统中为 "IntelliJ IDEA" -> "Preferences") 。在弹出的设置窗口中,选择 "Plugins" 标签,进入插件管理页面。在插件市场(Marketplace)选项卡的搜索框中输入 "Spring Boot",找到 Spring Boot 插件后点击 "Install" 按钮进行安装。安装完成后,重启 IDEA 使插件生效。安装好插件后,在创建新项目时,就会出现 Spring Initializr 选项,通过它可以快速创建 Spring Boot 项目,并且在项目开发过程中,插件会提供诸如代码提示、自动补全、项目结构可视化等功能,大大提高开发效率。
构建工具方面,Maven 和 Gradle 是 Spring Boot 项目常用的选择。以 Maven 为例,首先要确保已安装 Maven 并配置好环境变量。可以在命令行中输入 "mvn -v" 来检查 Maven 是否安装成功并查看其版本信息。在 IDEA 中配置 Maven 时,同样进入 "Settings",在搜索框中输入 "Maven",找到 "Build, Execution, Deployment" -> "Build Tools" -> "Maven"。在 "Maven home directory" 中指定 Maven 的安装目录,"User settings file" 指定 Maven 的 settings.xml 文件路径,"Local repository" 指定本地仓库路径。若使用 Gradle,配置过程类似,在 IDEA 的设置中找到 Gradle 相关选项,指定 Gradle 的安装目录和相关配置文件路径 。合理配置构建工具后,在项目构建和依赖管理时,能够准确地下载项目所需的依赖包,确保项目的正常运行。
2.2 项目创建方式
Spring Initializr 提供了一种便捷的网页创建 Spring Boot 项目的方式。打开浏览器,访问 Spring Initializr 的官方网站(https://start.spring.io/ )。在页面中,首先选择项目构建工具,如 Maven Project 或 Gradle Project,这里以 Maven 为例;然后选择编程语言,通常为 Java;接着选择 Spring Boot 版本,可根据项目需求和前面提到的版本选择建议进行确定。在 "Project Metadata" 部分,填写 "Group"(通常是公司或组织的域名倒置,如 com.example)和 "Artifact"(项目名称)等信息。在 "Dependencies" 区域,可以勾选项目所需的依赖,比如开发 Web 应用需勾选 "Spring Web",若要进行数据库操作,可勾选 "Spring Data JPA""MySQL Driver" 等依赖。完成所有配置后,点击 "Generate" 按钮,网站会生成一个压缩包,下载并解压该压缩包,即可得到一个基本的 Spring Boot 项目结构,然后可以使用 IDEA 等 IDE 打开项目进行后续开发。
使用 IDEA 可视化创建 Spring Boot 项目也十分简单。打开 IDEA,点击 "File" -> "New" -> "Project",在弹出的新建项目窗口中,选择 "Spring Initializr",点击 "Next"。在这一步,同样需要填写项目的基本信息,如 "Group""Artifact" 等,以及选择 Spring Boot 版本。点击 "Next" 后,进入依赖选择页面,在左侧的依赖列表中勾选项目所需的依赖,已选择的依赖会显示在右侧。例如,若要开发一个简单的 Web 应用,至少勾选 "Spring Web" 依赖。最后点击 "Finish",IDEA 会自动创建项目并下载项目所需的依赖,等待下载完成后,就可以开始编写代码了。
2.3 项目结构解析
在一个 Spring Boot 项目中,主启动类起着至关重要的作用。以一个名为 "demo" 的项目为例,主启动类通常位于 "src/main/java/com/example/demo" 目录下,类名一般为 "DemoApplication" 。主启动类上使用了@SpringBootApplication注解,这个注解是 Spring Boot 应用的核心注解,它包含了@SpringBootConfiguration(标识当前类是配置类)、@EnableAutoConfiguration(启用自动配置)和@ComponentScan(启用组件扫描,默认扫描当前包及其子包下的组件) 。在主启动类的main方法中,通过SpringApplication.run(DemoApplication.class, args)来启动 Spring Boot 应用,这行代码会触发 Spring 容器的初始化,加载各种配置和 Bean,为整个应用的运行做好准备。
application配置文件用于配置 Spring Boot 应用的各种属性。常见的配置文件格式有application.properties和application.yml,它们都位于 "src/main/resources" 目录下。application.properties文件采用 "键 = 值" 的格式来配置属性,例如 "server.port=8080" 用于配置应用的端口号;而application.yml文件采用 YAML 语法,以缩进的方式来表示层级关系,如:
java
server:
port: 8080
配置文件可以对应用的各种行为进行定制,如数据库连接配置、日志级别配置、缓存配置等。并且 Spring Boot 在启动时会按照一定的顺序加载配置文件,以确定最终生效的配置。
项目的包结构一般遵循一定的规范。"src/main/java" 目录用于存放 Java 源代码,按照功能和模块进行分包,例如 "controller" 包用于存放控制器类,处理 HTTP 请求;"service" 包用于存放业务逻辑类;"repository" 包用于存放数据访问层类,与数据库进行交互等。"src/main/resources" 目录除了存放配置文件,还可以存放静态资源(如 "static" 目录下存放 CSS、JS、图片等静态文件)和模板文件(如使用 Thymeleaf 模板引擎时,模板文件存放在 "templates" 目录下) 。"src/test/java" 目录用于存放测试代码,对项目的各个功能模块进行单元测试和集成测试,以确保代码的正确性和稳定性。
2.4 第一个 Spring Boot 程序
下面我们来开发一个简单的 Hello World 接口,感受 Spring Boot 的开发流程。首先,确保项目中已经引入了 "spring-boot-starter-web" 依赖,若使用 Maven,在 "pom.xml" 文件中会有如下依赖配置:
java
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
若使用 Gradle,在 "build.gradle" 文件中添加:
java
implementation 'org.springframework.boot:spring-boot-starter-web'
在 "src/main/java/com/example/demo/controller" 包下创建一个名为 "HelloController" 的控制器类,代码如下:
java
package com.example.demo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/hello")
public String sayHello() {
return "Hello, World!";
}
}
在上述代码中,@RestController注解表示这是一个 RESTful 风格的控制器,会将方法返回值直接作为 HTTP 响应体返回,而不需要再进行额外的视图解析。@GetMapping("/hello")注解表示该方法处理 HTTP 的 GET 请求,请求路径为 "/hello" 。当访问 "/hello" 路径时,sayHello方法会返回 "Hello, World!" 字符串。
接下来启动 Spring Boot 应用,可以直接在 IDEA 中右键点击主启动类,选择 "Run",或者点击 IDEA 工具栏上的绿色运行按钮。应用启动成功后,打开浏览器,访问 "http://localhost:8080/hello"(假设应用使用默认端口 8080),浏览器页面会显示 "Hello, World!",这表明我们开发的第一个 Spring Boot 程序成功运行。也可以使用 Postman 等工具来发送 HTTP 请求进行测试,能更方便地查看请求和响应的详细信息。
三、Spring Boot 自动配置原理
3.1 @SpringBootApplication 注解解析
@SpringBootApplication是 Spring Boot 应用的核心注解,它实际上是一个组合注解,由@SpringBootConfiguration、@EnableAutoConfiguration和@ComponentScan这三个注解组成,每个注解都承担着独特而重要的作用。
@SpringBootConfiguration本质上是@Configuration注解的变体,它明确标识了标注的类是一个配置类。在 Spring 的世界里,配置类用于定义和管理 Bean 的创建与配置。例如,在一个 Spring Boot 项目中,我们可以创建一个配置类来定义数据库连接池的 Bean,代码如下:
java
@SpringBootConfiguration
public class DatabaseConfig {
@Bean
public DataSource dataSource() {
// 这里可以选择不同类型的数据源,如HikariCP、Tomcat JDBC等
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
config.setUsername("root");
config.setPassword("password");
return new HikariDataSource(config);
}
}
在上述代码中,@SpringBootConfiguration标记了DatabaseConfig类为配置类,@Bean注解定义了一个DataSource类型的 Bean,用于提供数据库连接。
@EnableAutoConfiguration是 Spring Boot 自动配置的关键注解,它的作用是根据项目的依赖和配置,自动导入合适的自动配置类。当 Spring Boot 应用启动时,@EnableAutoConfiguration会触发AutoConfigurationImportSelector类的工作,该类会读取所有 jar 包中的META-INF/spring.factories文件。在spring.factories文件中,以org.springframework.boot.autoconfigure.EnableAutoConfiguration为键,列出了一系列自动配置类。例如,如果项目中引入了spring-boot-starter-web依赖,那么WebMvcAutoConfiguration自动配置类就会被导入,它会自动配置 Spring MVC 的相关组件,包括DispatcherServlet、RequestMappingHandlerMapping、ViewResolver等,让我们能够快速搭建起一个 Web 应用。
@ComponentScan注解用于指定 Spring 容器扫描组件的包路径,默认扫描当前主启动类所在的包及其子包。通过这个注解,Spring 能够自动发现并注册被@Component、@Service、@Repository、@Controller等注解标记的组件。例如,我们在com.example.demo.controller包下创建一个UserController类,并使用@Controller注解标记它:
java
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class UserController {
@GetMapping("/user")
@ResponseBody
public String getUser() {
return "This is a user";
}
}
由于@ComponentScan默认扫描主启动类所在包及其子包,所以UserController会被 Spring 容器扫描到并注册为一个 Bean,从而能够处理 HTTP 请求。
3.2 自动配置实现机制
META-INF/spring.factories文件在 Spring Boot 自动配置中扮演着至关重要的角色,它是自动配置类的注册中心。在每个 Spring Boot 依赖的 jar 包中,都可能包含一个META-INF/spring.factories文件,该文件以属性文件的格式定义了自动配置类的映射关系。例如,在spring-boot-autoconfigure依赖的spring.factories文件中,有如下配置:
java
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
...
这表明当@EnableAutoConfiguration注解生效时,Spring Boot 会尝试加载这些自动配置类。
条件注解是控制自动配置类是否生效的关键机制。常见的条件注解有@ConditionalOnClass、@ConditionalOnMissingBean、@ConditionalOnProperty等 。以@ConditionalOnClass为例,它的作用是当指定的类在类路径下存在时,对应的自动配置类才会生效。比如DataSourceAutoConfiguration类上可能有@ConditionalOnClass(DataSource.class)注解,这意味着只有当项目中引入了数据库连接相关的依赖,使得DataSource类在类路径下存在时,DataSourceAutoConfiguration才会生效,从而自动配置数据源相关的 Bean。再看@ConditionalOnMissingBean,它表示当容器中不存在指定类型的 Bean 时,才会创建该 Bean。例如,在配置事务管理器时,如果容器中没有用户自定义的事务管理器 Bean,TransactionAutoConfiguration中的事务管理器配置才会生效。@ConditionalOnProperty则是根据配置文件中的属性来决定是否生效,比如@ConditionalOnProperty(name = "my.feature.enabled", havingValue = "true"),只有当配置文件中存在my.feature.enabled=true时,对应的配置才会生效。
自动配置的实现过程大致如下:当 Spring Boot 应用启动时,@SpringBootApplication注解生效,其中的@EnableAutoConfiguration触发AutoConfigurationImportSelector类读取META-INF/spring.factories文件中的自动配置类列表。然后,这些自动配置类会根据各自的条件注解进行筛选,只有满足条件的自动配置类才会被加载并生效,从而完成自动配置过程,为应用程序自动创建和配置所需的 Bean。
3.3 自定义自动配置
通过@Conditional注解,我们可以实现自定义的自动配置,这为 Spring Boot 应用的个性化定制提供了强大的支持。@Conditional注解是一系列条件注解的元注解,它允许我们根据特定的条件来控制 Bean 的加载。例如,我们创建一个自定义的服务MyService,并希望根据配置文件中的属性来决定是否创建这个服务的 Bean:
java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@Configuration
public class CustomAutoConfiguration {
@Bean
@ConditionalOnProperty(name = "my.service.enabled", havingValue = "true", matchIfMissing = true)
public MyService myService() {
return new MyService();
}
}
class MyService {
// 服务的具体业务逻辑
public String sayHello() {
return "Hello from MyService";
}
}
在上述代码中,@ConditionalOnProperty注解表示只有当配置文件中my.service.enabled属性的值为true或者该属性不存在时,才会创建MyService的 Bean。这样,我们可以在application.properties或application.yml文件中通过配置my.service.enabled属性来灵活控制MyService的创建。
再比如,我们希望根据类路径下是否存在某个特定的类来创建 Bean,可以使用@ConditionalOnClass注解:
java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
@Configuration
public class AnotherCustomAutoConfiguration {
@Bean
@ConditionalOnClass(RedisTemplate.class)
public RedisService redisService() {
return new RedisService();
}
}
class RedisService {
// Redis服务相关的业务逻辑
}
这里@ConditionalOnClass(RedisTemplate.class)表示只有当RedisTemplate类在类路径下存在时,才会创建RedisService的 Bean,这在项目中根据不同的依赖来动态配置 Bean 时非常有用。
3.4 自动配置实战案例
在实际项目中,有时我们需要禁用默认的自动配置,然后使用自定义的配置类。以数据源配置为例,假设 Spring Boot 默认的数据源自动配置不符合我们的需求,我们可以通过在@SpringBootApplication注解中使用exclude属性来排除默认的数据源自动配置类,如下:
java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
上述代码排除了DataSourceAutoConfiguration,这样 Spring Boot 就不会自动配置数据源。然后我们可以创建自己的数据源配置类:
java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
@Configuration
public class CustomDataSourceConfig {
@Bean
public HikariDataSource dataSource() {
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/newdb");
config.setUsername("newuser");
config.setPassword("newpassword");
return new HikariDataSource(config);
}
}
在这个自定义配置类中,我们使用 HikariCP 数据源,并根据项目的实际需求进行了详细的配置,如设置数据库连接 URL、用户名和密码等。
再比如,在 Web 应用中,我们可能希望自定义 Spring MVC 的视图解析器。Spring Boot 默认会根据依赖自动配置视图解析器,我们可以通过自定义配置类来覆盖默认配置。首先创建一个自定义的视图解析器配置类:
java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
public class CustomViewResolverConfig {
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
}
在上述配置中,我们定义了一个InternalResourceViewResolver视图解析器,并设置了视图文件的前缀和后缀。这样,当处理视图解析时,Spring MVC 会按照我们自定义的配置来查找和渲染视图,而不是使用默认的视图解析器配置,实现了对 Spring Boot 自动配置的灵活定制。
四、Spring Boot 配置文件
4.1 配置文件格式
在 Spring Boot 项目中,application.properties和application.yml是两种常用的配置文件格式,它们各有特点,开发者可根据项目需求进行选择。
application.properties文件采用传统的键值对格式,遵循 Java 标准属性文件规范,每行表示一个独立配置项,使用等号(=)或冒号(:)分隔键值。例如,配置数据库连接信息时,可以这样写:
java
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
这种格式简单直观,易于理解和编辑,对于简单的配置项非常适用。而且由于其是 Java 传统的配置文件格式,所有的 IDE 都能完美支持,不需要额外安装插件。
application.yml文件则采用 YAML(YAML Ain't Markup Language)格式,它使用缩进表示层级关系,支持复杂数据结构,使用冒号加空格(: )分隔键值。同样以数据库连接配置为例,application.yml的写法如下:
java
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
可以看到,application.yml的层级结构更加清晰,对于复杂的配置,如包含嵌套结构的配置,使用application.yml能使配置文件的可读性大大提高。此外,YAML 还支持更简洁的列表表示方式,例如配置多个 Redis 集群节点:
java
spring:
redis:
cluster:
nodes:
- 192.168.1.1:7001
- 192.168.1.2:7002
- 192.168.1.3:7003
而在application.properties中则需要写成:
java
spring.redis.cluster.nodes[0]=192.168.1.1:7001
spring.redis.cluster.nodes[1]=192.168.1.2:7002
spring.redis.cluster.nodes[2]=192.168.1.3:7003
相比之下,application.yml在处理这类配置时更加简洁明了。不过,使用application.yml需要开发者了解 YAML 语法,虽然现代 IDE 大多已内置对 YAML 的支持,但在修改配置时,需要注意缩进的正确性,否则可能会导致配置解析错误。
4.2 配置文件加载顺序
Spring Boot 在启动时会按照特定的顺序加载配置文件,了解这个顺序对于避免配置冲突和错误至关重要。
首先是内部配置文件的加载顺序,Spring Boot 会扫描以下位置的application.properties或者application.yml文件作为默认配置文件:
- file:./config/ :项目根路径下的config文件夹,优先级最高。如果在这个位置存在配置文件,其中的配置会优先被加载和应用。
- file:./ :项目根路径。若上一个位置没有找到对应的配置文件,会从这里加载。
- classpath:/config/ :类路径下的config文件夹。在项目打包后,该路径对应jar包中的resources/config目录。
- classpath:/ :类路径,即jar包中的resources目录,优先级最低。
例如,当配置应用的端口号时,如果在file:./config/application.properties中设置了server.port=8081,同时在classpath:/application.properties中设置了server.port=8080,那么应用最终会使用8081作为端口号,因为file:./config/位置的配置文件优先级更高,会覆盖低优先级的配置。
在实际项目中,还可能涉及外部配置文件。外部配置文件的加载顺序如下:
- 命令行参数:可以直接在启动命令后添加启动参数,例如java -jar demo.jar --server.port=8088,这种方式设置的参数优先级最高,会覆盖其他配置文件中的相同配置。
- 来自java:comp/env的 JNDI 属性。
- Java 系统属性(System.getProperties())。
- 操作系统环境变量。
- jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置文件。
- jar包内部的application-{profile}.properties或application.yml(带spring.profile)配置文件,再来加载不带profile。
- jar包外部的application.properties或application.yml(不带spring.profile)配置文件。
- jar包内部的application.properties或application.yml(不带spring.profile)配置文件。
- @Configuration注解类上的@PropertySource。
了解这些加载顺序,有助于我们在不同的场景下灵活配置 Spring Boot 应用,确保配置的正确性和一致性。例如,在生产环境中,可以通过命令行参数或外部配置文件来动态调整一些关键配置,而不会影响到代码本身,提高了应用的可维护性和灵活性。
4.3 配置参数引用与占位符
在 Spring Boot 的配置文件中,我们可以使用${}语法来引用其他配置项的值,实现参数的灵活配置,还可以通过random.*属性生成随机数。
使用${}语法引用配置项时,例如在application.properties文件中:
java
app.name=MyApp
app.description=${app.name} is a Spring Boot application
这里app.description的值引用了app.name的值,这样当app.name发生变化时,app.description也会随之更新,避免了重复配置和硬编码。在application.yml文件中同样可以使用这种方式,如:
java
app:
name: MyApp
description: ${app.name} is a Spring Boot application
关于随机数配置,Spring Boot 提供了多种生成随机数的方式。例如,{random.value}可以生成一个随机字符串;{random.int}生成一个随机整数;{random.long}生成一个随机长整型数。还可以指定随机数的范围,如{random.int(10)}会生成一个 0(包括)到 10(不包括)之间的随机整数,${random.int[1024,65536]}则会生成一个 1024(包括)到 65536(包括)之间的随机整数。
假设我们要为应用的某个加密密钥生成一个随机字符串,可以在配置文件中这样写:
java
security.encryption.key=${random.value}
或者在application.yml中:
java
security:
encryption:
key: ${random.value}
这样每次应用启动时,security.encryption.key都会被赋予一个不同的随机字符串,提高了应用的安全性。通过这种方式,我们可以在配置文件中灵活地使用随机数和配置参数引用,满足各种不同的配置需求,使应用的配置更加灵活和安全。
4.4 多环境配置
在实际开发中,我们通常会有开发、测试、生产等不同的环境,每个环境的配置可能会有所不同,比如数据库连接地址、服务器端口、日志级别等。Spring Boot 提供了多环境配置的支持,方便我们在不同环境下切换配置。
常见的多环境配置文件命名方式为application-{profile}.properties或application-{profile}.yml,其中{profile}表示环境标识,例如application-dev.yml代表开发环境配置,application-prod.yml代表生产环境配置。以application-dev.yml为例,配置内容可能如下:
java
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://localhost:3306/devdb
username: devuser
password: devpassword
而application-prod.yml的配置可能是:
java
server:
port: 80
spring:
datasource:
url: jdbc:mysql://prod-db-server:3306/proddb
username: produser
password: prodpassword
要激活特定的环境配置,我们可以在主配置文件application.properties或application.yml中进行设置。如果使用application.properties,可以添加如下配置:
java
spring.profiles.active=dev
如果使用application.yml,则可以这样配置:
java
spring:
profiles:
active: dev
这样 Spring Boot 在启动时就会加载application-dev.yml中的配置。
除了通过主配置文件激活环境,还可以在启动命令中指定,例如java -jar demo.jar --spring.profiles.active=prod,这种方式在部署时非常有用,可以根据不同的部署环境灵活切换配置。另外,YAML 还支持在单个文件中使用多个文档块来配置不同环境,通过---分隔,例如:
java
# 公共配置
spring:
application:
name: myapp
---
# 开发环境配置
spring:
profiles: dev
server:
port: 8080
---
# 生产环境配置
spring:
profiles: prod
server:
port: 80
通过这种多环境配置的方式,我们可以方便地管理不同环境下的配置,提高开发和部署的效率,确保应用在各个环境中都能正确运行。