Skip to content

配置管理

LCGYL Framework 提供灵活强大的配置管理功能,支持多种配置源和格式。

版本说明

本文档基于 LCGYL Framework 2.1 版本,包含 YAML 配置、Profile 支持、@ConfigurationProperties 类型安全绑定等新特性。

配置文件

application.properties

默认的配置文件格式。

properties
# 应用配置
app.name=MyApp
app.version=1.0.0
app.description=我的应用

# 服务器配置
server.port=8080
server.host=localhost

# 数据库配置
datasource.url=jdbc:mysql://localhost:3306/mydb
datasource.username=root
datasource.password=secret
datasource.pool.size=10

# 日志配置
logging.level.root=INFO
logging.level.com.example=DEBUG

application.yaml 2.1+

原生支持 YAML 格式配置文件,无需额外依赖。

yaml
app:
  name: MyApp
  version: 1.0.0
  description: 我的应用

server:
  port: 8080
  host: localhost

datasource:
  url: jdbc:mysql://localhost:3306/mydb
  username: root
  password: secret
  pool:
    size: 10

logging:
  level:
    root: INFO
    com.example: DEBUG

读取配置

使用 @Value 注解

最简单的方式,直接注入配置值。

java
@Component
public class AppConfig {
    
    @Value("app.name")
    private String appName;
    
    @Value("app.version")
    private String version;
    
    @Value("server.port")
    private int port;
    
    // Getters
    public String getAppName() {
        return appName;
    }
}

默认值

使用 : 指定默认值。

java
@Component
public class ServerConfig {
    
    @Value("server.port:8080")
    private int port;  // 如果未配置,默认 8080
    
    @Value("server.host:localhost")
    private String host;  // 如果未配置,默认 localhost
}

类型转换

框架自动进行类型转换。

java
@Component
public class Config {
    
    @Value("server.port")
    private int port;  // String → int
    
    @Value("feature.enabled")
    private boolean enabled;  // String → boolean
    
    @Value("timeout.seconds")
    private long timeout;  // String → long
    
    @Value("rate.limit")
    private double rateLimit;  // String → double
}

集合类型

支持列表和数组。

properties
# application.properties
# 逗号分隔
allowed.hosts=localhost,127.0.0.1,example.com
admin.emails=admin@example.com,support@example.com
yaml
# application.yaml
allowed:
  hosts:
    - localhost
    - 127.0.0.1
    - example.com

admin:
  emails:
    - admin@example.com
    - support@example.com
yaml
# application.yaml
allowed:
  hosts:
    - localhost
    - 127.0.0.1
    - example.com

admin:
  emails:
    - admin@example.com
    - support@example.com
java
@Component
public class SecurityConfig {
    
    @Value("allowed.hosts")
    private List<String> allowedHosts;
    
    @Value("admin.emails")
    private String[] adminEmails;
}

配置类 2.1+

@ConfigurationProperties

将配置绑定到 POJO 类,提供类型安全的配置访问。

properties
# application.properties
database.url=jdbc:mysql://localhost:3306/mydb
database.username=root
database.password=secret
database.pool.minSize=5
database.pool.maxSize=20
database.pool.timeout=30000
yaml
# application.yaml
database:
  url: jdbc:mysql://localhost:3306/mydb
  username: root
  password: secret
  pool:
    minSize: 5
    maxSize: 20
    timeout: 30000
java
@Component
@ConfigurationProperties(prefix = "database")
public class DatabaseConfig {
    
    private String url;
    private String username;
    private String password;
    private PoolConfig pool;
    
    // Getters and Setters
    
    public static class PoolConfig {
        private int minSize;
        private int maxSize;
        private long timeout;
        
        // Getters and Setters
    }
}

使用配置类

java
@Component
public class DatabaseService {
    
    @Inject
    private DatabaseConfig config;
    
    public void connect() {
        String url = config.getUrl();
        String username = config.getUsername();
        int poolSize = config.getPool().getMaxSize();
        
        // 使用配置创建连接
    }
}

环境配置 2.1+

多环境配置文件

resources/
├── application.properties          # 通用配置
├── application-dev.properties      # 开发环境
├── application-test.properties     # 测试环境
└── application-prod.properties     # 生产环境

激活环境

properties
# application.properties
# 激活开发环境
app.profiles.active=dev

或通过命令行:

bash
java -jar myapp.jar --app.profiles.active=prod

环境特定配置

properties
# application-dev.properties
server.port=8080
datasource.url=jdbc:mysql://localhost:3306/mydb_dev
logging.level.root=DEBUG

# application-prod.properties
server.port=80
datasource.url=jdbc:mysql://prod-db:3306/mydb
logging.level.root=WARN
yaml
# application-dev.yaml
server:
  port: 8080
datasource:
  url: jdbc:mysql://localhost:3306/mydb_dev
logging:
  level:
    root: DEBUG

# application-prod.yaml
server:
  port: 80
datasource:
  url: jdbc:mysql://prod-db:3306/mydb
logging:
  level:
    root: WARN
yaml
# application-dev.yaml
server:
  port: 8080
datasource:
  url: jdbc:mysql://localhost:3306/mydb_dev
logging:
  level:
    root: DEBUG

# application-prod.yaml
server:
  port: 80
datasource:
  url: jdbc:mysql://prod-db:3306/mydb
logging:
  level:
    root: WARN
java
@Component
public class SecurityConfig {
    
    @Value("server.port")
    private int port;
    
    @Value("datasource.url")
    private String datasourceUrl;
    
    @Value("logging.level.root")
    private String loggingLevel;
}

配置优先级

配置源按以下优先级加载(从高到低):

  1. 命令行参数
  2. 系统属性
  3. 环境变量
  4. application-{profile}.properties
  5. application.properties
  6. 默认值
bash
# 命令行参数优先级最高
java -jar myapp.jar --server.port=9090

动态配置

配置刷新

java
@Component
public class ConfigRefreshService {
    
    @Inject
    private ConfigurationManager configManager;
    
    public void refresh() {
        // 重新加载配置
        configManager.refresh();
    }
}

配置监听

监听配置变化。

java
@Component
public class ConfigChangeListener {
    
    @OnConfigChange("server.port")
    public void onPortChange(String oldValue, String newValue) {
        System.out.println("端口从 " + oldValue + " 变更为 " + newValue);
    }
}

加密配置

加密敏感信息

properties
# 使用 ENC() 包裹加密值
datasource.password=ENC(encrypted_password_here)
api.key=ENC(encrypted_api_key_here)
yaml
# application.yaml
datasource:
  password: ENC(encrypted_password_here)
api:
  key: ENC(encrypted_api_key_here)

配置加密器

java
@Component
public class ConfigEncryptor {
    
    private static final String ALGORITHM = "AES";
    private static final String SECRET_KEY = "your-secret-key";
    
    public String encrypt(String value) {
        // 加密实现
    }
    
    public String decrypt(String encryptedValue) {
        // 解密实现
    }
}

配置验证

使用验证注解

java
@Component
@ConfigurationProperties(prefix = "server")
public class ServerConfig {
    
    @NotNull
    @Min(1024)
    @Max(65535)
    private Integer port;
    
    @NotBlank
    private String host;
    
    @Email
    private String adminEmail;
    
    // Getters and Setters
}

自定义验证

java
@Component
@ConfigurationProperties(prefix = "database")
public class DatabaseConfig {
    
    private String url;
    private String username;
    private String password;
    
    @PostConstruct
    public void validate() {
        if (url == null || url.isEmpty()) {
            throw new ConfigurationException("数据库 URL 不能为空");
        }
        
        if (!url.startsWith("jdbc:")) {
            throw new ConfigurationException("无效的数据库 URL");
        }
    }
}

外部配置

从外部文件加载

java
Application app = Application.builder()
    .configLocation("file:/etc/myapp/config.properties")
    .run(args);

从多个位置加载

java
Application app = Application.builder()
    .configLocations(
        "classpath:application.properties",
        "file:/etc/myapp/config.properties",
        "file:${user.home}/.myapp/config.properties"
    )
    .run(args);

配置占位符

引用其他配置

properties
app.name=MyApp
app.version=1.0.0
app.fullName=${app.name} v${app.version}

# 结果:MyApp v1.0.0

系统属性

properties
# 引用系统属性
user.home=${user.home}
java.version=${java.version}

# 引用环境变量
database.host=${DB_HOST:localhost}

条件配置

基于配置的条件

java
@Component
@ConditionalOnProperty(name = "cache.enabled", havingValue = "true")
public class CacheService {
    // 只在 cache.enabled=true 时创建
}

基于环境的条件

java
@Component
@Profile("dev")
public class DevDatabaseConfig {
    // 只在 dev 环境创建
}

@Component
@Profile("prod")
public class ProdDatabaseConfig {
    // 只在 prod 环境创建
}

最佳实践

1. 使用配置类而不是 @Value

java
// ✅ 推荐:使用配置类
@Component
@ConfigurationProperties(prefix = "database")
public class DatabaseConfig {
    private String url;
    private String username;
    // ...
}

// ❌ 不推荐:到处使用 @Value
@Component
public class ServiceA {
    @Value("database.url")
    private String url;
}

@Component
public class ServiceB {
    @Value("database.url")
    private String url;
}

2. 提供默认值

java
@Value("server.port:8080")
private int port;

@Value("cache.ttl:3600")
private long cacheTtl;

3. 验证配置

java
@PostConstruct
public void validate() {
    if (port < 1024 || port > 65535) {
        throw new ConfigurationException("无效的端口号: " + port);
    }
}

4. 不要硬编码配置

java
// ❌ 不推荐
public class Service {
    private static final String API_URL = "https://api.example.com";
}

// ✅ 推荐
@Component
public class Service {
    @Value("api.url")
    private String apiUrl;
}

5. 敏感信息加密

properties
# ❌ 不推荐:明文密码
database.password=secret123

# ✅ 推荐:加密密码
database.password=ENC(encrypted_value)

6. 使用类型安全的配置

java
// ✅ 推荐:强类型
@ConfigurationProperties(prefix = "server")
public class ServerConfig {
    private int port;  // 编译时类型检查
}

// ❌ 不推荐:字符串类型
@Value("server.port")
private String port;  // 需要手动转换

常见问题

Q: 配置文件放在哪里?

A:

  • 开发时:src/main/resources/application.properties
  • 打包后:JAR 包内的 application.properties
  • 外部配置:/etc/myapp/config.properties${user.home}/.myapp/config.properties

Q: 如何覆盖配置?

A: 使用命令行参数或环境变量。

bash
# 命令行
java -jar myapp.jar --server.port=9090

# 环境变量
export SERVER_PORT=9090
java -jar myapp.jar

Q: 配置值为空怎么办?

A: 提供默认值或进行验证。

java
@Value("optional.config:")
private String config;  // 空字符串

@Value("optional.config:default")
private String config;  // 默认值

下一步

Released under the Apache License 2.0