nodejs简单层级结构配置文件
在NodeJS中使用配置文件,有几种比较不错的方案:
第一种:文件格式使用json是毋容置疑的好方案。格式标准,易于理解,文件内容读取到内存之后,使用JSON的标准分析函数即可得到配置项。
第二种:将配置文件做成模块。其内容格式完全可以整合成一个object,然后将其导出。在NodeJS中require引入后,可以直接访问配置项。
第三种:使用Ini格式或者类XML的配置文件。这样的配置文件后台开发司空见惯,格式清晰,也不失是一种比较好的方法。
由于最近一个项目需要在NodeJS中读取分析后台生成的类XML配置文件,所以凑周末时间写了一个简单层级配置文件的解析类。封装后发布到npmjs,供有需要的同学一起使用。01.简单层级配置文件格式
主要实现代码原理如下:
第一种:文件格式使用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.com02.使用方法 首先使用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;