###node_song mvc 框架介绍(基于nodejs+express+ejs+mongoose+controller.js) controller.js:简化路由匹配的工具文件,解析controllers目录下所有~.js文件,对~.js文件内容中的路由url和url对应的action方法进行匹配
###(一)目录介绍(-表示文件夹 ~表示文件 *二级目录)
-项目名
-controllers(action文件夹)
* ~t1Controller.js(controllers文件夹下文件,文件名自定义,主要用来写各种action)
* ~t2Controller.js(controllers文件夹下文件,主要用来写各种action)
-models(对象模型文件夹)
-views(文件夹)
* ~test.html
-public(公共文件夹)
* --css(文件夹)
* --js(文件夹)
* --images(文件夹)
-util(工具文件夹)
* ~controller.js(本文主要讲解的重要文件:用于简化路由匹配)
-logs(日志文件夹)
~app.js(程序入口)
~appserver.js(系统初始化文件)
~configjs(配置文件)
~database.js(数据库连接文件) ~logger.js(日志打印工具)
-----(二)主要文件介绍----
(1)app.js 文件代码
/**[@filename](/user/filename) app.js
* [@author](/user/author) song
* [@classDescription](/user/classDescription) 程序入口
* [@version](/user/version) 0.1.0
*/
var config = require('./config'),
appserver = require('./appserver.js'),
log = require('./logger.js'),
tsweb = appserver.app;
var fs = require("fs");
process.on("uncaughtException", function(err){
//console.warn('ERROR: -- [' + (new Date).toUTCString() + ' ] Caught unhandled exception:');
//console.warn('ERROR: -- [' + (new Date).toUTCString() + ' ] 未处理错误事件:'+(err.stack || err));
log.logger.error('-- [' + (new Date).toUTCString() + ' ] Caught unhandled exception:' + (err.stack || err));
//log.logger.error('-- [' + (new Date).toUTCString() + ' ] 未处理错误事件:'+(err.stack || err));
//正式版关闭以下行,防止程序异常中止
//process.exit();
});
process.on('exit',function(){
//console.error('SYSTEM -- [' + (new Date).toUTCString() + ' ] system exit, Good bye!');
log.logger.info('SYSTEM -- [' + (new Date).toUTCString() + ' ] system exit, Good bye!');
});
process.on('SIGINT',function(){
//console.log('SYSTEM -- [' + (new Date).toUTCString() + ' ] system is killed, and now exit !');
log.logger.info('SYSTEM -- [' + (new Date).toUTCString() + ' ] system is killed, and now exit !');
process.exit();
});
tsweb.listen(config.serverPort);
(2)appserver.js 代码
/**
*[@filename](/user/filename) appserver.js
* [@author](/user/author) songbo
* [@classDescription](/user/classDescription) 系统初始化
* [@version](/user/version) 0.1.0
*/
var express = require('express'),
logger = require('./logger'),
connect = require('connect'),
MemoryStore = connect.session.MemoryStore,
controller = require("./util/controller"),
ejs = require('ejs'),
config = require('./config');
var app_version = "0.0.1";
var app = exports.app = express.createServer();
app.configure(function(){
//app.set('views', __dirname + '/views');
//app.set('view engine' , 'jade');
app.set('view engine' , 'html');
app.register("html", ejs);
app.set('view options', {layout: false});
app.use(connect.favicon(__dirname+ '/public/favicon.ico'));
app.use(express.logger({ format : ":method :url"}));
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({ store: new MemoryStore({ reapInterval: 60 * 1000, maxAge: 15 * 600000 * 1000 }), secret: 'ection' }));
//app.use(express.session({key: 'sid',cookie: { secure: 'true', maxAge:86400000 }}))
app.use(express.methodOverride());
app.use(express.static(__dirname + '/public'));
app.use(express.static(__dirname + '/views'));
//使用controller.js的bootControllers方法进行路由匹配
controller.bootControllers(app);
console.log("node_song mvc version " + app_version + " now running on port " + config.serverPort);
});
(3)config.js 代码
/**
*[@filename](/user/filename) appserver.js
* [@author](/user/author) song
* [@classDescription](/user/classDescription) 配置文件
* [@version](/user/version) 0.1.0
*/
module.exports={
title : 'node_song--nodejs mvc框架',
serverPort : 8001,//监听端口
webTitle : ' ',//web页面title
/******* mongodbl*****相关配置*******/
mongodb : 'mongodb://127.0.0.1/Songdb',
/*******mysql*****相关配置*******/
mysqlHost : '127.0.0.1',
mysqlPort : 3306,
mysqlDb : 'SongDb',
mysqlUser : 'song',
mysqlPass : 'song',
};
(4)database.js 代码
/**
*[@filename](/user/filename) database.js
* [@author](/user/author) song
* [@classDescription](/user/classDescription) 数据库连接
* [@version](/user/version) 0.1.0
*/
var util = require('util'),
config = require('./config'),
mysql = require('mysql'),
mongoose = require('mongoose'),
Schema = mongoose.Schema,
ObjectId = Schema.ObjectId;
mongoose.connect(config.mongodb);
/*********这里也可写连接mysql的代码*****/
(4)logger.js 代码
/**
*[@filename](/user/filename) logger.js
* [@author](/user/author) songbo
* [@classDescription](/user/classDescription) 日志工具
* [@version](/user/version) 0.1.0
*/
var winston = require('winston');
require('./util/DateFormat.js');
var logger = exports.logger = new winston.Logger({
transports : [
new winston.transports.Console(),
new winston.transports.File({filename : 'logs/node_song' + new Date().format('yyyy-MM-dd') + '.log'})
]
});
###(三)util目录下controller.js介绍(本文重点文件–路由解析工具文件)
controller.js 代码
/**
*[@filename](/user/filename) controller.js
* [@author](/user/author) song
* [@classDescription](/user/classDescription) 路由解析
* [@version](/user/version) 0.1.0
*/
var fs = require("fs");
var mappingString = "";
function add_to_mapping_string(method, url, description, auth) {
mappingString += "<div style='width: 400px; height: 20px; padding: 5px; background-color: " +
"#ccc; color: #000; font-family: Arial, Verdana, sans-serif'><b>"
+ method + " " + url + "</b></div><div style='width: 400px; padding: 5px; background-color: " +
"#eee; color: #000; font-family: Arial, Verdana, sans-serif'>"
+ description + "<br /><b>Auth:</b> " + auth + "</div><br />";
}
//解析controllers目录下所有.js文件
function bootController(app, file) {
var name = file.replace('.js', '');
var actions = require('../controllers/' + name);
var mapping = actions["mapping"];
Object.keys(actions).map(function(action){
var fn = actions[action];
if(typeof(fn) === "function") {
if(a = mapping[action]) {
add_to_mapping_string(a.method, a.url, a.description, a.auth);
switch(a.method) {
case 'get':
app.get(a.url, fn);
console.log("get " + a.url);
break;
case 'post':
app.post(a.url, fn);
console.log("post " + a.url);
break;
case 'put':
app.put(a.url, fn);
console.log("put " + a.url);
break;
case 'delete':
app.del(a.url, fn);
console.log("delete " + a.url);
break;
}
} else {
console.log("WARNING: no mapping for " + action + " defined");
}
}
});
}
module.exports = {
bootControllers : function(app) {
fs.readdir(__dirname + '/../controllers', function(err, files){
if (err) throw err;
files.forEach(function(file){
console.log("booting controller " + file);
if(file != '.svn')
bootController(app, file);
else
console.log("Not booting .svn controller! " );
});
//可查看所有接口的url:/show_available_interfaces
app.get("/show_available_interfaces", function(req, res){
res.send(mappingString);
});
//404页面
app.get('*', function(req, res) {
console.log('404 handler..') ;
console.log(req.url);
res.send('Page Not Found!(404)');
});
});
}
};
##(四)model的写法(User数据模型对象,使用第三方模块mongoose)
/**
* [@classDescription](/user/classDescription) User数据模型对象
* [@author](/user/author) song
* [@version](/user/version) 0.1.0
*/
var mongoose = require('mongoose'),
Schema = mongoose.Schema,
ObjectId = Schema.ObjectId;
var UserSchema = new Schema({
loginName : {type:String,required: true,index:true},
realName : String,
password : String,
phone : String,
email : String,
});
mongoose.model("User",UserSchema);
var User = exports.User = mongoose.model('User');
var UserDao = exports.UserDao = {
/**
* 删除所有数据
*/
delAllData:function(cb){
User.remove({}, function(err){
cb(err);
});
},
/**
* 增加默认数据
*/
addDefaultData:function(cb){
var m = new User();
m.loginName = 'admin';
m.realName = '系统管理员';
m.password = tools.md5('admin');
m.phone = '10086';
m.email = 'test[@163](/user/163).com';
m.save();
},
};
//增加默认用户admin
User.find(function(err,user){
if(err){
console.log('无法查询用户数据:'+err);
//process.exit();
}else{
if (user.length == 0) {
UserDao.addDefaultData();
}
}
});
###(四)自定义controller的写法–t1Controller.js介绍(controllers目录下) (1)在controllers目录下新建js文件,名称无要求 (2)例如楼主写的t1Controller.js代码(hello world例子和一个操作users表mongo数据库的例子)
/**
* [@classDescription](/user/classDescription) t1Controller.js
* [@author](/user/author) song
* [@version](/user/version) 0.1.0
*/
var config = require('../config'),
log = require('../logger.js'),
db = require('../database.js');
var userModel = require('../models/userModel.js');
module.exports = {
mapping: {
"Hello": {
"url": "/test",//访问的url,楼主监听的是8001端口,所以访问路径为localhost:8001/test
"method": "get",
"description": "简单的hello world例子",
"auth": false
},
"TestUser": {
"url": "/testUser",
"method": "get",
"description": "操作User表",
"auth": false
},
},
/**
* testUser
* [@param](/user/param) req
* [@param](/user/param) res
*/
Hello: function(req, res){
console.log("Hello world!!" );
res.render('./test.html', {
locals: {
title: config.title,
text: "hello world"
}
});
},
/**
* hello world
* [@param](/user/param) req
* [@param](/user/param) res
*/
// GET 方法
TestUser: function(req, res){
console.log("TestUser!!" );
var loginName="admin";
//
userModel.User.findOne({loginName: loginName,}, function(err, results){
var text="";
if (results) {
console.log("find admin!!" );
// log的使用方法,写入日志
log.logger.info('find admin success!');
text="find admin success";
}else {
console.log("not found!!" );
text="not found";
};
res.render('./test.html', {
locals: {
title: config.title,
text: text
}
});
});
},
}
views文件夹下新建test.htlm文件,body标签内写入代码<%=text%> 调用text对象进行显示 启动mongo后 node app 启动项目后 访问路径localhost:8001/test 访问路径localhost:8001/testUser
###本文旨在交流,转载请指明出处…
同样借地方说一下我的小demo http://kmanjs.com 使用 koa.js + MongoDB(mongoose) + Angular.js + Node.js 做的一个小框架. 也是自动根据route的文件位置进行加载. 同时支持使用koa-resource-router添加RESTful风格的API