Java 属性配置文件读取方法详解
一、配置文件基础概念
1. 配置文件类型对比
类型 | 格式 | 优点 | 缺点 | 适用场景 |
---|
Properties | key=value | 简单易读,Java原生支持 | 不支持层级结构 | 简单配置,JDBC参数 |
XML | 标签层级结构 | 结构化强,支持复杂数据类型 | 冗余,解析复杂 | 复杂配置,Spring旧版本 |
YAML | 缩进层级结构 | 简洁易读,支持复杂结构 | 依赖缩进,易出错 | Spring Boot,云原生应用 |
JSON | 键值对结构 | 通用性强,语言无关 | 无注释支持 | 前后端共享配置 |
2. 配置文件位置策略
graph TDA[配置文件位置] --> B[类路径 resources/]A --> C[文件系统绝对路径]A --> D[相对项目路径]A --> E[网络位置 URL]A --> F[JVM启动参数指定]
二、Properties 文件读取方法
1. 原生 Java 读取方式
import java.io.InputStream;
import java.util.Properties;public class PropertiesLoader {public static void main(String[] args) {Properties prop = new Properties();try (InputStream input = PropertiesLoader.class.getClassLoader().getResourceAsStream("config.properties")) {if (input == null) {throw new RuntimeException("配置文件未找到");}prop.load(input);String dbUrl = prop.getProperty("database.url");int maxConnections = Integer.parseInt(prop.getProperty("pool.max_connections", "10") );System.out.println("DB URL: " + dbUrl);System.out.println("Max Connections: " + maxConnections);} catch (Exception e) {e.printStackTrace();}}
}
2. 增强型读取工具类
import java.util.Properties;public class ConfigUtils {private static final Properties properties = new Properties();private static boolean loaded = false;static {loadProperties("application.properties");}private static void loadProperties(String fileName) {try (InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName)) {if (is == null) {throw new FileNotFoundException(fileName + " not found");}properties.load(is);loaded = true;} catch (IOException e) {throw new RuntimeException("加载配置文件失败", e);}}public static String getString(String key) {checkLoaded();return properties.getProperty(key);}public static int getInt(String key, int defaultValue) {try {return Integer.parseInt(getString(key));} catch (NumberFormatException e) {return defaultValue;}}public static boolean getBoolean(String key) {return Boolean.parseBoolean(getString(key));}private static void checkLoaded() {if (!loaded) {throw new IllegalStateException("配置文件未加载");}}public static void reload() {properties.clear();loaded = false;loadProperties("application.properties");}
}
三、YAML 文件读取方法
1. SnakeYAML 库读取
<dependency><groupId>org.yaml</groupId><artifactId>snakeyaml</artifactId><version>1.33</version>
</dependency>
import org.yaml.snakeyaml.Yaml;
import java.util.Map;public class YamlLoader {public static void main(String[] args) {Yaml yaml = new Yaml();try (InputStream in = YamlLoader.class.getClassLoader().getResourceAsStream("application.yml")) {Map<String, Object> config = yaml.load(in);Map<String, Object> dbConfig = (Map<String, Object>) config.get("database");String url = (String) dbConfig.get("url");List<String> servers = (List<String>) config.get("servers");System.out.println("DB URL: " + url);System.out.println("Servers: " + servers);} catch (Exception e) {e.printStackTrace();}}
}
2. 绑定到 Java 对象
public class AppConfig {private Database database;private List<String> servers;private Security security;public static class Database {private String url;private String username;private String password;private int maxConnections;}public static class Security {private boolean enabled;private String token;}
}
public class YamlToObject {public static void main(String[] args) {Yaml yaml = new Yaml(new Constructor(AppConfig.class));try (InputStream in = YamlToObject.class.getClassLoader().getResourceAsStream("application.yml")) {AppConfig config = yaml.load(in);System.out.println("DB User: " + config.getDatabase().getUsername());} catch (Exception e) {e.printStackTrace();}}
}
四、Spring Boot 配置读取最佳实践
1. 基础配置绑定
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;@Component
public class DatabaseConfig {@Value("${database.url}")private String url;@Value("${database.username}")private String username;@Value("${database.password}")private String password;@Value("${pool.max_connections:20}") private int maxConnections;public void initDataSource() {System.out.println("Connecting to: " + url);}
}
2. 类型安全配置绑定
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;@Component
@ConfigurationProperties(prefix = "app")
public class AppProperties {private Database database;private List<String> servers;private Security security;public static class Database {private String url;private String username;private String password;private int maxConnections;}public static class Security {private boolean enabled;private String token;}
}
app:database:url: jdbc:mysql://localhost/dbusername: rootpassword: secretmax_connections: 50servers:- server1.example.com- server2.example.comsecurity:enabled: truetoken: abc123xyz
3. 多环境配置管理
src/main/resources/
├── application.yml # 公共配置
├── application-dev.yml # 开发环境
├── application-test.yml # 测试环境
└── application-prod.yml # 生产环境
启动参数指定环境:
java -jar myapp.jar --spring.profiles.active=prod
五、高级配置技巧
1. 动态刷新配置
import org.springframework.cloud.context.config.annotation.RefreshScope;@RefreshScope
@Component
public class DynamicConfig {@Value("${dynamic.property}")private String dynamicValue;public String getConfig() {return dynamicValue;}
}
通过 /actuator/refresh
端点刷新配置(需要 Spring Cloud)
2. 加密敏感配置
import org.jasypt.encryption.StringEncryptor;
import org.springframework.beans.factory.annotation.Autowired;public class SecureConfig {@Autowiredprivate StringEncryptor encryptor;@Value("${encrypted.property}")private String encryptedProperty;public String getDecryptedValue() {return encryptor.decrypt(encryptedProperty);}
}
3. 自定义配置源
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.PropertySource;@Configuration
public class CustomPropertySourceConfig {@Beanpublic PropertySource<?> customPropertySource() {Map<String, Object> properties = new HashMap<>();properties.put("custom.property", "value-from-db");return new MapPropertySource("customSource", properties);}
}
六、配置读取安全最佳实践
1. 敏感信息处理
风险 | 解决方案 | 实现方式 |
---|
密码明文存储 | 使用加密配置 | Jasypt, Spring Cloud Config 加密 |
配置文件泄露 | 配置文件与代码分离 | 外部化配置(K8s ConfigMap, Vault) |
生产配置误用 | 环境隔离 | Spring Profiles, 独立配置文件 |
2. 配置审计策略
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;@Component
public class ConfigAuditor {private final Environment env;public ConfigAuditor(Environment env) {this.env = env;}@EventListener(ApplicationReadyEvent.class)public void auditConfiguration() {System.out.println("=== 配置审计报告 ===");System.out.println("Active Profiles: " + Arrays.toString(env.getActiveProfiles()));System.out.println("DB URL: " + env.getProperty("spring.datasource.url"));System.out.println("Security Enabled: " + env.getProperty("app.security.enabled"));}
}
七、性能优化方案
1. 配置读取优化策略
场景 | 优化方案 | 效果 |
---|
高频访问配置 | 缓存配置值 | 减少重复解析 |
大型配置文件 | 按需加载 | 减少启动内存占用 |
分布式配置 | 客户端缓存+版本校验 | 减少网络请求 |
敏感配置 | 延迟解密 | 启动时不暴露敏感信息 |
2. 高效配置缓存实现
public class ConfigCache {private static final Map<String, Object> cache = new ConcurrentHashMap<>();private static final Properties properties = new Properties();static {try (InputStream is = ConfigCache.class.getResourceAsStream("/application.properties")) {properties.load(is);} catch (IOException e) {throw new RuntimeException("配置加载失败", e);}}public static Object getProperty(String key) {return cache.computeIfAbsent(key, k -> {Object value = properties.get(k);if (value instanceof String) {}return value;});}public static void refresh() {cache.clear();}
}
八、配置读取完整流程示例
九、总结:配置读取最佳实践
1. 技术选型指南
场景 | 推荐方案 |
---|
简单Java应用 | Properties + 工具类 |
Spring Boot应用 | @ConfigurationProperties |
复杂配置结构 | YAML + 配置类 |
微服务/云原生 | Spring Cloud Config |
高安全要求 | HashiCorp Vault |
2. 配置管理黄金法则
- 环境隔离:严格区分dev/test/prod环境配置
- 安全第一:绝不将敏感信息提交到代码仓库
- 外部化配置:配置文件与应用程序分离
- 版本控制:所有配置文件纳入版本管理
- 配置监控:实时监控配置变更和生效状态
- 默认安全:设置安全相关的默认值
- 文档化:维护配置项说明文档
3. 配置读取检查清单
架构师建议:在现代应用架构中,配置管理已从简单的文件读取发展为独立的基础设施。对于关键业务系统,建议采用专业的配置中心(如Spring Cloud Config、Apollo、Nacos),实现配置的集中管理、版本控制、实时推送和审计跟踪,将配置读取提升到新的专业水平。