首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java 讀取 .properties 配置文件的多種實用方法詳解

     編輯:Java 綜合教學

前言

在 Java 開發中,.properties 配置文件因其簡潔易讀、適合存儲鍵值對配置,被廣泛應用於項目中。本文將系統梳理讀取屬性文件的幾種主流方式,並通過代碼示例幫助你快速掌握核心用法。

一、基於 java.util.Properties 類(JDK 原生方案)

Properties 繼承自 Hashtable,實現了 Map 接口。雖然可用 put/putAll,但官方建議使用 setProperty/getProperty 確保鍵值均為字符串類型。持久化時使用 store()(save() 已棄用)。加載配置文件提供兩種 load 重載:

  • load(InputStream inStream)
  • load(Reader reader)

1. 獲取 InputStream 的五種常見途徑

// 1. 通過當前類的類加載器(推薦用於 classpath 下資源)
InputStream in = TestProperties.class.getClassLoader().getResourceAsStream("test.properties");

// 2. 直接從文件系統讀取
InputStream in = new FileInputStream(new File("filePath"));

// 3. 通過系統類加載器
InputStream in = ClassLoader.getSystemResourceAsStream("filePath");

// 4. Servlet 環境下通過 ServletContext 獲取
InputStream in = context.getResourceAsStream("filePath");

// 5. 通過 URL 打開流
URL url = new URL("path");
InputStream in = url.openStream();

2. 讀取並獲取屬性值

Properties prop = new Properties();
prop.load(inStream);
String username = prop.getProperty("username"); // 推薦
// String username = (String) prop.get("username"); // 不推薦,返回 Object 需強轉

二、基於 java.util.ResourceBundle 類(更簡便的資源綁定)

ResourceBundle 專為國際化設計,讀取 .properties 時無需加後綴名,自動按 Locale 匹配。主要有兩種用法:

1. 靜態工廠方法 getBundle()

// 文件位於包 com.mmq 下,名為 test.properties
ResourceBundle bundle = ResourceBundle.getBundle("com/mmq/test");
String username = bundle.getString("username");

2. 從 InputStream 構建 PropertyResourceBundle

InputStream in = ...; // 獲取流的方式同上
ResourceBundle bundle = new PropertyResourceBundle(in);

路徑注意事項:
- 文件在包下:Properties 用 com/mmq/test.properties,ResourceBundle 用 com/mmq/test
- 文件在 src 根目錄:直接用 test.properties 或 test

三、實戰封裝:可緩存、多模塊的配置加載工具類

下面展示一個生產級的封裝示例,包含單例加載器、併發緩存工具類及常量定義,支援外部配置路徑覆蓋。

1. ResourceLoader.java —— 單例加載器,支援緩存與外部路徑

package com.bijian.study;

import java.io.File;
import java.io.FileInputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

public final class ResourceLoader {
    private static final ResourceLoader INSTANCE = new ResourceLoader();
    private static final Map<String, Properties> CACHE = new HashMap<>();

    private ResourceLoader() {}

    public static ResourceLoader getInstance() {
        return INSTANCE;
    }

    public Properties getPropFromProperties(String fileName) throws Exception {
        // 1. 優先從緩存獲取
        Properties cached = CACHE.get(fileName);
        if (cached != null) return cached;

        // 2. 確定文件路徑:優先讀取 JVM 參數 configurePath,否則從 classpath 獲取
        String filePath;
        String configPath = System.getProperty("configurePath");
        if (configPath == null) {
            filePath = this.getClass().getClassLoader().getResource(fileName).getPath();
        } else {
            filePath = configPath + "/" + fileName;
        }

        // 3. 加載並緩存
        Properties prop = new Properties();
        prop.load(new FileInputStream(new File(filePath)));
        CACHE.put(fileName, prop);
        return prop;
    }
}

2. PropertiesUtil.java —— 併發安全的鍵值緩存訪問層

package com.bijian.study;

import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

public class PropertiesUtil {
    private static final ResourceLoader LOADER = ResourceLoader.getInstance();
    private static final ConcurrentMap<String, String> CONFIG_CACHE = new ConcurrentHashMap<>();
    private static final String DEFAULT_FILE = "test.properties";

    public static String getStringByKey(String key, String propName) {
        try {
            Properties prop = LOADER.getPropFromProperties(propName);
            key = key.trim();
            // 雙重檢查鎖定模式避免重複解析
            return CONFIG_CACHE.computeIfAbsent(key, k -> prop.getProperty(k));
        } catch (Exception e) {
            throw new RuntimeException("加載配置失敗: " + propName, e);
        }
    }

    public static String getStringByKey(String key) {
        return getStringByKey(key, DEFAULT_FILE);
    }

    public static Properties getProperties() {
        try {
            return LOADER.getPropFromProperties(DEFAULT_FILE);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

3. Constant.java / Main.java —— 靜態常量引用與測試入口

// Constant.java
package com.bijian.study;
public class Constant {
    public static final String TEST = PropertiesUtil.getStringByKey("test", "test.properties");
}

// Main.java
package com.bijian.study;
public class Main {
    public static void main(String[] args) {
        System.out.println(Constant.TEST);
    }
}

總結與最佳實踐建議

  • 簡單場景:直接用 Properties.load() 或 ResourceBundle.getBundle() 即可。
  • 生產環境:建議封裝緩存層(如上例),避免重複 I/O;併發場景下使用 ConcurrentHashMap 保證線程安全。
  • 路徑管理:通過 JVM 參數 -DconfigurePath=/external/config 實現配置文件外部化,便於部署變更。
  • 編碼問題:Properties.load(InputStream) 默認 ISO-8859-1,若含中文請改用 load(Reader) 配合 InputStreamReader(stream, "UTF-8")。

掌握這幾種方式,靈活選擇,即可輕鬆應對各類配置讀取需求。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved