SpringBoot 配置是指通过特定的方式(如配置文件、环境变量、命令行参数等)来定义应用程序的行为和属性。SpringBoot 提供了灵活的配置机制,允许开发者在不修改代码的情况下调整应用程序的运行参数。
application.properties 或 application.yml
SpringBoot 默认支持这两种配置文件格式,通常放在 src/main/resources
目录下。
.properties
格式示例:server.port=8080
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
.yml
格式示例:server:
port: 8080
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb
环境变量
可以通过操作系统环境变量覆盖配置,例如:
export SERVER_PORT=9090
命令行参数
在启动时通过 --
传递参数:
java -jar myapp.jar --server.port=9090
@ConfigurationProperties
用于将配置文件中的属性绑定到 Java Bean 上:
@ConfigurationProperties(prefix = "myapp")
public class MyAppConfig {
private String name;
private int version;
// getters and setters
}
SpringBoot 按照以下优先级加载配置(从高到低):
application-{profile}.properties
或 application-{profile}.yml
application.properties
或 application.yml
SpringBoot 支持通过 spring.profiles.active
指定运行环境:
spring:
profiles:
active: dev
并可以定义不同环境的配置文件,如 application-dev.yml
和 application-prod.yml
。
server:
port: 8080
servlet:
context-path: /api
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
logging:
level:
root: INFO
org.springframework.web: DEBUG
@Value("${server.port}")
private int port;
@Configuration
@ConfigurationProperties(prefix = "app")
public class AppConfig {
private String name;
private List<String> servers;
// getters and setters
}
SpringBoot 支持两种主要的配置文件格式:
key=value
的形式存储配置,支持 ISO-8859-1 编码。Properties 文件的适用场景
.properties
)。YAML 文件的适用场景
\n
)。# 数据库配置
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=123456
# 列表配置(需特殊处理)
server.ports=8080,8081,8082
# 数据库配置
spring:
datasource:
url: jdbc:mysql://localhost:3306/test
username: root
password: "123456" # 字符串可加引号
# 列表配置(原生支持)
server:
ports:
- 8080
- 8081
- 8082
编码问题
\u4E2D\u6587
)。优先级与覆盖规则
application.properties
和 application.yml
,Properties 的优先级更高。spring.config.name
和 spring.config.location
自定义文件路径。YAML 的语法陷阱
key: value
)。password: "123@456"
)。类型转换差异
server.port=8080
实际是字符串 “8080”)。port: 8080
会被识别为整数)。多环境配置
application-{profile}.properties/yml
(如 application-dev.yml
)。---
分隔符在同一文件内定义多环境配置。占位符与表达式
${}
占位符(如 ${spring.datasource.url}
)。random.int(1,100)
)。SpringBoot 支持多种配置文件格式(如 application.properties
、application.yml
),并且遵循特定的加载顺序。理解加载顺序有助于解决配置冲突和覆盖问题。
SpringBoot 会按照以下顺序加载配置文件(后加载的配置会覆盖先加载的配置):
application.properties
或 application.yml
(项目根目录)
src/main/resources/application.yml
application-{profile}.properties
或 application-{profile}.yml
(项目根目录)
src/main/resources/application-dev.yml
(当 spring.profiles.active=dev
时加载)外部配置文件(config/
目录)
config/
文件夹中的配置文件。src/main/resources/config/application.yml
外部配置文件(config/
子目录)
config/
中的配置文件。./config/application.yml
(打包后的 JAR 文件同级目录)命令行参数
--
传递的参数优先级最高。java -jar app.jar --server.port=8081
系统环境变量
export SERVER_PORT=8082
Java 系统属性(-D
参数)
-D
设置的 JVM 参数。java -Dserver.port=8083 -jar app.jar
# application.yml(默认配置)
server:
port: 8080
spring:
profiles:
active: dev # 激活 dev 环境
# application-dev.yml(开发环境)
server:
port: 8081
# application-prod.yml(生产环境)
server:
port: 80
config/application.yml
:server:
port: 9090
运行时,实际端口为 9090
(覆盖默认配置)。
Profile 优先级
application-{profile}.yml
会覆盖 application.yml
中的相同配置。
文件格式优先级
.properties
和 .yml
的优先级相同,后加载的会覆盖先加载的。
命令行参数最高优先级
例如:java -jar app.jar --server.port=7070
会覆盖所有文件配置。
避免配置冲突
如果多个配置文件定义了相同的属性,确保理解覆盖逻辑,避免意外行为。
调试配置加载
启动时添加 --debug
参数可以查看详细的配置加载日志:
java -jar app.jar --debug
SpringBoot 提供了多种配置来源,这些配置来源之间存在优先级关系,优先级高的配置会覆盖优先级低的配置。了解这些优先级规则对于正确管理和覆盖配置非常重要。
命令行参数
通过 java -jar
启动时传递的参数,例如:
java -jar app.jar --server.port=8081
--
前缀指定参数。Java 系统属性(System.getProperties()
)
通过 -D
参数设置,例如:
java -Dserver.port=8082 -jar app.jar
操作系统环境变量
直接在操作系统中设置的变量,例如:
export SERVER_PORT=8083
SERVER_PORT
转换为 server.port
。外部配置文件(application-{profile}.properties
或 application-{profile}.yml
)
例如 application-prod.yml
或 application-prod.properties
,优先级高于默认配置文件。
默认配置文件(application.properties
或 application.yml
)
项目中的 application.properties
或 application.yml
。
@Configuration
类上的 @PropertySource
注解
例如:
@Configuration
@PropertySource("classpath:custom.properties")
public class AppConfig { }
SpringBoot 默认配置
内置的默认值(如 server.port
默认为 8080
)。
假设有以下配置来源:
--server.port=9000
application.properties
:server.port=8080
application-prod.properties
:server.port=9090
最终生效的端口是 9000
,因为命令行参数优先级最高。
多环境配置
spring.profiles.active
指定激活的配置文件,例如:spring.profiles.active=prod
application-prod.properties
会覆盖默认的 application.properties
。YAML 和 Properties 文件的优先级
application.yml
和 application.properties
,properties
文件的优先级更高。配置覆盖的陷阱
自定义配置文件的加载顺序
spring.config.location
可以指定额外的配置文件路径,例如:java -jar app.jar --spring.config.location=file:/path/to/custom-config/
application.properties
。以下是一个测试配置优先级的示例:
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@RestController
class ConfigController {
@Value("${server.port}")
private String port;
@GetMapping("/port")
public String getPort() {
return "Server port: " + port;
}
}
}
/port
可以查看最终生效的 server.port
值。通过理解这些优先级规则,可以更灵活地管理 SpringBoot 应用的不同环境配置。
环境变量配置是指在SpringBoot应用中,通过操作系统或外部配置文件设置的环境变量来动态调整应用行为的一种方式。这些变量通常用于存储与部署环境相关的配置,如数据库连接、API密钥、服务端口等。
# Linux/Mac
export DB_URL=jdbc:mysql://localhost:3306/mydb
# Windows
set DB_URL=jdbc:mysql://localhost:3306/mydb
在application.properties或application.yml中引用环境变量:
# application.properties
db.url=${DB_URL}
# application.yml
db:
url: ${DB_URL}
java -jar myapp.jar --spring.datasource.url=jdbc:mysql://localhost:3306/mydb
SpringBoot加载环境变量的优先级从高到低:
@RestController
public class EnvController {
@Value("${db.url}")
private String dbUrl;
@Autowired
private Environment env;
@GetMapping("/dbinfo")
public String getDbInfo() {
// 方式1:通过@Value注解
String url1 = dbUrl;
// 方式2:通过Environment接口
String url2 = env.getProperty("db.url");
return "DB URL: " + url1 + " / " + url2;
}
}
${VARIABLE_NAME:default_value}
# application-dev.yml
db:
url: jdbc:mysql://dev-server:3306/mydb
# application-prod.yml
db:
url: ${PROD_DB_URL}
启动时指定profile:
java -jar myapp.jar --spring.profiles.active=prod
命令行参数配置是指在启动SpringBoot应用时,通过命令行直接传递参数来覆盖或设置应用的配置项。这些参数通常以--
开头,后面跟随配置属性名称和值。
java -jar your-application.jar --server.port=8081 --spring.datasource.url=jdbc:mysql://localhost:3306/mydb
--server.port=8080
--app.feature.enabled=true
-D
前缀,如-Dspring.profiles.active=dev
@SpringBootApplication
public class MyApp {
public static void main(String[] args) {
SpringApplication.run(MyApp.class, args);
}
@Value("${custom.message:Default Message}")
private String message;
@PostConstruct
public void init() {
System.out.println("Message from command line: " + message);
}
}
启动命令:
java -jar app.jar --custom.message="Hello from command line"
在SpringBoot中,命令行参数的优先级非常高:
--
前缀,否则会被当作普通JVM参数--feature.enabled=true
可以简写为--feature.enabled
参数分组:使用@ConfigurationProperties
绑定多个相关参数
@ConfigurationProperties("app")
public class AppProperties {
private String name;
private int version;
// getters and setters
}
参数验证:结合JSR-303验证
@Validated
@ConfigurationProperties("app")
public class AppProperties {
@NotNull
private String name;
@Min(1)
private int version;
}
多环境参数:结合profile使用
java -jar app.jar --spring.profiles.active=prod --db.host=prod-db.example.com
对于复杂的参数配置,可以考虑:
java -jar app.jar --debug
@Autowired
private Environment env;
public void checkProperty() {
System.out.println(env.getProperty("custom.message"));
}
SpringBoot 提供了多种配置属性的来源,允许开发者灵活地管理和覆盖配置。以下是常见的配置属性来源及其优先级(从高到低):
通过 java -jar
启动应用时,使用 --
前缀传递参数。
示例:
java -jar app.jar --server.port=8081
特点:
通过 -D
参数设置。
示例:
java -Dserver.port=8082 -jar app.jar
注意:
直接通过操作系统环境变量配置,SpringBoot 会自动转换为小写并替换 .
为 _
。
示例:
export SERVER_PORT=8083
适用场景:
application.properties
或 application.yml
。application-dev.yml
。server:
port: 8084
优先级规则:
.properties
文件优先级高于 .yml
(同目录下)。通过注解显式加载自定义配置文件。
示例:
@Configuration
@PropertySource("classpath:custom.properties")
public class AppConfig {}
限制:
.properties
。通过代码设置默认值。
示例:
SpringApplication app = new SpringApplication(MyApp.class);
app.setDefaultProperties(Collections.singletonMap("server.port", "8085"));
app.run(args);
application.yml
总是覆盖系统环境变量。server.port
转为 SERVER_PORT
。application-dev.yml
但未通过 --spring.profiles.active=dev
启用。spring.profiles.active
切换配置。/actuator/env
端点查看最终生效的配置。配置属性继承是 SpringBoot 中一种允许子配置类或子配置文件继承父配置类或父配置文件属性的机制。通过继承,可以避免重复定义相同的属性,提高配置的复用性和可维护性。
基于 @ConfigurationProperties
的继承
@ConfigurationProperties(prefix = "parent")
public class ParentProperties {
private String commonProperty;
// getters and setters
}
@ConfigurationProperties(prefix = "child")
public class ChildProperties extends ParentProperties {
private String specificProperty;
// getters and setters
}
基于配置文件的继承
application.yml
或 application.properties
中定义父配置:parent:
commonProperty: value
application-dev.yml
)继承并覆盖:parent:
commonProperty: overridden-value
使用 spring.config.import
导入父配置
spring:
config:
import: classpath:parent-config.yml
prefix
,可能会导致属性覆盖或冲突。application-dev.yml
)会覆盖通用配置文件(application.yml
)中的属性。基于类的继承
@Configuration
@ConfigurationProperties(prefix = "base")
public class BaseConfig {
private String url;
private int timeout;
// getters and setters
}
@Configuration
@ConfigurationProperties(prefix = "extended")
public class ExtendedConfig extends BaseConfig {
private boolean enabled;
// getters and setters
}
基于配置文件的继承
application.yml
(父配置):shared:
database:
url: jdbc:mysql://localhost:3306/parent
username: root
application-dev.yml
(子配置):shared:
database:
url: jdbc:mysql://dev-server:3306/child
配置属性覆盖(Configuration Property Override)是指在 SpringBoot 应用中,通过不同的配置源(如配置文件、环境变量、命令行参数等)对同一属性进行多次定义时,SpringBoot 会根据优先级规则选择最终的属性值。这种机制允许开发者在不同环境中灵活地覆盖默认配置。
SpringBoot 按照以下优先级顺序加载配置属性(从高到低):
--property=value
)java:comp/env
)System.getProperties()
)application-{profile}.properties
或 application-{profile}.yml
文件(带 Profile 的配置文件)application.properties
或 application.yml
文件(默认配置文件)@PropertySource
注解指定的属性文件SpringApplication.setDefaultProperties
设置)java -jar myapp.jar --server.port=8081
export SPRING_DATASOURCE_URL=jdbc:mysql://production-db:3306/mydb
java -jar myapp.jar
application.properties
(默认配置):server.port=8080
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
application-prod.properties
(生产环境配置):spring.datasource.url=jdbc:mysql://prod-db:3306/mydb
启动时激活 prod
Profile:
java -jar myapp.jar --spring.profiles.active=prod
属性名格式:
spring.datasource.url
对应 SPRING_DATASOURCE_URL
)。Profile 文件未生效:
application-{profile}.properties/yml
。spring.profiles.active
正确激活 Profile。属性覆盖失败:
YAML 与 Properties 混用:
application.yml
和 application.properties
,可能导致优先级混乱。@TestPropertySource
覆盖测试配置@SpringBootTest
@TestPropertySource(properties = {"server.port=0", "spring.datasource.url=jdbc:h2:mem:test"})
public class MyTest {
// 测试代码
}
通过 SpringApplication.setDefaultProperties
:
public static void main(String[] args) {
SpringApplication app = new SpringApplication(MyApp.class);
Properties props = new Properties();
props.setProperty("server.port", "8082");
app.setDefaultProperties(props);
app.run(args);
}
配置属性占位符(Property Placeholder)是 Spring/SpringBoot 中用于动态替换配置文件内容的语法,格式为 ${key:defaultValue}
。
${key}
表示引用配置文件中定义的属性值:defaultValue
为可选部分,当 key
不存在时使用默认值# 定义属性
app.name=MyApp
app.version=${APP_VERSION:1.0.0} # 带默认值
# 引用属性
welcome.message=Welcome to ${app.name}!
server:
port: ${SERVER_PORT:8080} # 优先取环境变量,不存在则用8080
@Value("${app.name}")
private String appName;
@Value("${undefined.key:default}")
private String withDefault;
@ConfigurationProperties(prefix = "mail")
public class MailConfig {
private String host; // 自动绑定 mail.host
}
SpringBoot 按以下顺序解析占位符:
base.path=/opt/app
log.path=${base.path}/logs # -> /opt/app/logs
secret.key=${random.uuid}
server.port=${random.int(8000,9000)}
占位符未解析
循环引用
a=${b}
b=${a} # 会导致启动失败
默认值失效
${key:-default}
冒号后不能有空格${key : default}
特殊字符处理
# 需用单引号包裹特殊字符
regex.pattern=${'^[a-z]+$'}
@ConfigurationProperties
而非 @Value
spring.config.import
替代已弃用的 spring.config.location
# application-dev.yml
db:
url: jdbc:mysql://localhost:3306/dev
# application-prod.yml
db:
url: ${DB_URL:jdbc:mysql://prod-server:3306/prod}
# 启动时激活环境
java -jar app.jar --spring.profiles.active=prod
配置属性引用(Property Reference)是 SpringBoot 中一种允许在配置文件中动态引用其他配置值的机制。通过 ${property.name}
语法,可以在 application.properties
或 application.yml
中引用已定义的属性值,实现配置的复用和动态组合。
application.properties
中# 定义基础属性
app.name=MyApp
app.version=1.0.0
# 引用属性
app.info=${app.name}@${app.version} # 结果为 "[email protected]"
application.yml
中app:
name: MyApp
version: 1.0.0
info: "${app.name}@${app.version}" # 结果为 "[email protected]"
database.url=jdbc:mysql://${db.host}:${db.port}/${db.name}
db.host=localhost
db.port=3306
db.name=mydb
:
指定默认值,当引用的属性不存在时使用。server.port=${custom.port:8080} # 若 custom.port 未定义,则使用 8080
app.path=${HOME}/myapp # 引用系统的 HOME 环境变量
# 错误示例
a=${b}
b=${a}
:
),需用双引号包裹。example: "${app.name}:${app.version}"
@Configuration
@ConfigurationProperties(prefix = "app")
public class AppConfig {
private String info; // 自动注入 "[email protected]"
// Getter 和 Setter
}
@SpringBootTest
public class PropertyReferenceTest {
@Value("${app.info}")
private String appInfo;
@Test
void testReference() {
System.out.println(appInfo); // 输出 "[email protected]"
}
}
配置属性加密是指将SpringBoot应用配置文件(如application.properties
或application.yml
)中的敏感信息(如数据库密码、API密钥等)进行加密存储,避免明文暴露的安全风险。SpringBoot通过集成jasypt
等库实现该功能。
<dependency>
<groupId>com.github.ulisesbocchiogroupId>
<artifactId>jasypt-spring-boot-starterartifactId>
<version>3.0.5version>
dependency>
# 加密后的值用ENC()包裹
spring.datasource.password=ENC(密文字符串)
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
public class JasyptUtil {
public static String encrypt(String key, String value) {
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
encryptor.setPassword(key);
return encryptor.encrypt(value);
}
public static String decrypt(String key, String encrypted) {
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
encryptor.setPassword(key);
return encryptor.decrypt(encrypted);
}
}
export JASYPT_ENCRYPTOR_PASSWORD=your_secret_key
java -jar app.jar --jasypt.encryptor.password=your_secret_key
jasypt.encryptor.password=your_secret_key
# 算法配置
jasypt.encryptor.algorithm=PBEWithMD5AndDES
# 迭代次数
jasypt.encryptor.keyObtentionIterations=1000
# 盐生成器
jasypt.encryptor.saltGeneratorClassName=org.jasypt.salt.RandomSaltGenerator
PBEWITHHMACSHA512ANDAES_256
String encrypted = JasyptUtil.encrypt("secret-key", "real-password");
// 输出:ENC(AbCdEfG123456...)
spring.datasource.url=jdbc:mysql://localhost:3306/db
spring.datasource.username=admin
spring.datasource.password=ENC(AbCdEfG123456...)
java -Djasypt.encryptor.password=secret-key -jar app.jar
配置属性验证是指在 Spring Boot 应用中,对从配置源(如 application.properties
或 application.yml
)加载的属性值进行合法性检查的过程。通过验证可以确保配置值符合预期,避免运行时因配置错误导致的异常或逻辑问题。
Spring Boot 支持通过 javax.validation
注解对 @ConfigurationProperties
类进行校验。
示例代码:
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;
import javax.validation.constraints.*;
@Validated // 启用验证
@ConfigurationProperties(prefix = "app")
public class AppConfig {
@NotBlank(message = "应用名称不能为空")
private String name;
@Min(value = 1, message = "端口号必须大于0")
@Max(value = 65535, message = "端口号必须小于65536")
private int port;
@Pattern(regexp = "^https?://.+", message = "URL必须以http或https开头")
private String url;
// Getters and Setters
}
通过实现 Validator
接口或使用 @PostConstruct
方法进行复杂逻辑校验。
示例代码:
import javax.annotation.PostConstruct;
@ConfigurationProperties(prefix = "db")
public class DatabaseConfig {
private String url;
private String username;
private String password;
@PostConstruct
public void validate() {
if (url == null || username == null || password == null) {
throw new IllegalStateException("数据库配置不完整");
}
}
}
注解 | 作用 |
---|---|
@NotNull |
值不能为 null |
@NotBlank |
字符串不能为空或仅空白 |
@Min /@Max |
数值最小/最大值限制 |
@Size |
集合/字符串长度限制 |
@Pattern |
正则表达式匹配 |
@Email |
邮箱格式校验 |
依赖引入:需添加 spring-boot-starter-validation
依赖:
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-validationartifactId>
dependency>
错误处理:验证失败会抛出 BindValidationException
,可通过 @ControllerAdvice
全局捕获。
嵌套验证:对嵌套对象需在字段上添加 @Valid
:
@Valid
private SecurityConfig security;
宽松绑定:Spring Boot 默认支持属性名的宽松绑定(如 myProp
可匹配 my-prop
),但验证时需注意注解是否兼容。
定义配置类:
@Validated
@ConfigurationProperties(prefix = "mail")
public class MailConfig {
@NotBlank
private String host;
@Email
private String adminEmail;
}
配置文件(application.yml
):
mail:
host: smtp.example.com
admin-email: [email protected]
启用配置:在主类添加 @EnableConfigurationProperties
:
@SpringBootApplication
@EnableConfigurationProperties(MailConfig.class)
public class MyApp { ... }
验证失败时的输出:
Binding to target org.springframework.boot.context.properties.bind.BindException:
Failed to bind properties under 'mail' to com.example.MailConfig failed:
Property: mail.adminEmail
Value: invalid-email
Reason: 必须是合法的电子邮件地址
配置属性转换(Property Conversion)是 Spring Boot 在加载配置文件(如 application.properties
或 application.yml
)时,将配置值从字符串形式自动转换为目标 Java 类型的过程。Spring Boot 内置了大量默认的类型转换器,同时也支持自定义转换逻辑。
int
、boolean
、long
等基本类型或其包装类。Duration
、Period
、LocalDate
等时间相关类型的转换。List
、Set
等集合类型。# application.properties
server.port=8080 # 转换为 int
app.enabled=true # 转换为 boolean
app.timeout=5000 # 转换为 long
app.session-timeout=30s # 转换为 Duration
app.start-date=2023-01-01 # 转换为 LocalDate
app.servers=192.168.1.1,192.168.1.2 # 转换为 List
假设有一个自定义配置类:
@ConfigurationProperties(prefix = "app")
public class AppConfig {
private List<Endpoint> endpoints;
// getter 和 setter
}
public class Endpoint {
private String url;
private int port;
// getter 和 setter
}
配置文件:
app.endpoints[0].url=http://example.com
app.endpoints[0].port=8080
app.endpoints[1].url=http://test.com
app.endpoints[1].port=9090
如果需要支持特殊类型的转换,可以实现 Converter
接口并注册为 Spring Bean。
Endpoint
的转换public class StringToEndpointConverter implements Converter<String, Endpoint> {
@Override
public Endpoint convert(String source) {
String[] parts = source.split(":");
Endpoint endpoint = new Endpoint();
endpoint.setUrl(parts[0]);
endpoint.setPort(Integer.parseInt(parts[1]));
return endpoint;
}
}
注册转换器:
@Configuration
public class ConversionConfig {
@Bean
public StringToEndpointConverter stringToEndpointConverter() {
return new StringToEndpointConverter();
}
}
配置文件:
app.endpoint=http://example.com:8080
IllegalArgumentException
。例如,将 abc
转换为 int
。s
、ms
)必须符合 Duration
或 Period
的格式要求。@ConfigurationPropertiesBinding
对于更复杂的转换逻辑,可以实现 GenericConverter
或 ConditionalGenericConverter
,并通过 @ConfigurationPropertiesBinding
注解标记为配置属性绑定专用的转换器。
@Component
@ConfigurationPropertiesBinding
public class CustomGenericConverter implements GenericConverter {
@Override
public Set<ConvertiblePair> getConvertibleTypes() {
return Collections.singleton(new ConvertiblePair(String.class, CustomType.class));
}
@Override
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
// 自定义转换逻辑
}
}
配置属性默认值指的是在 Spring Boot 应用中,当未显式配置某个属性时,Spring Boot 自动提供的预设值。这些默认值通常内置于框架或相关依赖中,旨在简化开发者的配置工作。
以下是一些典型的 Spring Boot 默认配置属性:
server.port=8080
server.servlet.context-path=
(默认为空)logging.level.root=INFO
application.properties
或 application.yml
文件中,IDE 通常会显示支持的属性和默认值。spring-boot-autoconfigure
模块中的 *AutoConfiguration
类。在 application.properties
或 application.yml
中显式定义属性即可覆盖默认值。例如:
# 覆盖服务器端口
server.port=9090
或 YAML 格式:
server:
port: 9090
可以通过 @ConfigurationProperties
和 @Bean
结合的方式为自定义属性设置默认值。例如:
@Configuration
@ConfigurationProperties(prefix = "myapp")
public class MyAppProperties {
private int timeout = 30; // 默认值30
private String name = "default";
// getters and setters
}
@Bean
public MyAppProperties myAppProperties() {
return new MyAppProperties();
}
然后在配置文件中只需覆盖部分属性:
myapp:
timeout: 60
application.properties
是 Spring Boot 默认的配置文件,采用 键值对(Key-Value) 格式存储配置信息。文件通常位于项目的 src/main/resources
目录下,Spring Boot 启动时会自动加载该文件中的配置。
键值对格式
每行定义一个配置项,格式为 key=value
,例如:
server.port=8080
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
注释
使用 #
或 !
开头表示注释:
# 这是服务器端口配置
server.port=8080
多级属性
通过 .
分隔层级,形成树形结构,例如:
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
服务器配置
server.port=8080
server.servlet.context-path=/api
数据库配置
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=123456
日志配置
logging.level.root=INFO
logging.level.com.example=DEBUG
自定义配置
支持用户自定义配置,例如:
app.name=MySpringBootApp
app.version=1.0.0
多环境配置
通过 spring.profiles.active
指定激活的配置文件(如 application-dev.properties
):
spring.profiles.active=dev
占位符(Placeholder)
支持引用其他配置项的值:
app.description=${app.name} version ${app.version}
列表/数组配置
使用逗号分隔多个值:
app.servers=192.168.1.1,192.168.1.2
以下是一个完整的 application.properties
示例:
# 服务器配置
server.port=8080
server.servlet.context-path=/demo
# 数据库配置
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=admin
spring.datasource.password=secret
# 自定义配置
app.name=SpringBootDemo
app.version=2.0.0
app.description=${app.name} @ ${server.port}
键名区分大小写
server.port
和 Server.Port
会被视为不同的配置。
避免空格
键和值中不要随意添加空格(除非是值的部分),例如:
# 错误写法
server.port = 8080
# 正确写法
server.port=8080
优先级规则
Spring Boot 会按以下顺序加载配置(后加载的覆盖前者):
application.properties
application-{profile}.properties
application.yml
是 Spring Boot 项目中的核心配置文件之一,采用 YAML(YAML Ain’t Markup Language) 格式,通过层级缩进和键值对的方式组织配置数据。相比传统的 application.properties
,YAML 格式更易读且支持复杂结构。
key: value
形式,冒号后需加空格。server:
port: 8080
servlet:
context-path: /api
spring:
datasource:
url: jdbc:mysql://localhost:3306/db
username: root
-
表示列表项,缩进需对齐。cors:
allowed-origins:
- "https://example.com"
- "http://localhost:3000"
---
分隔多个配置块,适用于不同环境的配置合并。# 公共配置
spring:
profiles:
active: dev
---
# 开发环境
spring:
profiles: dev
server:
port: 8081
server:
port: 8080
logging:
level:
org.springframework: INFO
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test
username: user
password: pass
hikari:
maximum-pool-size: 10
@Value
或 @ConfigurationProperties
绑定。app:
auth:
token-expire: 3600
secret-key: "my-secret"
spring-boot-configuration-processor
或外部化配置(如 Vault)。在 Spring Boot 中,多环境配置是一种常见的实践,允许开发者为不同的环境(如开发、测试、生产)定义不同的配置。Spring Boot 通过特定的文件命名规则来识别和加载不同环境的配置文件。
Spring Boot 的多环境配置文件遵循以下命名格式:
application-{profile}.properties
或
application-{profile}.yml
其中:
application
是固定的前缀。{profile}
是环境标识,例如 dev
(开发环境)、test
(测试环境)、prod
(生产环境)等。以下是一个典型的多环境配置文件结构:
src/main/resources/
├── application.yml # 主配置文件(公共配置)
├── application-dev.yml # 开发环境配置
├── application-test.yml # 测试环境配置
└── application-prod.yml # 生产环境配置
可以通过以下方式激活特定的环境配置:
通过 spring.profiles.active
属性
在 application.properties
或 application.yml
中指定:
spring.profiles.active=dev
或 YAML 格式:
spring:
profiles:
active: dev
通过命令行参数
在运行应用时通过 --spring.profiles.active
指定:
java -jar myapp.jar --spring.profiles.active=prod
通过环境变量
设置环境变量 SPRING_PROFILES_ACTIVE
:
export SPRING_PROFILES_ACTIVE=test
Spring Boot 会按以下顺序加载配置:
application.properties
或 application.yml
)。application-dev.yml
)。spring.config.import
引入额外的配置文件。假设有以下多环境配置:
application.yml
(公共配置)
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb
username: root
password: root
application-dev.yml
(开发环境配置)
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb_dev
logging:
level:
root: debug
application-prod.yml
(生产环境配置)
server:
port: 80
spring:
datasource:
url: jdbc:mysql://prod-db:3306/mydb_prod
username: admin
password: securepassword
避免敏感信息硬编码
生产环境的密码等敏感信息应使用环境变量或配置中心(如 Spring Cloud Config)管理。
默认环境配置
如果没有显式激活任何环境,Spring Boot 会加载 application.properties
或 application.yml
。
多环境配置的兼容性
确保不同环境的配置键一致,避免因环境切换导致配置缺失。
使用 @Profile
注解
可以通过 @Profile
注解实现 Bean 的环境隔离,例如:
@Configuration
@Profile("dev")
public class DevConfig {
// 仅开发环境生效的 Bean
}
通过合理的多环境配置文件命名和激活机制,可以轻松实现不同环境的配置切换。
在 SpringBoot 中,激活特定环境配置是指通过配置或代码的方式,指定当前应用运行的环境(如开发环境 dev
、测试环境 test
、生产环境 prod
等),从而加载对应的配置文件(如 application-dev.yml
、application-prod.yml
)。SpringBoot 会根据激活的环境自动加载相应的配置,覆盖默认的 application.yml
或 application.properties
中的配置。
SpringBoot 支持多种方式激活特定环境配置:
在 application.yml
或 application.properties
中设置 spring.profiles.active
属性:
# application.yml
spring:
profiles:
active: dev
在启动应用时通过命令行参数指定:
java -jar myapp.jar --spring.profiles.active=prod
设置操作系统环境变量:
export SPRING_PROFILES_ACTIVE=test
在启动时通过 -D
参数指定:
java -Dspring.profiles.active=dev -jar myapp.jar
SpringBoot 会根据 spring.profiles.active
的值加载对应的配置文件,命名格式为:
application-{profile}.yml
或
application-{profile}.properties
例如:
application-dev.yml
(开发环境)application-prod.yml
(生产环境)假设有以下配置文件:
# application.yml(默认配置)
server:
port: 8080
logging:
level:
root: info
# application-dev.yml(开发环境)
logging:
level:
root: debug
database:
url: jdbc:mysql://localhost:3306/dev_db
# application-prod.yml(生产环境)
server:
port: 80
database:
url: jdbc:mysql://prod-server:3306/prod_db
激活开发环境时(spring.profiles.active=dev
),SpringBoot 会合并 application.yml
和 application-dev.yml
的配置,最终生效的配置为:
server:
port: 8080
logging:
level:
root: debug
database:
url: jdbc:mysql://localhost:3306/dev_db
application-{profile}.yml
的配置会覆盖 application.yml
中的同名配置。dev,db-mock
),但需注意配置冲突。application.yml
。通过 @Profile
注解可以指定 Bean 仅在特定环境下生效:
@Configuration
@Profile("dev")
public class DevConfig {
@Bean
public DataSource devDataSource() {
// 开发环境数据源配置
}
}
在单个 application.yml
中通过 ---
分隔多环境配置:
# 公共配置
server:
port: 8080
spring:
profiles:
active: dev
---
# 开发环境配置
spring:
profiles: dev
logging:
level:
root: debug
---
# 生产环境配置
spring:
profiles: prod
server:
port: 80
配置分组管理是指将SpringBoot应用程序的配置属性按照功能或模块进行逻辑分组,以提高配置的可读性和可维护性。通过@ConfigurationProperties
注解结合前缀(prefix)实现属性绑定,可以创建多个配置类来管理不同模块的配置。
// 数据库配置组
@ConfigurationProperties(prefix = "app.datasource")
@Data
public class DataSourceProperties {
private String url;
private String username;
private String password;
private int maxPoolSize;
}
// 缓存配置组
@ConfigurationProperties(prefix = "app.cache")
@Data
public class CacheProperties {
private String host;
private int port;
private long timeout;
}
app:
datasource:
url: jdbc:mysql://localhost:3306/demo
username: root
password: 123456
max-pool-size: 20
cache:
host: redis.local
port: 6379
timeout: 5000
@ConfigurationProperties(prefix = "app")
@Data
public class AppProperties {
private DataSource datasource;
private Cache cache;
@Data
public static class DataSource {
private String url;
private String username;
}
@Data
public static class Cache {
private String host;
private int port;
}
}
@Validated
@ConfigurationProperties(prefix = "app.security")
@Data
public class SecurityProperties {
@NotEmpty
private String secretKey;
@Min(1)
@Max(60)
private int tokenExpireMinutes;
}
命名规范:
组织原则:
文档化:
属性绑定失败:
配置覆盖顺序:
类型安全:
final
(Java 16+的record类型更佳)在 Spring Boot 中,配置项的命名规范是确保配置清晰、一致且易于维护的关键。以下是详细的命名规则和最佳实践:
-
)分隔单词,例如 server.port
或 spring.datasource.url
。camelCase
和 snake_case
转换为 kebab-case
,但官方建议直接使用 kebab-case
以保持一致性。配置项通常按功能模块分层,以点(.
)分隔层级,例如:
server.port
:服务器端口配置。spring.datasource.username
:数据库用户名配置。logging.level.root
:日志级别配置。Spring Boot 为不同模块提供了标准化的配置前缀,例如:
server.*
:服务器相关配置(如端口、上下文路径)。spring.*
:Spring 框架核心配置(如数据源、事务)。logging.*
:日志相关配置。management.*
:Actuator 监控相关配置。如果项目中需要自定义配置,建议遵循以下规则:
myapp.api.timeout=5000
myapp.cache.enabled=true
myapp.security.jwt.secret
。当配置需通过环境变量传递时(如 Docker/K8s 部署),需转换为大写 + 下划线格式,例如:
server.port
→ SERVER_PORT
spring.datasource.url
→ SPRING_DATASOURCE_URL
# 标准配置示例
server.port=8080
spring.datasource.url=jdbc:mysql://localhost:3306/db
spring.datasource.username=root
logging.level.root=INFO
# 自定义配置示例
myapp.feature.enabled=true
myapp.retry.max-attempts=3
database.url
和 db.url
同时存在会导致混淆。ds.url
不如 datasource.url
清晰。通过遵循这些规范,可以显著提升配置的可读性和可维护性。
SpringBoot 提供了丰富的配置选项,可以通过 application.properties
或 application.yml
文件进行配置。以下是一些常用的基础配置项:
# 设置服务器端口,默认为 8080
server.port=8080
# 设置应用的上下文路径,默认为空
server.servlet.context-path=/myapp
# 设置服务器绑定的地址,默认为所有地址
server.address=0.0.0.0
# 数据源配置
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# 连接池配置
spring.datasource.hikari.maximum-pool-size=10
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.connection-timeout=30000
# 设置日志级别
logging.level.root=INFO
logging.level.org.springframework.web=DEBUG
logging.level.com.myapp=TRACE
# 日志文件配置
logging.file.name=myapp.log
logging.file.path=/var/log
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
# 应用名称
spring.application.name=my-springboot-app
# 激活特定的配置文件
spring.profiles.active=dev
# 静态资源路径配置
spring.mvc.static-path-pattern=/static/**
spring.web.resources.static-locations=classpath:/static/
# 文件上传配置
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=10MB
# Redis 配置
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=
spring.cache.type=redis
# 缓存过期时间
spring.cache.redis.time-to-live=600000
# 邮件配置
spring.mail.host=smtp.example.com
spring.mail.port=587
[email protected]
spring.mail.password=password
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
# 安全配置
spring.security.user.name=admin
spring.security.user.password=admin123
# CSRF 配置
spring.security.csrf.enabled=true
# Actuator 配置
management.endpoints.web.exposure.include=health,info,metrics
management.endpoint.health.show-details=always
# 自定义指标
management.metrics.tags.application=my-springboot-app
# 国际化配置
spring.messages.basename=messages
spring.messages.encoding=UTF-8
# 默认语言
spring.messages.fallback-to-system-locale=false
spring.messages.default-locale=en
# 测试数据库配置
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
# 测试日志级别
logging.level.org.springframework.test=DEBUG
# 时区配置
spring.jackson.time-zone=GMT+8
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
# 自定义属性
app.name=My Application
app.version=1.0.0
app.description=This is a Spring Boot application
# 多环境配置
spring.profiles.include=dev,db
服务器端口配置是指通过修改SpringBoot应用的配置文件,指定应用启动时监听的网络端口号。默认情况下,SpringBoot应用使用8080端口,但可以通过配置更改为其他端口。
server.port=9090
server:
port: 9090
java -jar myapp.jar --server.port=9090
export SERVER_PORT=9090
java -jar myapp.jar
server.port=0
server.port=8443
server.ssl.key-store=classpath:keystore.jks
server.ssl.key-store-password=secret
server.ssl.key-password=secret
@Bean
public ServletWebServerFactory servletContainer() {
TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
tomcat.addAdditionalTomcatConnectors(createStandardConnector());
return tomcat;
}
private Connector createStandardConnector() {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setPort(8080);
return connector;
}
netstat -ano|findstr "8080"
上下文路径(Context Path)是指Web应用程序在服务器上的根路径。例如,如果你的应用部署在 http://localhost:8080/myapp
,那么 /myapp
就是上下文路径。在SpringBoot中,上下文路径可以通过配置来修改。
/api
)。SpringBoot提供了多种配置上下文路径的方式:
application.properties
或 application.yml
# application.properties
server.servlet.context-path=/myapp
# application.yml
server:
servlet:
context-path: /myapp
export SERVER_SERVLET_CONTEXT_PATH=/myapp
java -jar myapp.jar --server.servlet.context-path=/myapp
路径格式:
/
开头(如 /myapp
)。/
结尾(错误示例:/myapp/
)。根路径:
/
表示没有上下文路径(直接通过 http://localhost:8080
访问)。影响范围:
/static
会变为 /myapp/static
)。与其他配置的冲突:
server.servlet.context-path
和 spring.mvc.servlet.path
,后者会作为前者的子路径。假设有一个简单的控制器:
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "Hello, SpringBoot!";
}
}
context-path
设置为 /myapp
,则访问路径为:http://localhost:8080/myapp/hello
。context-path
设置为 /
,则访问路径为:http://localhost:8080/hello
。启动应用后,可以通过以下方式验证:
http://localhost:8080/myapp/hello
查看是否返回预期结果。Tomcat started on port(s): 8080 (http) with context path '/myapp'
。静态资源404:
/static/style.css
。/myapp/static/style.css
或模板中的相对路径。重定向问题:
redirect:/page
时,实际会跳转到 /myapp/page
。Swagger集成:
/myapp/swagger-ui.html
。日志级别用于定义日志信息的重要性或严重程度。在Spring Boot中,常见的日志级别从低到高依次为:
Spring Boot支持通过多种方式配置日志级别:
# 设置root日志级别
logging.level.root=WARN
# 设置特定包的日志级别
logging.level.org.springframework=DEBUG
logging.level.com.example=TRACE
YAML格式:
logging:
level:
root: WARN
org.springframework: DEBUG
com.example: TRACE
java -jar myapp.jar --logging.level.org.springframework=DEBUG
@SpringBootApplication
public class MyApp {
public static void main(String[] args) {
SpringApplication.run(MyApp.class, args);
LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
loggerContext.getLogger("org.springframework").setLevel(Level.DEBUG);
}
}
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%npattern>
encoder>
appender>
<logger name="com.example.service" level="DEBUG" additivity="false">
<appender-ref ref="CONSOLE" />
logger>
<root level="INFO">
<appender-ref ref="CONSOLE" />
root>
configuration>
数据库连接配置是指在SpringBoot应用中,通过配置文件或代码方式设置与数据库建立连接所需的参数。这些参数通常包括数据库URL、用户名、密码、驱动类名等。
SpringBoot中常用的数据库连接配置参数包括:
# 基本配置
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# 连接池配置(HikariCP默认)
spring.datasource.hikari.maximum-pool-size=10
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.idle-timeout=30000
spring.datasource.hikari.max-lifetime=1800000
spring.datasource.url=jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:postgresql://localhost:5432/mydb
spring.datasource.username=postgres
spring.datasource.password=123456
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=jdbc:oracle:thin:@localhost:1521:ORCL
spring.datasource.username=system
spring.datasource.password=123456
spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
当需要连接多个数据库时,可以这样配置:
@Configuration
public class DataSourceConfig {
@Bean
@Primary
@ConfigurationProperties("spring.datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties("spring.datasource.secondary")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
}
对应application.properties:
# 主数据源
spring.datasource.primary.url=jdbc:mysql://localhost:3306/db1
spring.datasource.primary.username=root
spring.datasource.primary.password=123456
spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver
# 次数据源
spring.datasource.secondary.url=jdbc:mysql://localhost:3306/db2
spring.datasource.secondary.username=root
spring.datasource.secondary.password=123456
spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver
SpringBoot 2.x默认使用HikariCP连接池,可以这样配置:
# HikariCP配置
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.maximum-pool-size=20
spring.datasource.hikari.minimum-idle=10
spring.datasource.hikari.idle-timeout=600000
spring.datasource.hikari.max-lifetime=1800000
数据源连接池(Connection Pool)是一种用于管理数据库连接的技术,它预先创建并维护一定数量的数据库连接,应用程序可以从连接池中获取连接,使用完毕后归还连接,而不是频繁地创建和关闭连接。这样可以显著提高数据库操作的性能和资源利用率。
在SpringBoot中,常用的连接池实现包括:
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
spring:
datasource:
hikari:
# 连接池名称
pool-name: MyHikariPool
# 最小空闲连接数
minimum-idle: 5
# 最大连接数
maximum-pool-size: 20
# 连接空闲超时时间(毫秒)
idle-timeout: 30000
# 连接最大生命周期(毫秒)
max-lifetime: 1800000
# 连接超时时间(毫秒)
connection-timeout: 30000
# 自动提交
auto-commit: true
spring:
datasource:
tomcat:
initial-size: 5
max-active: 20
min-idle: 5
max-idle: 10
max-wait: 10000
test-on-borrow: true
validation-query: SELECT 1
@Repository
public class UserRepository {
@Autowired
private JdbcTemplate jdbcTemplate;
public List<User> findAll() {
return jdbcTemplate.query(
"SELECT * FROM users",
(rs, rowNum) -> new User(
rs.getLong("id"),
rs.getString("name"),
rs.getString("email")
)
);
}
}
@Configuration
public class DataSourceConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource.hikari")
public DataSource dataSource() {
return DataSourceBuilder.create()
.type(HikariDataSource.class)
.build();
}
}
连接泄漏:
配置不当:
maximum-pool-size
不宜过大,通常建议在CPU核心数的2-3倍minimum-idle
应根据实际负载调整连接验证:
connection-test-query
SELECT 1
多数据源配置:
@Primary
注解标记主数据源监控连接池:
缓存配置是指在 Spring Boot 应用中,通过配置来管理和优化缓存的行为。缓存是一种存储数据的机制,用于减少重复计算或数据库查询的开销,从而提高应用性能。Spring Boot 提供了对多种缓存技术的支持,如 Caffeine、EhCache、Redis 等,并通过简单的配置即可集成这些缓存方案。
Spring Boot 通过 spring.cache
前缀的配置项来管理缓存行为。以下是常见的配置选项:
在 Spring Boot 应用中,首先需要在主类或配置类上添加 @EnableCaching
注解以启用缓存功能。
@SpringBootApplication
@EnableCaching
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
通过 spring.cache.type
指定使用的缓存类型,例如:
spring.cache.type=caffeine
支持的缓存类型包括:
simple
:基于内存的简单缓存(默认)。caffeine
:高性能的本地缓存。ehcache
:功能丰富的本地缓存。redis
:分布式缓存。none
:禁用缓存。对于某些缓存实现(如 Caffeine 或 Redis),可以配置缓存的过期时间。例如:
# Caffeine 缓存配置
spring.cache.caffeine.spec=maximumSize=500,expireAfterWrite=10m
maximumSize
:缓存的最大条目数。expireAfterWrite
:写入后过期时间(例如 10m
表示 10 分钟)。如果使用 Redis 作为缓存,可以配置连接信息:
spring.cache.type=redis
spring.redis.host=localhost
spring.redis.port=6379
spring.cache.redis.time-to-live=30m # 缓存过期时间
spring.cache.redis.key-prefix=myapp: # 缓存键前缀
Spring Boot 提供了一系列注解来管理缓存行为:
@Cacheable
标记方法的返回值需要被缓存。例如:
@Cacheable(value = "users", key = "#id")
public User getUserById(Long id) {
return userRepository.findById(id).orElse(null);
}
value
:缓存名称。key
:缓存的键(支持 SpEL 表达式)。@CacheEvict
标记方法执行后清除缓存。例如:
@CacheEvict(value = "users", key = "#id")
public void deleteUser(Long id) {
userRepository.deleteById(id);
}
@CachePut
更新缓存,通常用于更新操作:
@CachePut(value = "users", key = "#user.id")
public User updateUser(User user) {
return userRepository.save(user);
}
@CacheEvict
或 @CachePut
保证一致性。以下是一个完整的缓存配置示例:
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-cacheartifactId>
dependency>
<dependency>
<groupId>com.github.ben-manes.caffeinegroupId>
<artifactId>caffeineartifactId>
dependency>
application.properties
:spring.cache.type=caffeine
spring.cache.caffeine.spec=maximumSize=1000,expireAfterWrite=30m
@Service
public class UserService {
@Cacheable(value = "users", key = "#id")
public User getUserById(Long id) {
// 模拟数据库查询
return new User(id, "User " + id);
}
@CacheEvict(value = "users", key = "#id")
public void deleteUser(Long id) {
// 模拟删除操作
}
}
模板引擎是一种将动态数据与静态模板结合生成最终内容的工具。在SpringBoot中,常用的模板引擎包括Thymeleaf、Freemarker、Velocity等。它们允许开发者将业务逻辑与页面展示分离,提高代码的可维护性。
Thymeleaf是SpringBoot官方推荐的模板引擎,支持HTML5。
配置示例(application.properties):
# 启用模板缓存(生产环境建议开启)
spring.thymeleaf.cache=true
# 模板文件前缀(默认templates/)
spring.thymeleaf.prefix=classpath:/templates/
# 模板文件后缀(默认.html)
spring.thymeleaf.suffix=.html
# 编码格式
spring.thymeleaf.encoding=UTF-8
# 模板模式(HTML5)
spring.thymeleaf.mode=HTML
Freemarker是另一种流行的模板引擎,语法简洁。
配置示例(application.properties):
# 模板文件后缀(默认.ftlh)
spring.freemarker.suffix=.ftl
# 模板文件前缀(默认templates/)
spring.freemarker.prefix=classpath:/templates/
# 是否启用缓存
spring.freemarker.cache=true
# 编码格式
spring.freemarker.charset=UTF-8
Controller代码:
@Controller
public class GreetingController {
@GetMapping("/greeting")
public String greeting(Model model) {
model.addAttribute("name", "World");
return "greeting"; // 对应templates/greeting.html
}
}
模板文件(greeting.html):
DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Greetingtitle>
head>
<body>
<h1 th:text="'Hello, ' + ${name} + '!'">Hello, World!h1>
body>
html>
模板文件不生效
resources/templates
目录下缓存导致修改不生效
spring.thymeleaf.cache=false
静态资源访问问题
resources/static
目录<link th:href="@{/css/style.css}" rel="stylesheet">
@Bean
public ITemplateResolver templateResolver() {
SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
resolver.setPrefix("classpath:/custom-templates/");
resolver.setSuffix(".html");
resolver.setTemplateMode("HTML5");
resolver.setCharacterEncoding("UTF-8");
return resolver;
}
通过配置多个ViewResolver可以实现:
@Bean
public ViewResolver thymeleafViewResolver() {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine());
resolver.setOrder(1);
return resolver;
}
@Bean
public ViewResolver freemarkerViewResolver() {
FreeMarkerViewResolver resolver = new FreeMarkerViewResolver();
resolver.setPrefix("");
resolver.setSuffix(".ftl");
resolver.setOrder(2);
return resolver;
}
静态资源路径配置是指SpringBoot项目中如何指定和访问静态资源(如HTML、CSS、JavaScript、图片等文件)的规则。SpringBoot默认提供了一套静态资源处理机制,开发者可以通过配置来修改默认行为。
SpringBoot默认会从以下位置查找静态资源(按优先级排序):
classpath:/META-INF/resources/
classpath:/resources/
classpath:/static/
classpath:/public/
# 修改默认静态资源路径
spring.web.resources.static-locations=classpath:/custom-static/,file:/opt/static/
# 修改静态资源访问前缀
spring.mvc.static-path-pattern=/static-content/**
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/my-resources/**")
.addResourceLocations("classpath:/my-static/", "file:/path/to/external/");
}
}
file:
前缀/
或转义的\\
// 同时保留默认路径和添加自定义路径的配置示例
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// 保留默认配置
registry.addResourceHandler("/**")
.addResourceLocations(
"classpath:/META-INF/resources/",
"classpath:/resources/",
"classpath:/static/",
"classpath:/public/"
);
// 添加自定义配置
registry.addResourceHandler("/external/**")
.addResourceLocations("file:/opt/app/static/");
}
}
@ConfigurationProperties
是 Spring Boot 提供的一个核心注解,用于将外部配置文件(如 application.properties
或 application.yml
)中的属性值批量绑定到 Java 对象的字段上。它实现了类型安全的配置管理,避免了直接使用 @Value
注解逐个注入的繁琐操作。
prefix
属性指定配置项的前缀(如 prefix = "app"
会匹配 app.*
的配置)。userName
、user-name
、USER_NAME
可自动映射到同一字段)。int
、List
、Map
等)。@Profile
实现环境隔离。app:
name: "MyApp"
version: 1.0
security:
enabled: true
roles: [ADMIN, USER]
@Configuration
@ConfigurationProperties(prefix = "app")
public class AppConfig {
private String name;
private double version;
private Security security;
// 嵌套静态类
public static class Security {
private boolean enabled;
private List<String> roles;
// Getter/Setter 省略
}
// Getter/Setter 省略
}
app:
servers:
- "192.168.1.1"
- "192.168.1.2"
对应字段:
private List<String> servers;
app:
endpoints:
user: "/api/user"
admin: "/api/admin"
对应字段:
private Map<String, String> endpoints;
@SpringBootApplication
@EnableConfigurationProperties(AppConfig.class)
public class MyApp { ... }
@Component
注解(需确保类在扫描路径内)。@Validated
@ConfigurationProperties(prefix = "app")
public class AppConfig {
@NotBlank
private String name;
@Min(1)
private double version;
}
需添加依赖:
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-validationartifactId>
dependency>
属性未生效:
prefix
是否与配置文件一致Setter
方法类型转换失败:
app.version=1.x
尝试映射到 double
字段会抛出异常IDE 提示支持:
spring-boot-configuration-processor
依赖可生成配置元数据,提供 IDE 自动补全:<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-configuration-processorartifactId>
<optional>trueoptional>
dependency>
与 @Value
对比:
特性 | @ConfigurationProperties |
@Value |
---|---|---|
批量绑定 | 支持 | 需逐个声明 |
松散绑定 | 支持 | 严格匹配 |
SpEL 表达式 | 不支持 | 支持 |
复杂类型(如 List) | 直接支持 | 需手动拆分字符串 |
@Value
是 Spring 框架提供的一个注解,用于将外部配置的值注入到 Spring 管理的 Bean 中。它可以用于字段、方法参数或构造函数参数上,支持从属性文件、环境变量、系统属性等来源获取值。
application.properties
或 application.yml
中读取配置。${user.home}
或 ${JAVA_HOME}
。@Value("${property.name:defaultValue}")
private String fieldName;
${property.name}
:表示从配置文件中读取 property.name
的值。:defaultValue
:可选,表示如果 property.name
不存在,则使用默认值。@Value("Hello, World!")
private String greeting;
假设 application.properties
中有以下配置:
app.name=MyApp
app.version=1.0.0
在代码中使用:
@Value("${app.name}")
private String appName;
@Value("${app.version}")
private String appVersion;
@Value("${user.home}")
private String userHome;
@Value("${JAVA_HOME}")
private String javaHome;
@Value("#{systemProperties['user.home']}")
private String userHomeSpEL;
@Value("#{T(java.lang.Math).random() * 100}")
private double randomNumber;
默认值的使用:
IllegalArgumentException
。@Value("${app.timeout:30}")
private int timeout;
类型匹配:
@Value
会自动尝试将字符串值转换为字段的类型。如果类型不匹配(例如将非数字字符串注入到 int
字段),会抛出异常。动态更新:
@Value
注入的值在应用启动时解析,之后不会动态更新。如果需要动态更新配置,可以使用 @ConfigurationProperties
或 Spring Cloud Config。SpEL 表达式的复杂性:
@Value
中使用过于复杂的 SpEL 表达式,以免降低代码可读性。静态字段:
@Value
不能直接用于静态字段。如果需要注入静态字段,可以通过 setter 方法实现:private static String staticField;
@Value("${static.value}")
public void setStaticField(String value) {
staticField = value;
}
假设 application.properties
中有以下配置:
app.servers=server1,server2,server3
在代码中可以注入为列表或数组:
@Value("${app.servers}")
private List<String> serversList;
@Value("${app.servers}")
private String[] serversArray;
假设 application.properties
中有以下配置:
app.map={key1: 'value1', key2: 'value2'}
在代码中可以注入为 Map:
@Value("#{${app.map}}")
private Map<String, String> map;
@Value
是 SpringBoot 中非常实用的注解,能够方便地将外部配置注入到代码中。合理使用 @Value
可以大大提高配置的灵活性和可维护性。
自定义配置类是指通过 @Configuration
注解标记的 Java 类,用于定义 Spring Boot 应用中的配置信息。这些类可以包含 @Bean
注解的方法,用于向 Spring 容器注册 Bean。自定义配置类通常用于集中管理应用的配置逻辑,替代传统的 XML 配置方式。
@Profile
注解,可以为不同环境(如开发、测试、生产)定义不同的配置。@Conditional
系列注解(如 @ConditionalOnProperty
),根据条件动态注册 Bean。@ConfigurationProperties
,将外部配置(如 application.yml
)绑定到 Java 对象。以下是一个简单的自定义配置类示例:
@Configuration
public class AppConfig {
@Bean
public MyService myService() {
return new MyServiceImpl();
}
@Bean
@Profile("dev")
public DataSource devDataSource() {
// 开发环境数据源配置
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.build();
}
@Bean
@Profile("prod")
public DataSource prodDataSource() {
// 生产环境数据源配置
return DataSourceBuilder.create().build();
}
}
@Bean
:如果可以通过组件扫描(@ComponentScan
)自动注册的 Bean,尽量使用 @Component
注解而非在配置类中显式声明。@DependsOn
或 @Order
注解控制加载顺序。@Bean
方法相互依赖,可能导致循环依赖问题,应通过设计避免。@SpringBootApplication
的关系:主类本身就是一个配置类,通常不需要额外标记 @Configuration
。使用 @Import
导入其他配置类:
@Configuration
@Import({DatabaseConfig.class, SecurityConfig.class})
public class AppConfig {
// 主配置类
}
条件化配置:
@Configuration
@ConditionalOnProperty(name = "feature.enabled", havingValue = "true")
public class FeatureConfig {
@Bean
public FeatureService featureService() {
return new FeatureService();
}
}
配置属性绑定:
@Configuration
@ConfigurationProperties(prefix = "app")
public class AppProperties {
private String name;
private int version;
// getters and setters
}
自定义配置类是 Spring Boot 灵活配置的核心机制之一,合理使用可以大幅提升应用的可维护性和可扩展性。
@Conditional
是 Spring 4.0 引入的核心注解,用于根据特定条件决定是否注册 Bean 或加载配置类。它允许开发者基于环境、属性、类路径等因素动态控制 Spring 应用的配置。
Condition
接口实现条件判断:public interface Condition {
boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}
@Conditional
注解,调用对应的 Condition
实现进行验证。注解 | 作用 |
---|---|
@ConditionalOnBean |
当容器中存在指定 Bean 时生效 |
@ConditionalOnMissingBean |
当容器中不存在指定 Bean 时生效 |
@ConditionalOnClass |
当类路径存在指定类时生效 |
@ConditionalOnMissingClass |
当类路径不存在指定类时生效 |
@ConditionalOnProperty |
当配置属性满足条件时生效 |
@ConditionalOnExpression |
基于 SpEL 表达式判断 |
@ConditionalOnWebApplication |
当是 Web 应用时生效 |
@ConditionalOnNotWebApplication |
当不是 Web 应用时生效 |
@Configuration
@ConditionalOnProperty(
prefix = "app.module",
name = "enabled",
havingValue = "true"
)
public class ModuleAutoConfiguration {
// 当app.module.enabled=true时才会加载
}
public class DatabaseTypeCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
String dbType = context.getEnvironment().getProperty("db.type");
return "mysql".equalsIgnoreCase(dbType);
}
}
@Configuration
@Conditional(DatabaseTypeCondition.class)
public class MySQLAutoConfiguration {
// 仅当db.type=mysql时生效
}
@Configuration
@ConditionalOnClass({ DataSource.class, JdbcTemplate.class })
@ConditionalOnMissingBean(DataSource.class)
public class EmbeddedDatabaseConfig {
// 当类路径存在DataSource和JdbcTemplate
// 且容器中没有DataSource Bean时生效
}
@AutoConfigureAfter
控制顺序@ConditionalOnWebApplication
)而非原始 @Conditional
@ConditionalOn...
元注解spring.autoconfigure.exclude
属性可以显式排除自动配置logging.level.org.springframework.boot.autoconfigure=DEBUG
ConditionEvaluationReport
获取详细评估报告:@Autowired
private ApplicationContext context;
public void printConditions() {
ConditionEvaluationReport report = ConditionEvaluationReport.get(
context.getBeanFactory());
report.getConditionAndOutcomesBySource().forEach((k,v) -> {
System.out.println(k + " => " + v);
});
}
配置属性绑定(Configuration Properties Binding)是 SpringBoot 提供的一种将外部配置文件(如 application.properties
或 application.yml
)中的属性值自动映射到 Java Bean 的机制。通过这种方式,可以方便地将配置信息注入到应用程序中,而无需手动解析配置文件。
@ConfigurationProperties
用于标记一个类,表示该类将绑定配置文件中的属性。可以指定前缀(prefix
)来限定绑定的属性范围。
@EnableConfigurationProperties
通常在配置类上使用,用于启用对 @ConfigurationProperties
注解类的支持。
@RefreshScope
使用)。dev
、test
、prod
)。import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "app")
public class AppConfig {
private String name;
private int version;
private DatabaseConfig database;
// Getters and Setters
// ...
public static class DatabaseConfig {
private String url;
private String username;
private String password;
// Getters and Setters
// ...
}
}
application.yml
)app:
name: "MyApp"
version: 1
database:
url: "jdbc:mysql://localhost:3306/mydb"
username: "root"
password: "secret"
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class AppController {
@Autowired
private AppConfig appConfig;
@GetMapping("/config")
public String getConfig() {
return "App: " + appConfig.getName() + ", Version: " + appConfig.getVersion();
}
}
结合 JSR-303 验证注解(如 @NotNull
、@Size
)对配置属性进行校验:
@ConfigurationProperties(prefix = "app")
@Validated
public class AppConfig {
@NotNull
private String name;
@Min(1)
@Max(10)
private int version;
}
SpringBoot 支持属性名的宽松匹配规则,例如:
app.database-url
可绑定到 Java 字段 databaseUrl
。结合 Spring Cloud 的 @RefreshScope
实现配置动态更新:
@RefreshScope
@ConfigurationProperties(prefix = "app")
public class AppConfig { ... }
属性未绑定
@ConfigurationProperties
的类被 Spring 容器管理(如添加 @Component
)。prefix
是否与配置文件中的前缀一致。类型不匹配
"123"
可绑定到 int
类型,但 "abc"
会导致绑定失败)。嵌套属性
public
的 getter/setter 方法。IDE 提示
spring-boot-configuration-processor
依赖生成配置元数据,实现 IDE 自动补全:<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-configuration-processorartifactId>
<optional>trueoptional>
dependency>
为配置类添加 final
和 @ConstructorBinding
(Spring Boot 2.2+)以实现不可变配置:
@ConfigurationProperties(prefix = "app")
@ConstructorBinding
public class AppConfig {
private final String name;
private final int version;
public AppConfig(String name, int version) {
this.name = name;
this.version = version;
}
}
避免在业务逻辑中直接使用 @Value
,优先使用类型安全的属性绑定。
对敏感信息(如密码)使用 @ConfigurationProperties
结合加密库(如 Jasypt)。
配置属性元数据(Configuration Properties Metadata)是 Spring Boot 提供的一种机制,用于描述和定义应用程序配置属性的结构、类型、默认值、描述信息等元数据。这些元数据通常存储在 META-INF/spring-configuration-metadata.json
或 additional-spring-configuration-metadata.json
文件中,供 IDE(如 IntelliJ IDEA、Eclipse)或其他工具在开发时提供智能提示、自动补全和配置验证。
application.properties
或 application.yml
时,可以检查配置项是否存在或类型是否匹配。配置属性元数据通常包含以下字段:
name
:配置属性的完整名称(如 spring.datasource.url
)。type
:属性的数据类型(如 java.lang.String
、java.lang.Integer
)。description
:属性的描述信息。defaultValue
:属性的默认值。deprecation
:标记属性是否已弃用,以及替代属性。示例元数据文件(additional-spring-configuration-metadata.json
):
{
"properties": [
{
"name": "app.my-service.enabled",
"type": "java.lang.Boolean",
"description": "Whether to enable my custom service.",
"defaultValue": true
},
{
"name": "app.my-service.timeout",
"type": "java.lang.Integer",
"description": "Timeout in milliseconds for the service.",
"defaultValue": 5000
}
]
}
Spring Boot 在编译时会自动为 @ConfigurationProperties
注解的类生成元数据。例如:
@ConfigurationProperties(prefix = "app.my-service")
public class MyServiceProperties {
private boolean enabled = true;
private int timeout = 5000;
// Getters and Setters
}
编译后,Spring Boot 会生成 META-INF/spring-configuration-metadata.json
文件。
如果需要手动补充或覆盖元数据,可以在 src/main/resources/META-INF/
下创建 additional-spring-configuration-metadata.json
文件。Spring Boot 会合并自动生成和手写的元数据。
@ConfigurationProperties
类后,需要重新编译以更新元数据。additional-spring-configuration-metadata.json
的配置会覆盖自动生成的元数据。假设有一个自定义配置类:
@ConfigurationProperties(prefix = "app.mail")
public class MailProperties {
private String host;
private int port;
private String username;
// Getters and Setters
}
生成的元数据可能如下:
{
"properties": [
{
"name": "app.mail.host",
"type": "java.lang.String",
"description": "Mail server host."
},
{
"name": "app.mail.port",
"type": "java.lang.Integer",
"description": "Mail server port."
},
{
"name": "app.mail.username",
"type": "java.lang.String",
"description": "Mail server username."
}
]
}
配置属性处理器是 Spring Boot 中的一个注解处理器(Annotation Processor),主要用于在编译时处理 @ConfigurationProperties
注解。它的核心功能是生成配置属性的元数据(metadata),这些元数据会被 IDE(如 IntelliJ IDEA、Eclipse)或其他工具用于提供配置项的自动补全、类型检查和文档提示。
@ConfigurationProperties
注解的类。META-INF/spring-configuration-metadata.json
文件,包含以下信息:
server.port
)java.lang.Integer
)8080
)@ConfigurationProperties
的 description
字段或 JavaDoc 提供)。application.properties
或 application.yml
中输入配置时,IDE 会根据元数据提供自动补全和类型检查。@Validated
注解,可以在启动时验证配置值的合法性。添加依赖(Maven 示例):
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-configuration-processorartifactId>
<optional>trueoptional>
dependency>
optional=true
表示该依赖仅用于编译时,不会传递到运行时。定义配置类:
@ConfigurationProperties(prefix = "app")
public class AppConfig {
private String name;
private int timeout;
// getters 和 setters
}
编译项目:执行 mvn compile
或 Gradle 等效命令后,会在 target/classes/META-INF
下生成元数据文件。
生成的 spring-configuration-metadata.json
内容示例:
{
"groups": [
{
"name": "app",
"type": "com.example.AppConfig",
"description": "Application configuration properties."
}
],
"properties": [
{
"name": "app.name",
"type": "java.lang.String",
"description": "Name of the application."
},
{
"name": "app.timeout",
"type": "java.lang.Integer",
"defaultValue": 30,
"description": "Timeout in seconds."
}
]
}
@ConfigurationProperties
的 hints
属性可以为枚举类型或特定值提供可选值提示。@Deprecated
注解标记过时属性,或在元数据中设置 deprecated=true
。optional=true
。@ConfigurationProperties
。Build > Compiler > Annotation Processors
中的启用选项)。src/main/resources/META-INF
下创建 additional-spring-configuration-metadata.json
文件,扩展或覆盖自动生成的元数据。Converter
或 GenericConverter
接口,支持复杂类型的属性绑定(如字符串到自定义对象的转换)。配置属性编辑器(PropertyEditor)是 Spring 框架中用于将字符串形式的配置值转换为目标 Java 类型的机制。它主要用于处理配置文件(如 application.properties
或 application.yml
)中的属性值到 Java 对象之间的转换。
@Value
或 @ConfigurationProperties
实现自动类型转换Spring Boot 已内置以下常用属性编辑器:
public class CustomDateEditor extends PropertyEditorSupport {
private final SimpleDateFormat dateFormat;
public CustomDateEditor(String format) {
this.dateFormat = new SimpleDateFormat(format);
}
@Override
public void setAsText(String text) throws IllegalArgumentException {
try {
setValue(dateFormat.parse(text));
} catch (ParseException e) {
throw new IllegalArgumentException("Could not parse date: " + e.getMessage(), e);
}
}
@Override
public String getAsText() {
Date value = (Date) getValue();
return (value != null ? dateFormat.format(value) : "");
}
}
@Configuration
public class EditorConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.registerCustomEditor(Date.class,
new CustomDateEditor("yyyy-MM-dd HH:mm:ss"));
}
}
Converter
或 Formatter
替代对于新项目,建议使用更现代的转换方式:
@Component
public class StringToDateConverter implements Converter<String, Date> {
@Override
public Date convert(String source) {
// 转换逻辑
}
}
配置属性转换器(Converter
)是 SpringBoot 中用于将配置文件中的字符串值转换为目标类型的机制。它属于 Spring 框架的类型转换系统(org.springframework.core.convert
),常用于处理 application.properties
或 application.yml
中的自定义类型转换。
SpringBoot 通过以下接口实现属性转换:
Converter
基础接口,将 S
类型转换为 T
类型。
@FunctionalInterface
public interface Converter<S, T> {
T convert(S source);
}
ConfigurationPropertiesBindingPostProcessor
负责在绑定 @ConfigurationProperties
时调用注册的转换器。
"192.168.1.1:8080"
)转换为自定义对象(如 ServerAddress
)。"yyyy/MM/dd"
)。public class ServerAddress {
private String ip;
private int port;
// 构造方法、Getter/Setter 省略
}
import org.springframework.core.convert.converter.Converter;
public class StringToServerAddressConverter implements Converter<String, ServerAddress> {
@Override
public ServerAddress convert(String source) {
String[] parts = source.split(":");
return new ServerAddress(parts[0], Integer.parseInt(parts[1]));
}
}
方式一:通过 @Configuration
声明
@Configuration
public class ConverterConfig {
@Bean
public Converter<String, ServerAddress> serverAddressConverter() {
return new StringToServerAddressConverter();
}
}
方式二:使用 ConversionService
@Bean
public ConversionService conversionService() {
DefaultConversionService service = new DefaultConversionService();
service.addConverter(new StringToServerAddressConverter());
return service;
}
配置文件(application.yml)
app:
server: "192.168.1.1:8080"
配置类绑定
@ConfigurationProperties(prefix = "app")
public class AppConfig {
private ServerAddress server;
// Getter/Setter
}
convert()
方法中显式处理格式错误(如抛出 IllegalArgumentException
)。@Order
调整顺序。List
),需额外实现 Converter
。通过 Conditional
实现动态注册:
@Bean
@ConditionalOnProperty(name = "app.converter.enabled", havingValue = "true")
public Converter<String, ServerAddress> conditionalConverter() {
return new StringToServerAddressConverter();
}
处理泛型集合类型:
public class StringToListConverter implements Converter<String, List<ServerAddress>> {
@Override
public List<ServerAddress> convert(String source) {
return Arrays.stream(source.split(","))
.map(part -> new ServerAddress(part.split(":")[0],
Integer.parseInt(part.split(":")[1])))
.collect(Collectors.toList());
}
}
配置属性验证器(Configuration Properties Validator)是 Spring Boot 提供的一种机制,用于验证应用程序配置属性(@ConfigurationProperties
注解的类)是否符合预期规则。它通过 JSR-303(Bean Validation)标准注解(如 @NotNull
、@Size
、@Min
等)或自定义验证逻辑,确保配置值在应用启动时满足业务要求。
需引入 spring-boot-starter-validation
:
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-validationartifactId>
dependency>
import org.springframework.boot.context.properties.ConfigurationProperties;
import javax.validation.constraints.*;
@ConfigurationProperties(prefix = "app")
public class AppConfig {
@NotBlank(message = "应用名称不能为空")
private String name;
@Min(value = 1, message = "线程数必须大于0")
private int threadPoolSize;
@Pattern(regexp = "^https?://.*", message = "URL必须以http或https开头")
private String apiUrl;
// Getter/Setter省略
}
在启动类或配置类上添加 @EnableConfigurationProperties
:
@SpringBootApplication
@EnableConfigurationProperties(AppConfig.class)
public class MyApp { ... }
Validator
接口:public class CustomValidator implements Validator {
@Override
public boolean supports(Class<?> clazz) {
return AppConfig.class.isAssignableFrom(clazz);
}
@Override
public void validate(Object target, Errors errors) {
AppConfig config = (AppConfig) target;
if (config.getThreadPoolSize() > 100) {
errors.rejectValue("threadPoolSize", "too.large", "线程数不能超过100");
}
}
}
@Bean
public CustomValidator appConfigValidator() {
return new CustomValidator();
}
通过 @Validated
指定验证组:
public interface AdvancedCheck {}
@ConfigurationProperties(prefix = "app")
@Validated
public class AppConfig {
@NotNull(groups = AdvancedCheck.class)
private String advancedFeature;
}
message
属性自定义。@Valid
:@Valid
private DatabaseConfig database;
apiUrl
可配为 api-url
)。application.yml
示例:
app:
name: "MyApp"
thread-pool-size: 200 # 会触发自定义验证错误
api-url: "invalid-url" # 会触发正则校验错误
启动时错误输出示例:
Binding to target org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'app' to com.example.AppConfig failed:
Property: app.threadPoolSize
Value: 200
Reason: 线程数不能超过100
Property: app.apiUrl
Value: "invalid-url"
Reason: URL必须以http或https开头
配置属性监听器是 SpringBoot 提供的一种机制,用于监听应用程序配置属性(通常来自 application.properties
或 application.yml
)的变化,并在属性值发生改变时触发相应的回调逻辑。这种机制常用于动态调整应用程序行为,而无需重启服务。
SpringBoot 主要通过以下两种方式实现配置监听:
@ConfigurationProperties
+ @RefreshScope
@RefreshScope
@ConfigurationProperties(prefix = "app")
public class AppConfig {
private String title;
private int timeout;
// getters and setters
}
ApplicationListener
@Component
public class MyEnvChangeListener
implements ApplicationListener<EnvironmentChangeEvent> {
@Override
public void onApplicationEvent(EnvironmentChangeEvent event) {
System.out.println("Changed keys: " + event.getKeys());
}
}
@RefreshScope
只对标注的 Bean 生效@Value
注解的属性默认不支持动态更新// 配置类
@RefreshScope
@ConfigurationProperties(prefix = "dynamic")
public class DynamicConfig {
private String featureFlag;
public String getFeatureFlag() {
return this.featureFlag;
}
public void setFeatureFlag(String flag) {
this.featureFlag = flag;
}
}
// 使用类
@Service
public class FeatureService {
@Autowired
private DynamicConfig config;
public boolean isFeatureEnabled() {
return "true".equals(config.getFeatureFlag());
}
}
// 监听器(可选)
@Component
public class ConfigChangeListener {
@EventListener
public void handle(RefreshScopeRefreshedEvent event) {
System.out.println("Configuration refreshed!");
}
}
监听不生效:
spring-boot-starter-actuator
依赖/actuator/refresh
端点部分属性不更新:
@PostConstruct
重新初始化Environment
接口直接获取最新值性能优化:
动态配置刷新(Dynamic Configuration Refresh)是指在应用运行时,无需重启服务即可更新应用配置的能力。Spring Boot 通过 @RefreshScope
和外部配置中心(如 Spring Cloud Config、Nacos、Apollo 等)实现这一功能。
@RefreshScope
注解Scope
机制,配置变更时会销毁并重新创建这些 Bean。spring-cloud-starter-config
等组件监听配置中心的变更事件。/actuator/refresh
端点或配置中心自动推送。
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-configartifactId>
dependency>
# application.yml
management:
endpoints:
web:
exposure:
include: refresh
@RestController
@RefreshScope
public class DemoController {
@Value("${dynamic.message}")
private String message;
@GetMapping("/message")
public String getMessage() {
return message;
}
}
@RefreshScope
Bean 是无状态的。static
)无法动态更新。@ConfigurationProperties
需配合 @RefreshScope
使用。@Component
public class ConfigChangeListener {
@EventListener
public void handleRefresh(RefreshScopeRefreshedEvent event) {
System.out.println("配置已刷新: " + event);
}
}
通过自定义 RefreshEventListener
实现选择性刷新:
@Bean
public RefreshEventListener customRefreshListener() {
return event -> {
if (shouldRefresh(event.getKeys())) {
// 执行刷新逻辑
}
};
}
@RefreshScope
@RefreshScope
Bean 避免相互依赖外部化配置管理是指将应用程序的配置信息(如数据库连接、服务端口、第三方API密钥等)从代码中分离出来,存储在外部文件或环境中。SpringBoot通过多种机制支持外部化配置,使应用程序能够灵活适应不同环境(开发、测试、生产等)。
SpringBoot按以下优先级加载配置(高优先级覆盖低优先级):
--server.port=8081
)SPRING_APPLICATION_JSON
环境变量(内联JSON)java:comp/env
)System.getProperties()
)application-{profile}.properties/yml
(Profile专属)application.properties/yml
(主配置文件)@PropertySource
注解加载的自定义文件SpringApplication.setDefaultProperties
设置)# 基础配置
server.port=8080
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=admin
# 多环境配置
logging.level.root=INFO
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb
username: admin
logging:
level:
root: INFO
通过spring.profiles.active
指定当前环境:
# application-dev.properties
spring.datasource.url=jdbc:mysql://dev-db:3306/mydb
# application-prod.properties
spring.datasource.url=jdbc:mysql://prod-db:3306/mydb
激活方式:
spring.profiles.active=prod
--spring.profiles.active=dev
export SPRING_PROFILES_ACTIVE=test
结合Spring Cloud Config实现动态刷新:
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-configartifactId>
dependency>
@RefreshScope
@RestController
public class MyController {
@Value("${custom.message}")
private String message;
// ...
}
敏感信息保护:
spring.datasource.password=${DB_PASSWORD}
配置组织结构:
spring.redis.*
)myapp:
cache:
timeout: 30s
验证配置:
@ConfigurationProperties
进行类型安全绑定:@ConfigurationProperties(prefix = "mail")
public class MailProperties {
private String host;
private int port;
// getters/setters
}
多文件策略:
application.yml
application-{env}.yml
application-{module}.yml
配置覆盖失效:
YAML缩进错误:
Profile未生效:
application-{profile}.yml
)public class CustomPropertySource implements PropertySource<Map<String, String>> {
// 实现从自定义源加载配置
}
@Configuration
@ConditionalOnProperty(name = "feature.enabled", havingValue = "true")
public class FeatureConfig { ... }
spring.datasource.password={cipher}FKSAJDFGYOS8F7GLHAKERGFHLSAJ
配置中心集成是指将SpringBoot应用的配置文件(如application.properties
或application.yml
)从本地迁移到集中式的配置管理服务中,实现配置的集中管理、动态更新和版本控制。常见的配置中心包括:
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-configartifactId>
<version>2022.0.0.0version>
dependency>
spring:
application:
name: order-service
profiles:
active: dev
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
file-extension: yaml
namespace: dev-namespace
group: DEFAULT_GROUP
@RestController
@RefreshScope // 关键注解
public class ConfigController {
@Value("${custom.config.message}")
private String message;
@GetMapping("/config")
public String getConfig() {
return message;
}
}
典型配置存储路径:
/{application}-{profile}.{file-extension}
示例:order-service-dev.yaml
ApplicationListener
处理配置变更事件特性 | 本地配置 | 配置中心 |
---|---|---|
动态更新 | 需重启 | 实时生效 |
多环境支持 | 需多个文件 | 统一管理 |
配置共享 | 难实现 | 轻松共享 |
版本追溯 | 手动备份 | 自动版本控制 |
配置安全保护是指在 SpringBoot 应用中,通过合理的配置和管理,确保敏感信息(如数据库密码、API 密钥等)不被泄露或滥用。SpringBoot 提供了多种机制来保护配置文件中的敏感数据,包括环境变量、加密配置和权限控制等。
在 application.properties
或 application.yml
中引用环境变量:
# application.properties
spring.datasource.username=${DB_USERNAME}
spring.datasource.password=${DB_PASSWORD}
或
# application.yml
spring:
datasource:
username: ${DB_USERNAME}
password: ${DB_PASSWORD}
在运行应用时设置环境变量:
export DB_USERNAME=admin
export DB_PASSWORD=secret
java -jar your-application.jar
<dependency>
<groupId>com.github.ulisesbocchiogroupId>
<artifactId>jasypt-spring-boot-starterartifactId>
<version>3.0.5version>
dependency>
java -cp jasypt-1.9.3.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI \
input="secret" password=myEncryptionKey algorithm=PBEWithMD5AndDES
# application.properties
spring.datasource.password=ENC(加密后的字符串)
jasypt.encryptor.password=myEncryptionKey
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-configartifactId>
dependency>
bootstrap.properties
:spring.application.name=your-application
spring.cloud.config.uri=http://config-server:8888
spring.cloud.config.username=config-user
spring.cloud.config.password=${CONFIG_SERVER_PASSWORD}
多数据源配置是指在 Spring Boot 应用中同时连接并管理多个数据库实例的能力。通过多数据源配置,应用可以同时操作多个不同的数据库(如 MySQL、PostgreSQL、Oracle 等),或者在同一数据库的不同实例之间切换。
在 pom.xml
中添加数据库驱动依赖(以 MySQL 为例):
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<scope>runtimescope>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-jpaartifactId>
dependency>
在 application.yml
中配置多个数据源:
spring:
datasource:
primary:
jdbc-url: jdbc:mysql://localhost:3306/db1
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
secondary:
jdbc-url: jdbc:mysql://localhost:3306/db2
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
创建配置类,定义多个数据源的 DataSource
Bean:
@Configuration
public class DataSourceConfig {
@Bean
@Primary
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties(prefix = "spring.datasource.secondary")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
}
为每个数据源配置独立的 EntityManagerFactory
和 TransactionManager
(以 JPA 为例):
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
basePackages = "com.example.repository.primary",
entityManagerFactoryRef = "primaryEntityManagerFactory",
transactionManagerRef = "primaryTransactionManager"
)
public class PrimaryDataSourceConfig {
@Primary
@Bean
public LocalContainerEntityManagerFactoryBean primaryEntityManagerFactory(
EntityManagerFactoryBuilder builder,
@Qualifier("primaryDataSource") DataSource dataSource) {
return builder
.dataSource(dataSource)
.packages("com.example.entity.primary")
.persistenceUnit("primary")
.build();
}
@Primary
@Bean
public PlatformTransactionManager primaryTransactionManager(
@Qualifier("primaryEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}
@Primary
注解标记一个主数据源。对于需要运行时动态切换数据源的场景,可以通过抽象路由数据源实现:
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder.getDataSourceType();
}
}
通过线程局部变量(ThreadLocal)保存当前数据源标识:
public class DataSourceContextHolder {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
public static void setDataSourceType(String dataSourceType) {
contextHolder.set(dataSourceType);
}
public static String getDataSourceType() {
return contextHolder.get();
}
public static void clearDataSourceType() {
contextHolder.remove();
}
}
多Redis实例配置是指在SpringBoot应用中同时连接多个Redis服务器或同一个Redis服务器的不同数据库。这种配置常用于以下场景:
spring:
redis:
# 默认实例(通常用于缓存)
host: 127.0.0.1
port: 6379
database: 0
# 自定义第二个实例
redis.secondary:
host: 127.0.0.1
port: 6380
database: 1
@Configuration
public class MultiRedisConfig {
// 主Redis配置
@Bean
@Primary
public RedisConnectionFactory primaryRedisFactory(
@Value("${spring.redis.host}") String host,
@Value("${spring.redis.port}") int port) {
return new LettuceConnectionFactory(host, port);
}
// 次Redis配置
@Bean
public RedisConnectionFactory secondaryRedisFactory(
@Value("${spring.redis.secondary.host}") String host,
@Value("${spring.redis.secondary.port}") int port) {
LettuceConnectionFactory factory = new LettuceConnectionFactory(host, port);
factory.afterPropertiesSet();
return factory;
}
// 主RedisTemplate
@Bean
@Primary
public RedisTemplate<String, Object> primaryRedisTemplate(
RedisConnectionFactory primaryRedisFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(primaryRedisFactory);
// 可在此配置序列化方式等
return template;
}
// 次RedisTemplate
@Bean(name = "secondaryRedisTemplate")
public RedisTemplate<String, Object> secondaryRedisTemplate(
RedisConnectionFactory secondaryRedisFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(secondaryRedisFactory);
return template;
}
}
@Service
public class RedisService {
@Autowired
private RedisTemplate<String, Object> primaryRedisTemplate;
@Autowired
@Qualifier("secondaryRedisTemplate")
private RedisTemplate<String, Object> secondaryRedisTemplate;
public void multiInstanceDemo() {
// 使用主实例
primaryRedisTemplate.opsForValue().set("primaryKey", "value1");
// 使用次实例
secondaryRedisTemplate.opsForValue().set("secondaryKey", "value2");
}
}
spring:
redis:
lettuce:
pool:
max-active: 8
max-idle: 8
min-idle: 0
redis.secondary:
lettuce:
pool:
max-active: 16
max-idle: 16
min-idle: 4
spring:
redis:
sentinel:
master: mymaster
nodes: 127.0.0.1:26379,127.0.0.1:26380
redis.secondary:
sentinel:
master: secondary
nodes: 127.0.0.1:26381,127.0.0.1:26382
@Primary注解:必须为其中一个RedisTemplate标记@Primary,否则Spring无法自动装配
连接泄漏:多实例时更需注意连接的关闭,建议使用try-with-resources
性能影响:每个Redis实例都会创建独立的连接池,需合理配置连接数
事务处理:跨实例的事务无法保证原子性
监控分离:建议为不同实例配置独立的监控
Key命名规范:不同实例使用相同的key可能导致混淆,建议添加前缀
问题1:出现"Consider marking one of the beans as @Primary"错误
解决:确保为其中一个RedisConnectionFactory或RedisTemplate添加@Primary注解
问题2:连接数过高
解决:检查各实例的连接池配置,确保max-active设置合理
问题3:性能下降
解决:考虑使用连接池(如Lettuce或Jedis),并监控各实例性能指标
多消息队列配置是指在 SpringBoot 项目中同时集成并管理多个消息队列(如 RabbitMQ、Kafka、ActiveMQ 等)的能力。通过合理的配置,可以实现不同业务场景下的消息通信需求,提高系统的灵活性和可扩展性。
spring:
rabbitmq:
primary:
host: primary.rabbitmq.example.com
port: 5672
username: admin
password: admin123
secondary:
host: secondary.rabbitmq.example.com
port: 5672
username: admin
password: admin123
配置类示例:
@Configuration
public class MultiRabbitConfig {
@Bean
@Primary
public CachingConnectionFactory primaryConnectionFactory(
@Value("${spring.rabbitmq.primary.host}") String host,
@Value("${spring.rabbitmq.primary.port}") int port,
@Value("${spring.rabbitmq.primary.username}") String username,
@Value("${spring.rabbitmq.primary.password}") String password) {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
connectionFactory.setHost(host);
connectionFactory.setPort(port);
connectionFactory.setUsername(username);
connectionFactory.setPassword(password);
return connectionFactory;
}
@Bean
public CachingConnectionFactory secondaryConnectionFactory(
@Value("${spring.rabbitmq.secondary.host}") String host,
@Value("${spring.rabbitmq.secondary.port}") int port,
@Value("${spring.rabbitmq.secondary.username}") String username,
@Value("${spring.rabbitmq.secondary.password}") String password) {
// 类似primary的配置
}
}
spring:
kafka:
primary:
bootstrap-servers: primary.kafka.example.com:9092
producer:
key-serializer: org.apache.kafka.common.serialization.StringSerializer
value-serializer: org.apache.kafka.common.serialization.StringSerializer
secondary:
bootstrap-servers: secondary.kafka.example.com:9092
producer:
key-serializer: org.apache.kafka.common.serialization.StringSerializer
value-serializer: org.apache.kafka.common.serialization.StringSerializer
配置类示例:
@Configuration
public class MultiKafkaConfig {
@Bean
@Primary
public KafkaTemplate<String, String> primaryKafkaTemplate(
@Value("${spring.kafka.primary.bootstrap-servers}") String bootstrapServers) {
Map<String, Object> configProps = new HashMap<>();
configProps.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
// 其他配置...
return new KafkaTemplate<>(new DefaultKafkaProducerFactory<>(configProps));
}
@Bean
public KafkaTemplate<String, String> secondaryKafkaTemplate(
@Value("${spring.kafka.secondary.bootstrap-servers}") String bootstrapServers) {
// 类似primary的配置
}
}
@Qualifier
注解明确指定要使用的消息队列@Service
public class OrderService {
private final RabbitTemplate primaryRabbitTemplate;
private final RabbitTemplate secondaryRabbitTemplate;
public OrderService(
@Qualifier("primaryRabbitTemplate") RabbitTemplate primaryRabbitTemplate,
@Qualifier("secondaryRabbitTemplate") RabbitTemplate secondaryRabbitTemplate) {
this.primaryRabbitTemplate = primaryRabbitTemplate;
this.secondaryRabbitTemplate = secondaryRabbitTemplate;
}
public void processOrder(Order order) {
// 重要订单使用主队列
if(order.isPriority()) {
primaryRabbitTemplate.convertAndSend("priority.orders", order);
} else {
secondaryRabbitTemplate.convertAndSend("normal.orders", order);
}
}
}
跨域(Cross-Origin Resource Sharing,CORS)是指浏览器出于安全考虑,限制从一个源(协议+域名+端口)加载的资源与另一个源的资源进行交互。例如:
http://localhost:8080
,后端 API 在 http://api.example.com
,此时浏览器会阻止请求。现代 Web 应用通常采用前后端分离架构,前端和后端可能部署在不同域名或端口下。若未配置 CORS,浏览器会拒绝跨域请求,导致前端无法访问后端 API。
通过 WebMvcConfigurer
接口实现全局跨域配置:
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // 匹配所有路径
.allowedOrigins("*") // 允许所有源(生产环境应指定具体域名)
.allowedMethods("GET", "POST", "PUT", "DELETE") // 允许的 HTTP 方法
.allowedHeaders("*") // 允许所有请求头
.allowCredentials(true) // 允许携带 Cookie
.maxAge(3600); // 预检请求缓存时间(秒)
}
}
在单个控制器或方法上使用 @CrossOrigin
注解:
@RestController
@CrossOrigin(origins = "http://example.com") // 允许特定源
public class MyController {
@GetMapping("/data")
@CrossOrigin(origins = "*") // 覆盖类级别配置
public String getData() {
return "Hello CORS!";
}
}
通过自定义过滤器实现跨域:
@Bean
public FilterRegistrationBean<CorsFilter> corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean<CorsFilter> bean =
new FilterRegistrationBean<>(new CorsFilter(source));
bean.setOrder(0); // 设置过滤器优先级
return bean;
}
配置项 | 说明 |
---|---|
allowedOrigins |
允许访问的源(* 表示全部,生产环境建议指定具体域名) |
allowedMethods |
允许的 HTTP 方法(如 GET 、POST ) |
allowedHeaders |
允许的请求头(如 Content-Type 、Authorization ) |
allowCredentials |
是否允许发送 Cookie(设为 true 时,allowedOrigins 不能为 * ) |
maxAge |
预检请求(OPTIONS)的缓存时间,减少重复预检 |
allowCredentials
与 allowedOrigins
冲突
若启用 allowCredentials(true)
,则 allowedOrigins
必须指定具体域名(不能为 *
)。
预检请求(Preflight)
复杂请求(如 Content-Type: application/json
)会先发送 OPTIONS
请求,需确保后端支持。
生产环境安全建议
allowedOrigins("*")
,应明确指定前端域名。allowedMethods
和 allowedHeaders
为最小必要集合。网关层配置
如果使用 Nginx 或 Spring Cloud Gateway,可在网关层统一处理跨域,减少后端压力。
使用 curl
模拟预检请求:
curl -X OPTIONS http://your-api.com/data \
-H "Origin: http://your-frontend.com" \
-H "Access-Control-Request-Method: POST"
检查响应头中是否包含:
Access-Control-Allow-Origin: http://your-frontend.com
Access-Control-Allow-Methods: POST
拦截器(Interceptor)是 Spring MVC 提供的一种机制,允许在请求处理的不同阶段(如请求到达 Controller 前、Controller 方法执行后、视图渲染后等)插入自定义逻辑。拦截器常用于权限验证、日志记录、性能监控等场景。
Spring 的拦截器基于 HandlerInterceptor
接口,该接口定义了三个方法:
preHandle
:在 Controller 方法执行前调用,返回 true
表示继续执行,返回 false
则中断请求。postHandle
:在 Controller 方法执行后、视图渲染前调用。afterCompletion
:在请求完成后调用(视图渲染完毕),通常用于资源清理。以下是完整的拦截器配置步骤:
实现 HandlerInterceptor
接口或继承 HandlerInterceptorAdapter
(Spring 5.3 后已废弃,建议直接实现接口)。
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
public class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
// 权限校验逻辑
if (!checkAuth(request)) {
response.sendError(403, "Forbidden");
return false;
}
return true;
}
private boolean checkAuth(HttpServletRequest request) {
// 实现具体的权限校验
return true;
}
}
通过 WebMvcConfigurer
配置类注册拦截器,并指定拦截路径。
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AuthInterceptor())
.addPathPatterns("/api/**") // 拦截的路径
.excludePathPatterns("/api/login"); // 排除的路径
}
}
可以通过 order()
方法设置多个拦截器的执行顺序,值越小优先级越高。
registry.addInterceptor(new LogInterceptor()).order(1);
registry.addInterceptor(new AuthInterceptor()).order(2);
preHandle
返回值:必须正确处理 true/false
,否则会导致请求中断或循环。/**
匹配所有路径。/api/*
匹配单级路径(如 /api/user
,但不匹配 /api/user/1
)。过滤器(Filter)是 Java Web 应用中的一种组件,用于在请求到达 Servlet 之前或响应返回客户端之前对请求和响应进行预处理或后处理。在 Spring Boot 中,过滤器通常用于实现跨域处理、日志记录、权限验证、请求参数校验等功能。
在 Spring Boot 中,可以通过以下方式配置过滤器:
@Component
和 @WebFilter
注解import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@Component
@WebFilter(urlPatterns = "/*") // 过滤所有请求
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 初始化逻辑
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// 预处理逻辑
System.out.println("Before request processing");
// 继续执行过滤器链
chain.doFilter(request, response);
// 后处理逻辑
System.out.println("After request processing");
}
@Override
public void destroy() {
// 销毁逻辑
}
}
FilterRegistrationBean
注册import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<MyFilter> myFilterRegistration() {
FilterRegistrationBean<MyFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(new MyFilter());
registration.addUrlPatterns("/*"); // 过滤所有请求
registration.setOrder(1); // 设置过滤器执行顺序
return registration;
}
}
FilterRegistrationBean
的 setOrder
方法决定,数值越小优先级越高。doFilter
方法中捕获并处理异常,避免异常传播到上层。destroy
方法中释放过滤器占用的资源(如数据库连接、文件句柄等)。@CrossOrigin
注解)不冲突。import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
public class LoggingFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
System.out.println("Request URL: " + httpRequest.getRequestURL());
System.out.println("Request Method: " + httpRequest.getMethod());
long startTime = System.currentTimeMillis();
chain.doFilter(request, response);
long duration = System.currentTimeMillis() - startTime;
System.out.println("Request processed in " + duration + "ms");
}
// 其他方法(init、destroy)可留空
}
chain.doFilter
:忘记调用 chain.doFilter
会导致请求无法继续处理。定时任务(Scheduled Task)是指在指定的时间或周期性地执行某项任务的功能。在SpringBoot中,可以通过简单的注解和配置实现定时任务的调度。
在启动类上添加@EnableScheduling
注解:
@SpringBootApplication
@EnableScheduling
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
使用@Scheduled
注解标记方法:
@Component
public class MyScheduledTasks {
// 每5秒执行一次
@Scheduled(fixedRate = 5000)
public void taskWithFixedRate() {
System.out.println("Fixed Rate Task: " + System.currentTimeMillis());
}
// 每天凌晨1点执行
@Scheduled(cron = "0 0 1 * * ?")
public void dailyTask() {
System.out.println("Daily Task executed at: " + new Date());
}
}
fixedRate
:固定频率执行,单位毫秒@Scheduled(fixedRate = 5000) // 每5秒执行
fixedDelay
:固定延迟执行(上次任务结束后间隔指定时间)@Scheduled(fixedDelay = 3000) // 上次执行完后3秒再执行
initialDelay
:初始延迟(首次执行的延迟时间)@Scheduled(initialDelay = 1000, fixedRate = 5000)
cron
:Cron表达式(最灵活)@Scheduled(cron = "0 15 10 * * ?") // 每天10:15执行
秒 分 时 日 月 周 年(可选)
常用示例:
0 0 * * * ?
:每小时执行0 0 12 * * ?
:每天中午12点0 15 10 ? * MON-FRI
:工作日10:15执行0 0/5 14,18 * * ?
:每天14点和18点,每隔5分钟执行默认情况下,定时任务使用单线程执行。可以通过配置线程池提高并发能力:
@Configuration
public class SchedulerConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
taskScheduler.setPoolSize(10);
taskScheduler.setThreadNamePrefix("scheduled-task-");
taskScheduler.initialize();
taskRegistrar.setTaskScheduler(taskScheduler);
}
}
?
@Component
public class BestPracticeScheduler {
private static final Logger logger = LoggerFactory.getLogger(BestPracticeScheduler.class);
// 使用线程池+异常处理+分布式锁的完整示例
@Scheduled(cron = "0 0 2 * * ?") // 每天凌晨2点执行
public void dataCleanupTask() {
try {
if (tryAcquireLock("dataCleanup")) {
logger.info("开始执行数据清理任务");
// 实际业务逻辑
logger.info("数据清理任务完成");
}
} catch (Exception e) {
logger.error("数据清理任务执行失败", e);
} finally {
releaseLock("dataCleanup");
}
}
private boolean tryAcquireLock(String lockKey) {
// 实现分布式锁逻辑
return true;
}
private void releaseLock(String lockKey) {
// 释放锁逻辑
}
}
可以通过实现SchedulingConfigurer
接口实现动态配置:
@Configuration
public class DynamicSchedulerConfig implements SchedulingConfigurer {
@Value("${task.interval}")
private long taskInterval;
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.addFixedRateTask(() -> {
System.out.println("Dynamic Task: " + System.currentTimeMillis());
}, taskInterval);
}
}
异步任务是指任务的执行不会阻塞主线程,而是由单独的线程池或线程来执行。在SpringBoot中,我们可以通过简单的配置和注解来实现异步任务的执行。
@EnableAsync
:启用异步支持,需要加在配置类或主类上@Async
:标记方法为异步执行@SpringBootApplication
@EnableAsync
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
@Service
public class MyService {
@Async
public void asyncMethod() {
// 异步执行的逻辑
}
}
SpringBoot允许自定义异步任务使用的线程池:
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(100);
executor.setThreadNamePrefix("Async-");
executor.initialize();
return executor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new SimpleAsyncUncaughtExceptionHandler();
}
}
corePoolSize
:核心线程数maxPoolSize
:最大线程数queueCapacity
:队列容量keepAliveSeconds
:线程空闲时间(秒)threadNamePrefix
:线程名前缀可以通过application.properties配置:
spring.task.execution.pool.core-size=5
spring.task.execution.pool.max-size=10
spring.task.execution.pool.queue-capacity=100
spring.task.execution.thread-name-prefix=Async-
Future
或CompletableFuture
AsyncUncaughtExceptionHandler
处理@Async
public Future<String> asyncMethodWithReturn() {
// 执行逻辑
return new AsyncResult<>("result");
}
// 调用方
Future<String> future = service.asyncMethodWithReturn();
String result = future.get(); // 阻塞获取结果
自定义异常处理器:
public class CustomAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
@Override
public void handleUncaughtException(Throwable ex, Method method, Object... params) {
// 处理异常逻辑
}
}
@Async("specificExecutor")
为不同任务指定不同线程池邮件服务配置是指在 Spring Boot 应用中,通过配置相关参数来集成邮件发送功能。Spring Boot 提供了对 JavaMail 的自动配置支持,开发者可以通过简单的配置快速实现邮件发送功能。
Spring Boot 通过 spring.mail
前缀提供邮件相关配置:
# 邮件服务器地址
spring.mail.host=smtp.example.com
# 邮件服务器端口
spring.mail.port=587
# 协议(默认为smtp)
spring.mail.protocol=smtp
# 用户名
[email protected]
# 密码
spring.mail.password=your-password
# 默认编码
spring.mail.default-encoding=UTF-8
# 其他属性配置
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.connectiontimeout=5000
spring.mail.properties.mail.smtp.timeout=3000
spring.mail.properties.mail.smtp.writetimeout=5000
@Service
public class EmailService {
@Autowired
private JavaMailSender mailSender;
public void sendSimpleEmail(String to, String subject, String text) {
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom("[email protected]");
message.setTo(to);
message.setSubject(subject);
message.setText(text);
mailSender.send(message);
}
}
public void sendHtmlEmail(String to, String subject, String htmlContent) throws MessagingException {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom("[email protected]");
helper.setTo(to);
helper.setSubject(subject);
helper.setText(htmlContent, true); // true表示内容是HTML
mailSender.send(message);
}
public void sendEmailWithAttachment(String to, String subject, String text,
String attachmentPath, String attachmentName)
throws MessagingException {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom("[email protected]");
helper.setTo(to);
helper.setSubject(subject);
helper.setText(text);
FileSystemResource file = new FileSystemResource(new File(attachmentPath));
helper.addAttachment(attachmentName, file);
mailSender.send(message);
}
安全配置:
性能问题:
邮件服务器限制:
测试建议:
国际化:
spring.mail.properties.mail.smtp.connectionpool=true
spring.mail.properties.mail.smtp.connectionpoolsize=5
@Async
public void sendAsyncEmail(String to, String subject, String text) {
sendSimpleEmail(to, subject, text);
}
结合Thymeleaf发送模板邮件:
public void sendTemplateEmail(String to, String subject, Map<String, Object> model)
throws MessagingException {
Context context = new Context();
context.setVariables(model);
String htmlContent = templateEngine.process("email-template", context);
sendHtmlEmail(to, subject, htmlContent);
}
认证失败:
连接超时:
邮件进入垃圾箱:
编码问题:
文件上传配置是指在 SpringBoot 应用中,通过配置文件或代码设置,实现对用户上传文件的支持,包括文件大小限制、存储路径、临时目录等参数的管理。
SpringBoot 通过 Multipart
相关属性控制文件上传行为,主要配置项如下:
# application.properties 示例
spring.servlet.multipart.enabled=true
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=100MB
spring.servlet.multipart.file-size-threshold=1MB
spring.servlet.multipart.location=/tmp
对于更复杂的场景,可通过配置类自定义:
@Configuration
public class UploadConfig implements WebMvcConfigurer {
@Bean
public MultipartConfigElement multipartConfigElement() {
MultipartConfigFactory factory = new MultipartConfigFactory();
factory.setLocation("/custom/tmp");
factory.setMaxFileSize(DataSize.ofMegabytes(50));
factory.setMaxRequestSize(DataSize.ofGigabytes(1));
return factory.createMultipartConfig();
}
}
推荐的最佳实践:
@Value("${file.upload-dir}")
private String uploadDir;
@PostConstruct
public void init() {
try {
Files.createDirectories(Paths.get(uploadDir));
} catch (IOException e) {
throw new RuntimeException("初始化上传目录失败", e);
}
}
错误表现:
org.springframework.web.multipart.MaxUploadSizeExceededException
解决方案:
max-file-size
和 max-request-size
错误表现:
java.io.IOException: The temporary upload location is not valid
解决方案:
spring.servlet.multipart.location
解决方案:
spring.http.encoding.force=true
spring.http.encoding.charset=UTF-8
@RestController
@RequestMapping("/api/files")
public class FileController {
@PostMapping
public String handleUpload(
@RequestParam("file") MultipartFile file,
@RequestParam(required = false) String description) {
if (file.isEmpty()) {
return "文件不能为空";
}
try {
byte[] bytes = file.getBytes();
Path path = Paths.get(uploadDir + file.getOriginalFilename());
Files.write(path, bytes);
return "上传成功: " + path.toString();
} catch (IOException e) {
return "上传失败: " + e.getMessage();
}
}
}
生产环境注意事项:
spring.servlet.multipart.resolve-lazily=false
)云存储集成:
@Bean
public StorageService cloudStorage() {
return new S3StorageService(accessKey, secretKey);
}
安全防护:
@SpringBootTest
@AutoConfigureMockMvc
class FileUploadTests {
@Autowired
private MockMvc mvc;
@Test
void testUpload() throws Exception {
MockMultipartFile file = new MockMultipartFile(
"file",
"test.txt",
"text/plain",
"Hello World".getBytes()
);
mvc.perform(multipart("/upload")
.file(file))
.andExpect(status().isOk());
}
}
安全认证配置是 SpringBoot 应用中用于保护资源访问权限的核心机制,通过验证用户身份(Authentication)和授权(Authorization)确保系统安全性。Spring Security 是 SpringBoot 官方推荐的安全框架,提供开箱即用的认证与授权功能。
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/public/**").permitAll()
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.formLogin(form -> form
.loginPage("/login")
.defaultSuccessUrl("/home")
.permitAll()
)
.logout(logout -> logout
.logoutSuccessUrl("/login?logout")
);
return http.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
/login
页面,可通过formLogin()
自定义:.formLogin(form -> form
.loginProcessingUrl("/auth") // 自定义登录处理URL
.usernameParameter("user") // 修改用户名参数名
.passwordParameter("pass")
)
http.httpBasic(Customizer.withDefaults());
http.oauth2Login(oauth -> oauth
.loginPage("/oauth-login")
.defaultSuccessUrl("/dashboard")
);
@Bean
public UserDetailsService users() {
UserDetails user = User.builder()
.username("user")
.password(passwordEncoder().encode("123"))
.roles("USER")
.build();
return new InMemoryUserDetailsManager(user);
}
UserDetailsService
接口:@Service
public class JpaUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) {
User user = userRepository.findByUsername(username);
return new CustomUserDetails(user); // 自定义UserDetails实现
}
}
@PreAuthorize("hasRole('ADMIN')")
@PostMapping("/delete")
public String deleteData() { /* ... */ }
http.csrf(csrf -> csrf.disable());
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOrigin("https://trusted.com");
config.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return source;
}
PasswordEncoder
,否则报There is no PasswordEncoder mapped
错误。.requestMatchers("/css/**", "/js/**").permitAll()
ROLE_
前缀,数据库角色字段应存储为ADMIN
而非ROLE_ADMIN
。H2 Console
等开发接口国际化(Internationalization,简称 i18n)是指应用程序能够适应不同语言和地区的需求,而无需修改代码。Spring Boot 提供了强大的国际化支持,允许开发者轻松地实现多语言切换。
zh_CN
表示中文-中国)。在 src/main/resources
目录下创建消息资源文件,命名格式为 messages_语言代码_国家代码.properties
:
messages.properties # 默认消息(通常为英文)
messages_zh_CN.properties # 中文-中国
messages_fr_FR.properties # 法语-法国
示例 messages_zh_CN.properties
内容:
welcome.message=欢迎使用我们的应用!
error.notfound=未找到资源
在 application.properties
或 application.yml
中配置:
spring.messages.basename=messages
spring.messages.encoding=UTF-8
@RestController
public class GreetingController {
@Autowired
private MessageSource messageSource;
@GetMapping("/greet")
public String greet(Locale locale) {
return messageSource.getMessage("welcome.message", null, locale);
}
}
<p th:text="#{welcome.message}">p>
资源文件:
greeting=你好,{0}!今天是{1}。
Java 代码:
String[] params = {"张三", "星期一"};
messageSource.getMessage("greeting", params, locale);
可以自定义 Locale 解析器:
@Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver slr = new SessionLocaleResolver();
slr.setDefaultLocale(Locale.US); // 设置默认区域
return slr;
}
@Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
lci.setParamName("lang"); // 通过URL参数切换语言
return lci;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor());
}
然后可以通过 URL 切换语言:http://example.com?lang=zh_CN
user.login.error.invalid_credentials
而非 error1
。通过合理配置和使用 Spring Boot 的国际化功能,可以轻松构建支持多语言的应用程序。
性能监控配置是指在 SpringBoot 应用中,通过集成监控工具或框架,对应用的运行状态、性能指标(如响应时间、吞吐量、内存使用率等)进行实时采集、分析和展示的配置过程。常见的性能监控工具包括 Spring Boot Actuator、Prometheus、Grafana、Micrometer 等。
Spring Boot Actuator 是 Spring Boot 提供的监控工具,可以暴露应用的运行状态和指标。
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
在 application.properties
或 application.yml
中配置:
# 启用所有端点
management.endpoints.web.exposure.include=*
# 启用特定端点(如 health, metrics, info)
management.endpoints.web.exposure.include=health,metrics,info
/actuator/health
:应用健康状态。/actuator/metrics
:性能指标(如 JVM 内存、线程数等)。/actuator/prometheus
:以 Prometheus 格式暴露指标(需额外依赖)。Prometheus 用于采集和存储指标数据,Grafana 用于可视化展示。
<dependency>
<groupId>io.micrometergroupId>
<artifactId>micrometer-registry-prometheusartifactId>
dependency>
management.endpoints.web.exposure.include=prometheus
通过 Micrometer 自定义业务指标(如接口调用次数、耗时等)。
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.stereotype.Component;
@Component
public class CustomMetrics {
private final Counter apiCallCounter;
public CustomMetrics(MeterRegistry registry) {
apiCallCounter = Counter.builder("api.calls.total")
.description("Total number of API calls")
.register(registry);
}
public void incrementApiCall() {
apiCallCounter.increment();
}
}
env
、heapdump
)的访问,可通过 management.endpoints.web.exposure.exclude
排除。scrape_interval
)。management:
endpoints:
web:
exposure:
include: health,metrics,prometheus
metrics:
export:
prometheus:
enabled: true
tags:
application: my-springboot-app # 添加自定义标签
健康检查(Health Check)是 Spring Boot Actuator 提供的一种监控机制,用于检测应用程序的运行状态。它通过暴露一个 HTTP 端点(默认是 /actuator/health
)来展示应用的当前健康状况,包括数据库连接、磁盘空间、外部服务依赖等关键组件的状态。
Spring Boot 默认集成了健康检查功能,但需要引入 spring-boot-starter-actuator
依赖:
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
默认情况下,健康检查端点返回简单的 UP
或 DOWN
状态。可以通过 application.properties
或 application.yml
配置更详细的信息:
# 开启健康检查详细信息(默认仅管理员可见)
management.endpoint.health.show-details=always
Spring Boot 允许通过实现 HealthIndicator
接口自定义健康检查逻辑。例如,检查一个外部 API 是否可用:
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;
@Component
public class CustomHealthIndicator implements HealthIndicator {
@Override
public Health health() {
boolean isApiHealthy = checkExternalApi();
if (isApiHealthy) {
return Health.up().withDetail("message", "External API is healthy").build();
} else {
return Health.down().withDetail("error", "External API is unreachable").build();
}
}
private boolean checkExternalApi() {
// 实现检查逻辑,比如发送 HTTP 请求
return true; // 示例代码,实际需替换为真实逻辑
}
}
Spring Boot 提供了多种内置的健康检查项,例如:
DataSourceHealthIndicator
:检查数据库连接。DiskSpaceHealthIndicator
:检查磁盘空间。RedisHealthIndicator
:检查 Redis 连接。可以通过配置禁用某些检查项:
management.health.db.enabled=false
Kubernetes 探针:
在 Kubernetes 中,可以配置 livenessProbe
和 readinessProbe
指向 /actuator/health
端点,实现容器健康状态管理。
微服务监控:
在微服务架构中,通过健康检查端点聚合所有服务的状态(如使用 Spring Cloud Gateway 或 Prometheus)。
敏感信息暴露:
开启 show-details=always
可能会暴露内部细节,建议在生产环境中结合 Spring Security 限制访问权限。
性能影响:
健康检查的逻辑应尽量轻量,避免频繁调用外部服务或复杂计算。
自定义健康检查的异常处理:
如果自定义 HealthIndicator
抛出异常,端点会返回 DOWN
状态,需确保逻辑健壮性。
如果项目引入了 Spring Security,可以通过以下配置限制健康检查端点的访问:
@Configuration
public class ActuatorSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/actuator/health").permitAll() // 允许所有人访问健康检查
.antMatchers("/actuator/**").hasRole("ADMIN") // 其他端点仅管理员可访问
.and().httpBasic();
}
}
通过合理配置健康检查,可以显著提升应用的可靠性和可维护性。
自定义Starter是SpringBoot提供的一种模块化配置方式,允许开发者将一组相关的依赖、自动配置类和默认属性打包成一个可重用的组件。通过引入该Starter依赖,应用可以快速获得特定功能的支持,而无需手动配置大量Bean。
@Configuration
注解的类,定义需要自动创建的Bean@ConfigurationProperties
的类,支持外部化配置@ConditionalOnClass
等,控制配置的生效条件<project>
<modelVersion>4.0.0modelVersion>
<groupId>com.examplegroupId>
<artifactId>my-spring-boot-starterartifactId>
<version>1.0.0version>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-autoconfigureartifactId>
dependency>
dependencies>
project>
@Configuration
@ConditionalOnClass(MyService.class)
@EnableConfigurationProperties(MyProperties.class)
public class MyAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public MyService myService(MyProperties properties) {
return new MyService(properties);
}
}
@ConfigurationProperties("my.service")
public class MyProperties {
private String prefix = "default";
private boolean enabled = true;
// getters and setters
}
在src/main/resources/META-INF/
下创建spring.factories
文件:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.MyAutoConfiguration
@Bean
@ConditionalOnProperty(name = "my.service.cache.enabled", havingValue = "true")
public CacheManager cacheManager() {
return new SimpleCacheManager();
}
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class MyAutoConfiguration {
// ...
}
<dependency>
<groupId>com.examplegroupId>
<artifactId>my-spring-boot-starterartifactId>
<version>1.0.0version>
dependency>
my.service.prefix=custom
my.service.enabled=true
spring-boot-starter-{name}
的命名约定配置不生效:
spring.factories
文件位置是否正确@Conditional
条件阻止配置加载属性绑定失败:
Bean冲突:
@ConditionalOnMissingBean
避免重复创建@AutoConfigureOrder
调整加载顺序