什么是 Properties 文件?
properties 文件是一种简单的、基于文本的配置文件,通常用于存储应用程序的配置信息,例如数据库连接信息、API密钥、开关设置等。

它的特点是:
- 键值对存储:格式为
key = value或key:value。 - 注释:使用 或 开头表示单行注释。
- 编码:通常使用 ISO-8859-1 编码,但可以存储 Unicode 字符(通过
\uXXXX转义)。
示例:config.properties
# Database Configuration db.url=jdbc:mysql://localhost:3306/mydb db.username=admin db.password=secret123 db.pool.size=10 # Application Settings app.name=My Awesome App app.version=1.2.0 feature.new.enabled=true
使用 java.util.Properties 类(最传统、最经典)
这是最基础、最核心的方法,适用于所有 Java 版本,它通过 InputStream 读取文件内容。
关键步骤:
- 创建一个
Properties对象。 - 使用
ClassLoader获取文件的InputStream。这是最推荐的方式,因为它能确保从类路径(src/main/resources)中正确加载文件,无论是在开发环境还是打包后的 JAR/WAR 文件中。 - 调用
load(InputStream)方法将输入流中的内容加载到Properties对象中。 - 使用
getProperty(String key)或getProperty(String key, String defaultValue)方法获取值。
完整代码示例:
项目结构:

src/
└── main/
├── java/
│ └── com/
│ └── example/
│ └── PropertiesReader.java
└── resources/
└── config.properties
PropertiesReader.java
package com.example;
import java.io.InputStream;
import java.util.Properties;
public class PropertiesReader {
public static void main(String[] args) {
// 1. 创建 Properties 对象
Properties props = new Properties();
// try-with-resources 语句可以自动关闭流,避免资源泄漏
try (InputStream input = PropertiesReader.class.getClassLoader().getResourceAsStream("config.properties")) {
// 2. 检查文件是否存在
if (input == null) {
System.out.println("Sorry, unable to find config.properties");
return;
}
// 3. 加载 properties 文件内容
props.load(input);
// 4. 读取并打印配置项
System.out.println("Database URL: " + props.getProperty("db.url"));
System.out.println("Database User: " + props.getProperty("db.username"));
System.out.println("App Name: " + props.getProperty("app.name"));
System.out.println("App Version: " + props.getProperty("app.version"));
// 5. 获取属性,如果不存在则返回默认值
String featureFlag = props.getProperty("feature.new.enabled", "false");
System.out.println("New Feature Enabled: " + featureFlag);
// 获取一个不存在的属性,会返回 null
String nonExistent = props.getProperty("non.existent.key");
System.out.println("Non-existent Key: " + nonExistent);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
为什么使用 getClassLoader().getResourceAsStream()?
- 路径是相对于类根目录的:对于 Maven/Gradle 项目,
src/main/resources目录下的文件在编译后会直接进入类路径的根目录。 - 环境无关性:无论你的代码是在 IDE 中运行,还是被打包成 JAR 文件运行,这种方式都能正确找到文件,如果你使用
new FileInputStream("config.properties"),路径是相对于当前工作目录的,这在 JAR 包运行时很容易出错。
使用 java.util.ResourceBundle 类(国际化友好)
ResourceBundle 专门用于本地化,但它也可以非常方便地读取 properties 文件,它不直接处理文件流,而是通过文件名来加载。
关键步骤:
properties文件必须遵循特定的命名规则:basename_<locale>.properties,config_en_US.properties,默认的(不带语言环境的)文件是config.properties。- 使用
ResourceBundle.getBundle("basename")来加载,JVM 会根据默认的Locale自动寻找最匹配的文件。 - 使用
getString(String key)获取字符串值。
完整代码示例:
假设你的 config.properties 文件在 src/main/resources 下。

ResourceBundleReader.java
package com.example;
import java.util.ResourceBundle;
public class ResourceBundleReader {
public static void main(String[] args) {
// "config" 是文件名,不包含 .properties 后缀
// ResourceBundle 会自动从类路径中查找 config.properties
ResourceBundle rb = ResourceBundle.getBundle("config");
System.out.println("App Name from ResourceBundle: " + rb.getString("app.name"));
System.out.println("Database URL from ResourceBundle: " + rb.getString("db.url"));
// 如果键不存在,会抛出 MissingResourceException
// System.out.println(rb.getString("non.existent.key"));
}
}
优点:
- 简洁,无需处理流和异常。
- 为国际化(i18n)提供了完美的支持。
缺点:
- 只能读取字符串值,对于
Integer,Boolean等类型,需要手动转换。 - 文件命名规则严格。
使用 Spring Framework 的 @Value 注解(在 Spring/Spring Boot 环境中)
如果你的项目是基于 Spring 或 Spring Boot 的,这是最优雅、最推荐的方式,它允许你直接将 properties 文件中的值注入到字段中。
步骤:
- 确保你的
properties文件位于src/main/resources目录下。 - 在 Spring Boot 项目中,默认会加载
application.properties或application.yml,你也可以自定义文件名。 - 使用
@Value("${key:default_value}")注解来注入属性。
完整代码示例:
application.properties
myapp.name=Spring Boot App myapp.message=Hello from Spring! feature.flag=true
SpringPropertiesService.java
package com.example;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
@Service // 声明为 Spring 服务组件
public class SpringPropertiesService {
// 从 application.properties 中读取 myapp.name,如果不存在则使用 "Default App"
@Value("${myapp.name:Default App}")
private String appName;
// 读取一个字符串
@Value("${myapp.message}")
private String message;
// 读取一个布尔值,Spring 会自动转换
@Value("${feature.flag:false}")
private boolean featureEnabled;
// 读取一个数字,Spring 会自动转换
@Value("${db.pool.size:10}")
private int poolSize;
public void printProperties() {
System.out.println("App Name: " + appName);
System.out.println("Message: " + message);
System.out.println("Feature Enabled: " + featureEnabled);
System.out.println("Pool Size: " + poolSize);
}
}
如何运行(需要 Spring 环境) 你需要一个 Spring Boot 应用来启动这个服务。
总结与最佳实践
| 方法 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
java.util.Properties |
通用、任何 Java 项目 | 核心基础,灵活,可读取任何值(需转换) | 需要手动处理流和异常,代码稍显冗长 |
java.util.ResourceBundle |
需要国际化支持的项目 | 代码简洁,自动处理本地化 | 只能读字符串,文件命名有要求 |
@Value (Spring) |
Spring / Spring Boot 项目 | 最优雅,与框架深度集成,自动类型转换 | 仅限 Spring 环境 |
如何选择?
-
如果你在一个普通的 Java SE 项目中(没有使用 Spring 框架):
- 首选
java.util.Properties,这是最可靠、最标准的方式。 - 如果你的应用有多个语言版本,并且需要根据用户语言切换配置,可以考虑
ResourceBundle。
- 首选
-
如果你在一个 Spring 或 Spring Boot 项目中:
- 毫不犹豫地使用
@Value注解,它能让你在代码中直接使用配置值,非常直观和方便,Spring Boot 还支持@ConfigurationProperties来将一组相关的属性绑定到一个类型安全的配置类中,这是更进阶的做法。
- 毫不犹豫地使用
-
文件路径的最佳实践:
- 始终将
properties文件放在src/main/resources目录下。 - 始终使用
ClassLoader.getResourceAsStream()或ResourceBundle来加载,确保路径的正确性。避免使用绝对路径或相对于项目根目录的相对路径。
- 始终将
