相較於傳統 .properties 或 INI 格式,XML 提供層級結構、型別擴展性、命名空間與驗證機制,已成為 Tomcat、J2EE 等主流框架的標準配置格式。採用 XML 可實現「配置與代碼分離」,僅修改文件即可適配不同部署環境(開發/測試/生產)。
| 維度 | DOM | SAX |
|---|---|---|
| 解析模式 | 一次性載入整棵樹到記憶體 | 事件驅動,流式逐行解析 |
| 記憶體佔用 | 大文件易 OOM | 常數級,適合大文件 |
| 隨機訪問 | 支援 XPath、樹遍歷 | 單向流,無法回溯 |
| 適用場景 | 小型配置、需頻繁修改回寫 | 大型文件、唯讀解析、效能敏感 |
本文採用 SAX,針對唯讀配置場景實現高效解析。
myenv.xml<?xml version="1.0" encoding="UTF-8"?>
<config>
<dbhost>localhost</dbhost>
<sqlname>mydb</sqlname>
<username>admin</username>
<passWord>secret</passWord>
</config>
部署位置:WEB-INF/classes/myenv.xml(類路徑根目錄)。
ConfigParserimport org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import java.util.Properties;
public class ConfigParser extends DefaultHandler {
private final Properties props = new Properties();
private String currentElement;
private final StringBuffer currentValue = new StringBuffer();
@Override
public void startElement(String uri, String localName, String qName, Attributes attrs) {
currentValue.setLength(0); // 清空緩衝區
currentElement = qName; // 記錄當前元素名
}
@Override
public void characters(char[] ch, int start, int length) {
currentValue.append(ch, start, length); // 累加文本內容
}
@Override
public void endElement(String uri, String localName, String qName) {
props.put(qName.toLowerCase(), currentValue.toString().trim());
}
public Properties getProps() { return props; }
}
ParseXMLimport javax.xml.parsers.*;
import java.net.URL;
import java.util.Properties;
public class ParseXML {
private Properties props;
public Properties getProps() { return props; }
public void parse(String filename) throws Exception {
ConfigParser handler = new ConfigParser();
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(false);
factory.setValidating(false);
SAXParser parser = factory.newSAXParser();
// 從類路徑獲取資源 URL
URL confURL = getClass().getClassLoader().getResource(filename);
if (confURL == null) throw new IllegalArgumentException("找不到配置文件:" + filename);
try {
parser.parse(confURL.toString(), handler);
props = handler.getProps();
} finally {
// 釋放引用協助 GC
factory = null;
parser = null;
handler = null;
}
}
}
ParseXML parser = new ParseXML();
parser.parse("myenv.xml");
Properties cfg = parser.getProps();
System.out.println("DB Host: " + cfg.getProperty("dbhost"));
System.out.println("DB User: " + cfg.getProperty("username"));
factory.setNamespaceAware(true) 並在 startElement 使用 localName。SAXParseException 記錄行號、列號,便於定位配置錯誤。Properties 單例化緩存,避免重複解析。StAX (JSR-173) 或第三方庫(Dom4j、JDOM2、Jackson XML)獲得更友好的 API。