在NodeJS中使用配置文件,有幾種比較不錯的方案:
第一種:文件格式使用json是毋容置疑的好方案。格式標準,易於理解,文件內容讀取到內存以後,使用JSON的標準分析函數便可獲得配置項。
第二種:將配置文件作成模塊。其內容格式徹底能夠整合成一個object,而後將其導出。在NodeJS中require引入後,能夠直接訪問配置項。
第三種:使用Ini格式或者類XML的配置文件。這樣的配置文件後臺開發司空見慣,格式清晰,也不失是一種比較好的方法。
因爲最近一個項目須要在NodeJS中讀取分析後臺生成的類XML配置文件,因此湊週末時間寫了一個簡單層級配置文件的解析類。封裝後發佈到npmjs,供有須要的同窗一塊兒使用。01.簡單層級配置文件格式
//定義主配置文件
<main>
<log>
filepath = /data/app/logs
filename = svrrequest.log
</log>
//定義可用的服務端IP地址
<server>
<ipinfo>
host = 192.168.10.58
port = 28000
</ipinfo>
<ipinfo>
host = 192.168.25.26
port = 14000
</ipinfo>
</server>
</main>
//定義MySQL數據庫訪問用戶和密碼
<mysql>
user = admin
password = admin@*123456%
</mysql>
//定義告警接收人郵件地址
email = motadou@126.com
02.使用方法 首先使用npm安裝該配置文件解析模塊:
npm install mo-configure
獲取配置項的語法以下:
//第一步,引入配置文件解析類
var configure = require("mo-configure");
//第二步,建立一個配置文件解析類
var config = new configure();
//第三步,指定配置文件路徑,或者傳入配置文件的內容
//好比:
//config.parseText('<main>email=motadou@126.com</main>')
//config.get("main.email");
config.parseFile("main.conf");
//例子一: configure to json
//json爲內置屬性,該屬性將配置文件內容轉換成了JSON格式的數據
console.log(config.json);
//例子二:有兩種方法獲取指定的配置項
//第一種直接訪問內部的JSON結構,但這種方法有時會拋出異常,請注意捕捉
console.log(config.json.email);
console.log(config.json.main.log.filename);
//第二種調用配置類的get函數,該函數當找不到配置項時,容許返回一個指定的默認值
console.log(config.get("email", "not define email"))
console.log(config.get("main.log.filename"));
//例子三:返回一個JSON對象
var ipinfo = config.get("main.server.ipinfo");
console.log(ipinfo);
03.配置文件類的實現 源代碼以及後續更新請參考Github項目:
https://github.com/motadou/mo-configure.git
主要實現代碼原理以下:
var fs = require("fs");
var configure = function () {
this._data = { };
this.__defineGetter__("json", function () { return this._data; });
}
configure.prototype.parseText = function (sText) {
var arr = sText.split(/\r\n|\r|\n/); //行劃分
var stack = [this._data];
for(var i = 0, len = arr.length; i < len; i++) {
var line = arr[i].replace(/^[\s\t ]+|[\s\t ]+$/g, '');
if (line.length == 0 || line[0] == "#") {
continue;
}
//當前行爲當前域下面的值
if (line[0] != "<") {
var options = line.split("=");
var key = options[0].replace(/^[\s\t ]+|[\s\t ]+$/g, '');
var value = options.length == 2?options[1].replace(/^[\s\t ]+|[\s\t ]+$/g, ''):undefined;
stack[stack.length - 1][key] = value;
continue;
}
//當前行爲域的標識
if (line[line.length - 1] != '>') {
//域標識符有開頭但沒有結尾,則分析錯誤
this.data = {};
return false;
}
//當前行爲域的結束
if (line[1] == "/") {
stack.pop();
continue;
}
//當前行爲域的開始
var key = line.substring(1, line.length - 1);
var parent = stack[stack.length - 1];
if (parent.hasOwnProperty(key)) {
//在當前域中已經有相同名字的域
if (parent[key] instanceof Array) {
parent[key].push({});
} else {
parent[key] = [parent[key], {}];
}
stack.push(parent[key][parent[key].length - 1]);
} else {
parent[key] = {};
stack.push(parent[key]);
}
}
}
configure.prototype.parseFile = function (sFilePath, encoding) {
var data = fs.readFileSync(sFilePath, encoding?encoding:"utf8");
this.parseText(data);
}
configure.prototype.toJson = function() {
return this._data;
}
configure.prototype.get = function (key, DEFAULT_VALUE) {
key = key.replace(/[\s\t ]+/g, '');
key = key.replace(/\.{2,}/g, '.');
var paths = key.split('.');
var parent = this._data;
for (var i = 0, len = paths.length; i < len; i++) {
if (!parent.hasOwnProperty(paths[i])){
return DEFAULT_VALUE;
}
if (i == len - 1) {
return parent[paths[i]];
}
parent = parent[paths[i]];
}
}
module.exports = configure;