express 4.0 相对3.0 将很多非必要的插件都抽离开,如cookie、session等,需要我们自己去安装插件再使用 例如: cookieParser = require(‘cookie-parser’); app.use(cookieParser());
mongoose是基于mongodb开发出来一个数据库工具,它使用scheme、model、entity三个概念来具象化mongoose,并封装了mongodb的一些函数,使得我们操作数据库更方便快捷
在查询数据库情况时使用了robmongo这个可视化工具,不用再在终端敲代码查看情况,节省了很多时间
首先,项目的目录如下: -model –user.js -module –setting.js -routes -account.js -views –info.jade –login.jade –reg.jade -node_modules server.js package.json
model 存放mongoose定义的collection对象和方法, module为自己定义的一些模块, routes则是路由(将路由分块管理有利于后期的维护), views则是模板使用的文件所在文件夹
定好项目的基本目录后,写一个基本的服务器,设置好服务器渲染时候的模板引擎类型、路径、静态资源路径、路由功能以及监听定好的端口:
/* Module dependence */ var express = require(‘express’) , path = require(‘path’) // 第三方中间件 , connect = require(‘connect’) // 第三方中间件 , cookieParser = require(‘cookie-parser’) // cookie解析中间件 , account_r = require(’./routes/account’) // 用户登录、注册、退出路由 ;
/* Create server */ var app = express();
/* Set options */ app.set(‘view engine’, ‘jade’); // 模板引擎 app.set(‘views’, __dirname + ‘/views’); // 模板引用路径 // console.log(‘app_views:’, app.set(‘views’));
app.enable(‘trust proxy’); // 查看源IP地址使用
/**
- Use cookie */ app.use(cookieParser());
/* Route */
// 用户登陆、注册、退出 app.use(’/user’, account_r);
// 为静态文件添加路径 app.use(’/static’, express.static(‘public’));
/* Listen at port and host */ var port = 3080; var server = app.listen(port, function(){ var host = server.address().address; var port = server.address().port; console.log(‘App listening at http://%s:%s’, host, port); });
启动服务器:node server.js 就能看到终端已经在监听服务器,但如果在浏览器端输入localhost:3080,会出现cannot get /的情况,因为路由还没有定义好,接下来我们来定义路由文件’routes/accout.js’和数据库文件’model/user.js’ user.js:
/**
- 数据库定义 */
/**
- 模块依赖
- @type {module} */ var express = require(‘express’) , mongoose = require(‘mongoose’) ;
var Schema = mongoose.Schema; // 数据库地址,newexpress 为数据库名称 url = ‘mongodb://127.0.0.1:27017/newexpress’ /* Exports and Create Server */ var connect = mongoose.connect(url);
// 定义对象模型 var UserScheme = new Schema({ real_name: {type: String, default: ‘匿名’}, password: {type: String, default: ‘123’}, mail: {type: String, default: ‘’}, birth: {type: Date, default: Date.now}
});
// 访问user对象 // (注意)NOTE: methods must be added to the schema before compiling it with mongoose.model() UserScheme.methods.speak = function() { var greeting = this.real_name ? 'My name is ’ + this.real_name : ‘I don’t have a name…’; console.log(greeting); }
mongoose.model(‘User’, UserScheme); var User = mongoose.model(‘User’);
// 暴露connect接口 exports.connect = function(callback) { console.log(‘user_db connect’); // mongoose.connect(url); return connect; } exports.disconnect = function(callback) { console.log(‘user_db disconnect!’); mongoose.disconnect(callback); }
exports.setup = function(callback) { callback(null); }
exports.add = function(user, callback) { var new_user = new User(); new_user.real_name = user.real_name; new_user.password = user.password; new_user.mail = user.mail; new_user.birth = user.birth;
new_user.save(function(err) {
if (err) {
callback(err);
} else {
callback(null);
}
});
}
exports.delete = function(id, callback) { exports.findUserById(id, function(err, doc) { if (err) { callback(err); } else { doc.remove(); callback(null); } }); }
exports.editMs = function(id, key, val, callback) { exports.findUserById(id, function(err, doc) { if (err) { callback(err); } else { doc.key = val; doc.save(function(err) { if (err) { callback(err); } else { callback(null); } }) } }); }
exports.allToUser = function(callback) { User.find({}, callback); }
exports.forAll = function(doEach, done) { User.find({}, function(err, docs) { if (err) { done(err,null); } docs.forEach(function(doc) { doEach(null, doc); }); done(null); }); }
exports.findUser = function(user, done) { console.log(‘findUser:’, user); User.find(user, function(err, doc) { if (err) { console.log(‘findUser: is err’); done(err, null); } else { console.log(‘findUser: no err’); done(null, doc); } }) }
var findUserById = exports.findUserById = function(id, callback) { User.findOne({_id: id}, function(err, doc) { if (err) { callback(err, null); } callback(null, doc); }); }
然后定义accout.js:
/* Module require */ var express = require(‘express’) , bodyParser = require(‘body-parser’) , multer = require(‘multer’) , user_db = require(’./…/model/user.js’) ;
/* Exports and Create Server */ var app = module.exports = express();
var upload = multer();// for parsing multipart/form-data
/**
- Use middler 第三方中间件 */ app.use(bodyParser.json()); // for parsing application/json app.use(bodyParser.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded
/**
- Middleware */
/**
-
打印请求信息
-
@param {http} req 请求
-
@param {http} res 响应
-
@param {func} next 继续下一个请求
-
@return {}
*/ var logRequestMs = function (req, res, next) {console.log(’============================== 请求信息 =====================================================’); console.log(‘请求地址:’, req.path); // 打印ip地址,获取ip地址列表 console.log(‘远程ip地址为:’, req.ip); // 当trust proxy为true,解析X-Forwarded-For获取ip地址列表,否则值为空数组。 console.log(‘远程ips地址为:’, req.ip); console.log(‘请求的cookie:’, req.cookies); // 打印当前时间 var now = new Date(); console.log(‘请求时间:’, now.getYear() - 100 + ‘年’ + (now.getMonth() + 1) + ‘月’ + now.getHours() + ‘时’ + now.getMinutes() + ‘分’ + now.getSeconds() + ‘秒’);
console.log(’================================结束请求信息===================================================’); next(); };
var listAll = function (fn) { user_db.allToUser(function(err, doc) { if (err) { console.log(‘err’); } else { console.log(‘ok’); doc.forEach(function(doc) { console.log(’_id:’, doc._id) console.log('real_name ', doc.real_name); console.log('password ', doc.password); console.log('birth ', doc.birth); console.log('mail ', doc.mail); }) } }); }
/**
- 设置cookie
- @param {http} res 响应
- @param {string} name cookie名称
- @param {string or obj} val cookie值
- @param {int} expire 持续时间 */ var setCookie = function (res, name, val, expire) { var days = expire * 24 * 60 * 60; res.cookie(name, val, { expires: new Date(Date.now() + days), // signed: true // signed 设置后报错 }); }
/**
- 删除cookie
- @param {http} res res
- @param {string} name cookie name
- @return {}
*/ var delCookie = function (res, name) { res.clearCookie(name); }
/**
- 获取cookie
- @param {[type]} err [description]
- @param {[type]} req [description]
- @param {[type]} name [description]
- @return {[type]} [description] */ var getCookie = function (req, key) { // if (req.signedCookie[name]) { // return req.signedCookie[name]; // } // else { // return null; // } if (typeof req.cookies[key] !== ‘undefined’) { return req.cookies[key]; } return undefined; }
/**
- 使用应用级中间件 */ app.use(logRequestMs);
/**
- Router 使用路由级中间件 */
// 注册页面 app.get(’/reg’, function(req, res) { res.render(‘reg’, {title: ‘注册’}); });
// 注册请求 app.post(’/reg’, function(req, res) { var username_ = req.body.username , password_ = req.body.password ; var register_user = { real_name: username_, password: password_, mail: ‘’, birth: new Date() }; user_db.findUser({real_name: username_}, function(err, doc) { if (err) { console.log('not found, and err is ', err.errors); } else { console.log(‘no err, and find user is ‘, doc, doc.length); if (doc.length === 0) { // 该用户名还未被注册 user_db.add(register_user, function(err) { if (err) { res.render(‘reg’, {success: false, err: err.errors}); } else { res.redirect(’/user/login’); } }); } else { console.log(‘用户名已经存在!’); res.render(‘reg’, {success: false, err: ‘用户名已经存在’}); } } })
});
// 登陆页面 app.get([’/’, ‘/login’], function (req, res, next) { var isLogin = false, username = ‘’ ; username = getCookie(req, ‘username’); if (typeof username !== ‘undefined’) { isLogin = true; username = req.cookies.username; } res.render(‘login’, {authenticated: isLogin, username: username}); });
// 登陆请求 app.post(’/login’, upload.array(), function (req, res, next) { var username_ = req.body.username , password_ = req.body.password ; // username: cjs, password: 123456 var search_user = { real_name: username_, password: password_ }; user_db.findUser(search_user, function(err, doc) { if (err) { console.log(err); delCookie(res, ‘username’); res.redirect(’/user’, {success: false, err: err.errors}); } else { console.log(‘pass auth’); setCookie(res, ‘username’, search_user.real_name, 30); res.redirect(’/user/info’); } }); });
// 登出页面 app.get(’/logout’, function(req, res) { delCookie(res, ‘username’); res.redirect(’/user/login’); });
// 测试页面 app.get(’/info’, function (req, res, next) { var isLogin = false, username = undefined ; username = getCookie(req, ‘username’); if (typeof username !== ‘undefined’) { isLogin = true; } res.render(‘info’, {authenticated: isLogin, username: username}) });
app.get(’/badreq’, function (req, res, next) { res.status(400).send(‘Bad request’); });
这样,就写好对应的路由逻辑,最后,在实现模板就可以了: 在views文件夹中添加info.jade、login.jade、reg.jade login.jade: div.sidebar a(href="/user/reg") 注册 if (authenticated) a(href="/user/logout") 退出 else a(href="/user/login") 登录 a(href="/user/info") 主页 div.content if (authenticated) p welcome back, #{username} else h1 User Login form(action="/user/login", method=“POST”) label Username input(type=“text”, name=“username”) label Password input(type=“password”, name=“password”) input(type=“submit”)
reg.jade: div.sidebar a(href="/user/reg") 注册 a(href="/user/login") 登录 a(href="/user/info") 主页 div.content h1 To register if (success == false) .err #{err} form(action="/user/reg", method=“post”) label(for=“username”) username input(type=“text” name=“username”)
label(for="password") password
input(type="password" name="password")
label(for="confirm_password") confirm password
input(type="password")
input(type="submit" value="submit")
info.jade div.sidebar a(href="/user/reg") 注册 if (authenticated) a(href="/user/logout") 退出 else a(href="/user/login") 登录 a(href="/user/info") 主页 div.content if (authenticated) h1 这是主页, #{username} else h1 这是主页,请先登录
样式就不再贴出,这样在浏览器输入http://localhost:3080/user/login 就可以看到登录的页面,至此实现了基本的逻辑功能