SpringBoot学习笔记(1)
1. SpingBoot
概述
1.1 Web
技术栈
Spring Framework
提供了两种主要的 Web
技术栈:Servlet Stack
【基于 Spring MVC
】和Reactive Stack
【基于 Spring WebFlux
】。它们在架构、执行模型和适用场景上存在显著差异。
🔁 Servlet Stack
✅ 特点
- 阻塞式 I/O:每个请求由一个线程处理,直到响应完成。
- 线程池模型:依赖线程池来处理并发请求,线程数受限。
- 成熟稳定:生态完善,社区资源丰富。
- 开发简便:基于命令式编程,易于理解和调试。
🚫 局限
- 资源消耗大:高并发时需要大量线程,增加硬件资源消耗。
- 扩展性受限:在高并发场景下,性能瓶颈明显。
⚡ Reactive Stack
✅ 特点
- 非阻塞式 I/O:基于 Reactor 的
Mono
和Flux
,实现异步处理。 - 事件驱动模型:采用少量线程处理大量并发请求。
- 高扩展性:适合高并发、实时性要求高的应用。
- 支持响应式编程:更好地处理流式数据和背压控制。
🚫 局限
- 学习曲线陡峭:需要掌握响应式编程理念。
- 调试复杂:异步调用链调试相对困难。
- 生态相对较新:部分第三方库可能不支持响应式。
1.2 SpringBoot
简介
Spring Boot
可以简单地创建独立的、生产级的基于 Spring
的应用程序,并且可以“直接运行”。对Spring
平台和第三方库采取了约定优于配置的观点,因此可以轻松上手。大多数Spring Boot
应用程序几乎不需要配置Spring
。其特点如下:
- 创建独立的 Spring 应用程序:无需依赖外部容器,应用可独立运行。
- 直接嵌入 Tomcat、Jetty 或 Undertow:无需部署
WAR
文件。 - 提供约定优于配置的“起步”依赖:简化构建配置。
- 尽可能自动配置 Spring 和第三方库:减少手动配置。
- 提供生产就绪的特性:如指标、健康检查和外部化配置。
- 绝对不生成代码,且不需要 XML 配置:简化开发流程。
创建一个简单的SpringBoot
项目的步骤如下:
-
引入
springboot
和相关依赖<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><!-- 项目基本信息 --><groupId>com.example</groupId><artifactId>demo</artifactId><version>1.0.0-SNAPSHOT</version><name>springboot-demo</name><description>Spring Boot Demo Project</description><!-- 继承 Spring Boot 父项目 --><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.3.3</version></parent><!-- 通用配置 --><properties><java.version>17</java.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding></properties><!-- 依赖管理 --><dependencies><!-- Web 支持 --><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><!-- 打包可执行 JAR --><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build> </project>
-
编写主程序:主程序所在的包即为主包
package com.person.boot;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication public class MainApplication {public static void main(String[] args) {SpringApplication.run(MainApplication.class, args);} }
-
编写控制器
package com.person.boot.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 Spring Boot";} }
-
编写配置文件:可选,集中式管理配置
# 修改服务器端口 server.port=8081
1.3 场景
在 Spring Boot
中,将 spring-boot-starter-web
称为“场景”,是一种对模块化依赖设计理念的通俗化表达。Spring Boot
的Starter是一组预定义的依赖集合,每个 Starter
对应一个特定的开发场景,如 Web
开发、数据访问、安全等。这种设计旨在:
- 简化依赖管理:用户无需手动添加多个零散的依赖。
- 自动配置:根据
Starter
自动启用相关功能,如内嵌Tomcat
、MVC
配置。
将Starter
称为“场景”,是因为它代表了一种完整的、开箱即用的功能模块,直接对应实际开发中的某种需求场景。其它常见的场景如下:
Starter | 对应场景 | 功能说明 |
---|---|---|
spring-boot-starter-data-jpa | 数据访问场景【JPA + 数据库】 | 集成 Hibernate、Spring Data JPA |
spring-boot-starter-security | 安全场景 | 提供认证、授权、加密等安全功能 |
spring-boot-starter-test | 测试场景 | 提供 JUnit、Mockito、Spring Test 支持 |
spring-boot-starter-actuator | 监控运维场景 | 提供健康检查、指标监控等运维功能 |
对于场景,在命名上有着以下区别:
- 官方提供的场景:
spring-boot-starter-*
- 第三方提供场景:
*-spring-boot-starter
对于插件spring-boot-maven-plugin
,其作用是将应用及其所有依赖打包为可执行的Fat JAR,即包含内嵌Servlet
容器,如Tomcat
。其优势是无需外部容器,直接通过 java -jar
运行,在Linux
系统上部署极其简单。
1.4 Spring Initializr
Spring Initializr
是Spring
官方提供的 项目初始化工具,用于快速生成 Spring Boot
项目的基础结构。其核心作用是 简化项目的创建和配置流程,帮助开发者专注于业务开发而非环境搭建。生成内容如下:
my-project/
├── src/
│ ├── main/
│ │ ├── java/ # 源码目录
│ │ └── resources/ # 配置文件目录
│ └── test/ # 测试代码目录
├── pom.xml # Maven 配置文件
└── .gitignore # Git 忽略文件模板
在创建中可能会遇到以下错误:表明IntelliJ IDEA
在尝试连接Spring Initializr
以创建Spring Boot
项目时失败。这通常与网络连接、代理设置或防火墙配置有关。
Initialization failed for 'https://start.spring.io/' Please check URL, network and proxy settings.
Error message: Cannot download 'https://start.spring.io/': Connection refused: no further information
解决方法如下:
- 如果未启用
VPN
:将默认地址https://start.spring.io
更改为https://start.aliyun.com/
。 - 启用了
VPN
:- 导航至
File
>Settings
。 - 在左侧菜单中选择
Appearance & Behavior
>System Settings
>HTTP Proxy
。 - 选择
Auto-detect proxy settings
或手动配置代理。 - 点击
Check connection
,输入https://start.spring.io
,测试连接是否成功。
- 导航至
1.5 依赖管理机制
在Maven
项目中,Spring Boot
提供了一个名为 spring-boot-starter-parent
的父 POM
。通过在项目的 pom.xml
中继承该父 POM
,可以自动获得一组经过 Spring Boot
团队测试和验证的依赖版本。这意味着在添加依赖时,无需显式指定版本号,Maven
会根据父 POM
中的配置自动解析依赖版本,从而确保项目中各个库之间的兼容性和一致性。
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.3.3</version> <!-- 指定 Spring Boot 版本 -->
</parent>
如果需要覆盖某个依赖的默认版本:
-
可以在
properties
中指定:<properties><jackson.version>2.12.3</jackson.version> </properties>
-
采用
maven
的就近原则,如下:<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId<version>8.0.33</version> </dependency>
Spring Boot
提供了一系列以 spring-boot-starter-
开头的 Starter
依赖,这些是预定义的依赖集合,旨在简化特定功能的集成。例如,spring-boot-starter-web
包含了构建 Web 应用所需的所有依赖,如 Spring MVC、Tomcat、Jackson
等。通过引入相应的 Starter
,开发者无需手动添加和管理各个相关依赖,从而提高开发效率并减少配置错误的可能性。
<dependencies><!-- 引入 Spring Boot Web Starter --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
</dependencies>
1.6 自动配置机制
package com.person.boot02;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class Boot02Application {public static void main(String[] args) {var ioc = SpringApplication.run(Boot02Application.class, args);// 获取并打印 Spring IOC 容器中所有注册的 Bean 名称String[] names = ioc.getBeanDefinitionNames();for (String name : names) {System.out.println(name);}}}
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration$DispatcherServletConfiguration
dispatcherServlet
spring.mvc-org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration$DispatcherServletRegistrationConfiguration
dispatcherServletRegistration
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration
org.springframework.boot.autoconfigure.task.TaskExecutorConfigurations$ThreadPoolTaskExecutorBuilderConfiguration
threadPoolTaskExecutorBuilder
......
这些Bean
的存在表明Spring Boot
已为你完成了MVC
等基础设施搭建,开发者只需专注于业务逻辑。
Spring Boot
的包扫描规则是框架自动管理组件发现的核心机制,直接影响 @Component
、@Service
、@Controller
等注解的生效范围。
- 默认扫描规则:默认扫描
@SpringBootApplication
注解标注的主类所在的包及其所有子包。 - 自定义扫描路径
@SpringBootApplication(scanBasePackages = "com.example")
@ComponentScan("com.example")
配置绑定:Spring Boot
允许将配置文件中的配置项,自动映射到Java 类的属性上。这种机制称为配置绑定。如果某个配置项未在配置文件中显式设置,Spring Boot
会使用 类中定义的默认值,如果类属性没有初始值,则根据类型推断默认值。
1.7 底层常用注解
1.7.1 @Configuration
与SpringBootConfiguration
在Spring Boot
应用中,@Configuration
和 @SpringBootConfiguration
都用于标记配置类,但它们的用途和设计目标有所不同。
-
@Congfiguration
:标记一个类为配置类,用于定义Bean
,替代XML
配置。-
核心功能
- 定义
@Bean
方法,声明Spring
容器管理的Bean
。 - 支持组件扫描,需配合
@ComponentScan
。 - 可以与其他
@Configuration
类组合使用。
- 定义
-
使用场景
-
通用配置:任何需要定义 Bean 的配置类。
-
模块化配置:将不同功能的 Bean 拆分到多个
@Configuration
类中。 -
第三方库集成:集成非 Spring Boot 管理的库时定义 Bean,如
Mybatis
。@Configuration public class DatabaseConfig {@Beanpublic DataSource dataSource() {// 配置数据源return new HikariDataSource();} }
-
-
-
@SpringBootConfiguration
:Spring Boot 特有注解,标记主配置类,标识这是Spring Boot
应用的入口配置。-
核心特性
- 本质上是
@Configuration
的增强版,用于 Spring Boot 的自动配置机制。 - 只能有一个:整个应用中应该只有一个类标记为
@SpringBootConfiguration
。 - 通常通过
@SpringBootApplication
间接使用,因为@SpringBootApplication
已经包含@SpringBootConfiguration
。
- 本质上是
-
使用场景
-
主启动类:Spring Boot 应用的入口类。
-
测试配置:在集成测试中指定主配置类的位置。
@SpringBootConfiguration @EnableAutoConfiguration @ComponentScan public class MyApplication {public static void main(String[] args) {SpringApplication.run(MyApplication.class, args);} }
-
-
上述两个注解的核心区别总结如下:
特性 | @Configuration | @SpringBootConfiguration |
---|---|---|
所属框架 | Spring Framework | Spring Boot |
主要用途 | 通用 Bean 定义 | 标记 Spring Boot 主配置类 |
数量限制 | 可定义多个 | 整个应用只能有一个 |
自动配置支持 | 不支持自动配置机制 | 支持 Spring Boot 自动配置 |
测试上下文定位 | 需手动指定配置类 | 自动识别主配置类【通过 @SpringBootTest 】 |
1.7.2 @Bean
与@Scope
在 Spring 框架中,@Bean
和 @Scope
是两个核心注解,用于控制 Bean 的定义和作用域。
-
@Bean
:在配置类中显式声明一个方法返回的对象应注册为 Spring Bean。@Configuration public class AppConfig {@Bean(name = "dataSource") // 指定Bean名称public DataSource dataSource() {HikariDataSource ds = new HikariDataSource();ds.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");ds.setUsername("root");ds.setPassword("123456");return ds;} }
-
@Scope
:定义Bean
的作用域,常见作用域如下:@Configuration public class ScopeConfig {@Bean@Scope("singleton") // 默认值,可省略public SingletonService singletonService() {return new SingletonService();}@Bean@Scope("prototype")public PrototypeService prototypeService() {return new PrototypeService();} }
作用域 描述 singleton
默认作用域,整个容器中只有一个实例【单例】 prototype
每次请求时创建新实例 request
每个 HTTP 请求创建一个新实例【仅 Web 应用有效】 session
每个 HTTP Session 创建一个新实例【仅 Web 应用有效】 application
整个 ServletContext
生命周期中共享一个实例【仅 Web 应用有效】
1.7.3 @import
与@ComponentScan
@Import
注解用于将多个配置类组合起来,实现配置的模块化管理。其作用如下:
-
配置聚合:将分散在多个类中的配置集中到主配置类。
-
模块化加载:按需加载不同模块的配置,如数据源配置、安全配置等。
-
替代 XML 的
<import>
:实现类似 XML 配置中<import resource="other-config.xml"/>
的效果。// 数据库配置模块 @Configuration public class DatabaseConfig {@Beanpublic DataSource dataSource() {return new HikariDataSource();} }// 主配置类 @Configuration @Import(DatabaseConfig.class) // 导入其他配置类 public class AppConfig {// 其他Bean定义... }
@ComponentScan
用于自动扫描指定包路径下的 Spring 组件,并将它们注册为 Spring 容器中的 Bean。
@Configuration
@ComponentScan("com.example") // 扫描com.example包及其子包
public class AppConfig {
}
1.7.4 条件注解
在 Spring
框架中,条件注解Conditional Annotations
允许根据特定条件动态控制 Bean
的注册或配置类的加载。这类注解在 Spring Boot 的自动配置中扮演核心角色。
**@Conditional
**是所有条件注解的基注解,需配合实现 Condition
接口的类使用。
public class EnvCondition implements Condition {@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {// 检查环境变量是否包含特定值String env = context.getEnvironment().getProperty("app.env");return "prod".equals(env);}
}@Configuration
@Conditional(EnvCondition.class)
public class ProdConfig {// 仅在生产环境生效的配置
}
**@Profile
**根据激活的 Profile 加载配置。
@Configuration
@Profile("dev") // 仅在 dev 环境生效
public class DevConfig {@Beanpublic DataSource inMemoryDataSource() {return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).build();}
}
Spring Boot 的派生条件注解如下:
注解 | 作用描述 |
---|---|
@ConditionalOnClass | 当类路径存在指定类时生效 |
@ConditionalOnMissingClass | 当类路径不存在指定类时生效 |
@ConditionalOnBean | 当容器中存在指定 Bean 时生效 |
@ConditionalOnMissingBean | 当容器中不存在指定 Bean 时生效 |
@ConditionalOnProperty | 当配置属性满足条件时生效 |
@ConditionalOnWebApplication | 当应用是 Web 应用时生效 |
1.7.5 @ConfigurationProperties
和@EnableConfigurationProperties
在 Spring Boot 中,@ConfigurationProperties
和 @EnableConfigurationProperties
是用于简化外部化配置管理的核心注解。
-
@ConfigurationProperties
:将配置文件如application.properties
/application.yml
中的属性值绑定到 Java 对象。@Component @ConfigurationProperties(prefix = "app.mail") // 绑定app.mail开头的配置项 @Validated public class MailConfigProperties {@NotBlankprivate String host;private int port = 25; // 默认值private boolean sslEnabled;// Getters and Setters// Lombok的@Getter/@Setter也可用 }
app.mail.host=smtp.example.com app.mail.port=587 app.mail.ssl-enabled=true
-
@EnableConfigurationProperties
:启用对@ConfigurationProperties
注解类的处理,将配置类注册为 Spring 容器中的 Bean。使用场景如下:-
需要显式声明配置类,即非自动扫描包路径下的类。
-
第三方库的配置类无法添加
@Component
注解时。@SpringBootApplication @EnableConfigurationProperties({MailConfigProperties.class, DatabaseConfigProperties.class}) public class MyApplication {public static void main(String[] args) {SpringApplication.run(MyApplication.class, args);} }
// 步骤1:定义配置类 无需@Component @ConfigurationProperties(prefix = "app.security") public class SecurityProperties {private String secretKey;private long tokenExpiration = 3600;// Getters/Setters }// 步骤2:启用配置类 @Configuration @EnableConfigurationProperties(SecurityProperties.class) public class SecurityConfig {@Autowiredprivate SecurityProperties securityProps;@Beanpublic TokenService tokenService() {return new TokenService(securityProps.getSecretKey(), securityProps.getTokenExpiration());} }
-
1.8 自动装配原理
Spring Boot
的自动装配Auto-Configuration
是基于“约定优于配置”的理念,自动根据项目的依赖和配置,为应用程序提供合理的默认设置。这意味着开发者无需手动配置常用组件,Spring Boot
会自动完成配置,减少了繁琐的 XML 或 Java 配置。
首先会导入场景,如spring-boot-starter-web
,每个场景都会引入相关的所有依赖。但是所有场景都会引入一个核心场景spring-boot-starter
,核心场景中引入了spring-boot-autoconfigure
包,这个包里面包括所有的场景的所有配置。只要某个包下如aop
、jdbc
的所有配置类都生效,那么SpringBoot
官方的整合功能就能生效。
先简单看其中一个配置类,@AutoConfiguration
本质上就是@Configruation
,而它本质上就是@Component
。这就出现一个问题,SpringBoot
默认是扫描不到这些配置类的。
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package org.springframework.boot.autoconfigure.availability;import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.availability.ApplicationAvailability;
import org.springframework.boot.availability.ApplicationAvailabilityBean;
import org.springframework.context.annotation.Bean;@AutoConfiguration
public class ApplicationAvailabilityAutoConfiguration {public ApplicationAvailabilityAutoConfiguration() {}@Bean@ConditionalOnMissingBean({ApplicationAvailability.class})public ApplicationAvailabilityBean applicationAvailability() {return new ApplicationAvailabilityBean();}
}
这时就跟@SpringBootApplication
注解有关了,该注解包含了以下三个注解:
-
@SpringBootConfiguration
:标识当前类为配置类,是@Configuration
的特化。 -
@EnableAutoConfiguration
:启用自动装配功能。// // Source code recreated from a .class file by IntelliJ IDEA // (powered by FernFlower decompiler) //package org.springframework.boot.autoconfigure;import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.context.annotation.Import;@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import({AutoConfigurationImportSelector.class}) public @interface EnableAutoConfiguration {String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";Class<?>[] exclude() default {};String[] excludeName() default {}; }
-
@ComponentScan
:启用组件扫描,默认扫描当前包及其子包。
@EnableAutoConfiguration
注解是SpringBoot
开启自动配置的核心,从源码中发现,通过
@Import({AutoConfigurationImportSelector.class})
批量给容器中导入组件,这样SpringBoot
就会默认加载spring-boot-autoconfigure
下META/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
文件下的所有配置类。
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration
......
虽然导入了所有的配置类,但是不一定会全部生效。随便查看一个配置类的源码,不难发现都会有条件注解, 如果条件成立就可以通过@Bean
给容器添加组件,这就是按需加载的核心。并且一些配置类有@EnableConfigurationProperties
注解,这就实现了和配置文件的绑定。
import java.time.Duration;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
import org.springframework.boot.autoconfigure.condition.ConditionMessage;
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.ImportRuntimeHints;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.util.ConcurrentReferenceHashMap;
import org.springframework.util.StringUtils;@AutoConfiguration
@ConditionalOnMissingBean(name = {"messageSource"},search = SearchStrategy.CURRENT
)
@AutoConfigureOrder(Integer.MIN_VALUE)
@Conditional({ResourceBundleCondition.class})
@EnableConfigurationProperties
@ImportRuntimeHints({MessageSourceRuntimeHints.class})
public class MessageSourceAutoConfiguration {private static final Resource[] NO_RESOURCES = new Resource[0];public MessageSourceAutoConfiguration() {}@Bean@ConfigurationProperties(prefix = "spring.messages")public MessageSourceProperties messageSourceProperties() {return new MessageSourceProperties();}@Beanpublic MessageSource messageSource(MessageSourceProperties properties) {ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();if (StringUtils.hasText(properties.getBasename())) {messageSource.setBasenames(StringUtils.commaDelimitedListToStringArray(StringUtils.trimAllWhitespace(properties.getBasename())));}if (properties.getEncoding() != null) {messageSource.setDefaultEncoding(properties.getEncoding().name());}messageSource.setFallbackToSystemLocale(properties.isFallbackToSystemLocale());Duration cacheDuration = properties.getCacheDuration();if (cacheDuration != null) {messageSource.setCacheMillis(cacheDuration.toMillis());}messageSource.setAlwaysUseMessageFormat(properties.isAlwaysUseMessageFormat());messageSource.setUseCodeAsDefaultMessage(properties.isUseCodeAsDefaultMessage());return messageSource;}......
}
1.9 配置文件
在 Spring Boot
中,application.properties
和 application.yml
【或 .yaml
】都是用于配置应用程序属性的文件。它们功能相同,但在语法和使用习惯上有所不同。
-
application.properties
:基于键值对,使用key=value
的形式。通过点号表示属性的层级关系。server.port=8080 spring.datasource.url=jdbc:mysql://localhost:3306/mydb spring.datasource.username=root spring.datasource.password=123456
-
application.yml
/application.yaml
:用YAML
格式,通过冒号和缩进表示属性的层级关系。server:port: 8080 spring:datasource:url: jdbc:mysql://localhost:3306/mydbusername: rootpassword: 123456
application.properties
和 application.yml
文件都用于配置应用程序的属性。对于复杂对象,如数组、集合、Map、嵌套对象等的配置,Spring Boot
提供了灵活的支持。
-
配置数组和集合:
List
、Set
、Array
-
application.properties
my.list=apple,banana,orange
@Value("${my.list}") private List<String> myList;或@Component @ConfigurationProperties(prefix = "my") public class MyConfig {private List<String> list;// getters and setters }
-
application.yml
my:list:- apple- banana- orange
-
-
配置
Map
类型-
application.properties
my.map.key1=value1 my.map.key2=value2
@Component @ConfigurationProperties(prefix = "my") public class MyConfig {private Map<String, String> map;// getters and setters }
-
application.yml
my:map:key1: value1key2: value2
-
-
配置嵌套对象和对象列表
-
application.properties
my.items[0].name=Item1 my.items[0].value=10 my.items[1].name=Item2 my.items[1].value=20
@Component @ConfigurationProperties(prefix = "my") public class MyConfig {private List<Item> items;// getters and setterspublic static class Item {private String name;private int value;// getters and setters} }
-
application.yml
my:items:- name: Item1value: 10- name: Item2value: 20
-
yaml
语法有着以下细节:
-
birthDay
推荐写为birth-day
-
文本:单引号不会转义,双引号会转义
-
大文本
-
以
|
开头,会保留格式description: |This is a multi-linestring that preservesline breaks.
-
以
>
开头,会将换行符压缩为空格summary: >This is a multi-linestring that foldsline breaks into spaces.
-
-
true
、false
、yes
、no
等在YAML
中会被解析为布尔值 -
使用
---
分隔多个文档
2. 日志配置
2.1 设置日志级别
在 Spring Boot
中,日志配置是应用开发和运维中的关键部分。Spring Boot 默认使用 SLF4J + Logback
作为日志框架,并提供了灵活的配置方式,支持通过配置文件或自定义日志配置文件进行设置。Spring Boot 支持以下日志级别,按优先级从低到高排列:
ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF
可以在 application.properties
或 application.yml
文件中设置全局或特定包的日志级别。
# 设置根日志级别为 INFO
logging.level.root=INFO# 设置特定包的日志级别为 DEBUG
logging.level.com.example=DEBUG
logging:level:root: INFOcom.example: DEBUG
日志分组:Springboot
中还内置了一些常用的日志分组,如web
、sql
。
logging.group.tomcat=org.apache.catalina,org.apache.coyote,org.apache.tomcat
logging.level.tomcat=TRACE
2.2 文件输出
Spring Boot 允许自定义控制台和文件的日志输出格式。可以在配置文件中使用 logging.pattern.console
和 logging.pattern.file
属性进行设置。
# 控制台日志输出格式
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n# 文件日志输出格式
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
常用的日志格式占位符包括:
%d{yyyy-MM-dd HH:mm:ss}
:日志时间%thread
:线程名%-5level
:日志级别,左对齐%logger{36}
:日志记录器名称,最大长度为36%msg
:日志消息%n
:换行符
除了控制台输出,Spring Boot 还支持将日志输出到文件。可以通过以下配置实现:
# 设置日志文件的名称[相对路径]
logging.file.name=app.log# 或者设置日志文件的路径[绝对路径]
logging.file.path=/var/logs# 如果同时设置了 logging.file.name 和 logging.file.path,只有 logging.file.name 会生效
2.3 日志滚动
# 指定日志文件名称
logging.file.name=logs/myapp.log# 设置滚动日志文件的命名模式[按日期和索引]
logging.pattern.rolling-file-name=logs/myapp-%d{yyyy-MM-dd}.%i.log# 设置单个日志文件的最大大小
logging.file.max-size=10MB# 设置保留的历史日志文件的最大数量
logging.file.max-history=30# 设置所有日志文件的总大小上限
logging.file.total-size-cap=1GB
对于更复杂的日志配置需求,可以使用日志框架的配置文件,如 logback-spring.xml
。将该文件放置在 src/main/resources
目录下,Spring Boot 会自动加载。如下述实现了:
-
日志文件按天归档,文件名包含日期和索引号。
-
每个日志文件最大为 10MB,超过后自动切割。
-
归档的日志文件将被压缩为
.gz
格式。 -
最多保留最近 30 天的日志文件,且总大小不超过 1GB。
<?xml version="1.0" encoding="UTF-8"?> <configuration><property name="LOG_PATH" value="logs"/><property name="LOG_FILE" value="${LOG_PATH}/app.log"/><property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"/><appender name="ROLLING_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>${LOG_FILE}</file><encoder><pattern>${LOG_PATTERN}</pattern></encoder><rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"><!-- 日志文件名格式:app-2025-05-06.0.log.gz --><fileNamePattern>${LOG_PATH}/app-%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern><!-- 单个日志文件最大大小 --><maxFileSize>10MB</maxFileSize><!-- 最多保留30天的日志 --><maxHistory>30</maxHistory><!-- 总日志文件大小上限 --><totalSizeCap>1GB</totalSizeCap></rollingPolicy></appender><root level="INFO"><appender-ref ref="ROLLING_FILE"/></root> </configuration>