NAE管理系统开发(nodejs+express+mongoDB)小结
这算是我第一个web的程序,写的各种丑陋不堪..记录一些不算收获的东西。看到哪写到哪。
1、路由中间件:用户登录检测和权限检测可以交给路由中间件去处理。
app.post( " /application/manage/:id/coopmng " , hasLogin, checkChangeAuth( " infoRight " ), manager.doCoopmng);
2、通过prototype,可以十分轻易的扩展内置的对象:扩展Date,添加format方法。
/*
*
* 时间对象的格式化;
*/
Date.prototype.format = function (format){
/*
* eg:format="YYYY-MM-dd hh:mm:ss";
*/
var o = {
" M+ " : this .getMonth() + 1 , // month
" d+ " : this .getDate(), // day
" h+ " : this .getHours(), // hour
" m+ " : this .getMinutes(), // minute
" s+ " : this .getSeconds(), // second
" q+ " : Math.floor(( this .getMonth() + 3 ) / 3 ), // quarter
" S " : this .getMilliseconds() // millisecond
}
if ( / (( | Y | ) + ) / .test(format)) {
format = format.replace(RegExp.$ 1 , ( this .getFullYear() + "" ).substr( 4 - RegExp.$ 1 .length));
}
for ( var k in o) {
if ( new RegExp( " ( " + k + " ) " ).test(format)) {
format = format.replace(RegExp.$ 1 , RegExp.$ 1 .length == 1 ? o[k] : ( " 00 " + o[k]).substr(( "" + o[k]).length));
}
}
return format;
}
* 时间对象的格式化;
*/
Date.prototype.format = function (format){
/*
* eg:format="YYYY-MM-dd hh:mm:ss";
*/
var o = {
" M+ " : this .getMonth() + 1 , // month
" d+ " : this .getDate(), // day
" h+ " : this .getHours(), // hour
" m+ " : this .getMinutes(), // minute
" s+ " : this .getSeconds(), // second
" q+ " : Math.floor(( this .getMonth() + 3 ) / 3 ), // quarter
" S " : this .getMilliseconds() // millisecond
}
if ( / (( | Y | ) + ) / .test(format)) {
format = format.replace(RegExp.$ 1 , ( this .getFullYear() + "" ).substr( 4 - RegExp.$ 1 .length));
}
for ( var k in o) {
if ( new RegExp( " ( " + k + " ) " ).test(format)) {
format = format.replace(RegExp.$ 1 , RegExp.$ 1 .length == 1 ? o[k] : ( " 00 " + o[k]).substr(( "" + o[k]).length));
}
}
return format;
}
3、cookie处理:在登录的时候,给它设置一个cookie,设定好过期时间,内容包含:userName,timestamp,checkCode=md5(userName, password, timestamp, skey)。skey是保存在服务器端的一个私钥。在登录验证cookie的时候,先检测时间是否过期(不能只依靠cookie的自动失效),然后再取出user现在的password,重新计算checkCode。可以保证用户修改密码后之前的cookie会失效。
4、通过eventProxy,可以并行查询数据库,提高效率,同时让代码简洁。
checkEventProxy.assign(
"
checkName
"
,
"
checkEmail
"
,
function
(goodName, goodEmail){
console.log(goodName);
if ( ! goodName)
return res.render( " error " , {message: " 昵称已经被注册 " });
if ( ! goodEmail)
return res.render( " error " , {message: " email已经被注册 " });
else {
users.save({email:userEmail, nickName:userNickName, password:userPassword}, function (err){
if (err){
log.error(err);
return res.render( " error " , {message: " 注册失败,请稍后再试 " });
}
else {
req.session.email = userEmail;
req.session.nickName = userNickName;
res.redirect( " /application " );
}
});
}
});
// 检查email是否已经存在
users.findOne({email:userEmail.toString()}, function (err, item){
if (err){
log.error(err);
checkEventProxy.trigger( " checkEmail " , false );
} else {
if (item)
checkEventProxy.trigger( " checkEmail " , false );
else
checkEventProxy.trigger( " checkEmail " , true );
}
});
// 检查昵称是否已经存在
users.findOne({nickName:userNickName.toString()}, function (err, item){
if (err){
log.error(err);
checkEventProxy.trigger( " checkName " , false );
} else {
if (item)
checkEventProxy.trigger( " checkName " , false );
else
checkEventProxy.trigger( " checkName " , true );
}
});
}
console.log(goodName);
if ( ! goodName)
return res.render( " error " , {message: " 昵称已经被注册 " });
if ( ! goodEmail)
return res.render( " error " , {message: " email已经被注册 " });
else {
users.save({email:userEmail, nickName:userNickName, password:userPassword}, function (err){
if (err){
log.error(err);
return res.render( " error " , {message: " 注册失败,请稍后再试 " });
}
else {
req.session.email = userEmail;
req.session.nickName = userNickName;
res.redirect( " /application " );
}
});
}
});
// 检查email是否已经存在
users.findOne({email:userEmail.toString()}, function (err, item){
if (err){
log.error(err);
checkEventProxy.trigger( " checkEmail " , false );
} else {
if (item)
checkEventProxy.trigger( " checkEmail " , false );
else
checkEventProxy.trigger( " checkEmail " , true );
}
});
// 检查昵称是否已经存在
users.findOne({nickName:userNickName.toString()}, function (err, item){
if (err){
log.error(err);
checkEventProxy.trigger( " checkName " , false );
} else {
if (item)
checkEventProxy.trigger( " checkName " , false );
else
checkEventProxy.trigger( " checkName " , true );
}
});
}
5、通过谷歌smtp.gmail.com或者其他的smtp服务提供商,可以发送邮件(不需要sendmail支持)。nodemailer模块(npm install nodemailer)可以十分简单的发送邮件以及附件。
6、mongoDB不支持多表查询,所以可能要有适当的数据表项冗余。同时mongoDB不提供事务,也无法完全保证原子性。
mongoDB选定collection后的增删查改操作:
db.collections(
"
users
"
).findOne({userEmail:email},{nickName:
1
/*
查询结果包含nickName
*/
},
function
(err,data){});
db.collections(
"
users
"
).find({userEmail:email},{skip:
10
/*
跳过10条记录
*/
, limit:
10
/*
结果最多10条,。实现分页功能
*/
}).toArray(
function
(err,data){});
db.collections(
"
users
"
).save({
/*
save的内容
*/
},
function
(){})
//
插入
db.collections( " users " ).remove({ /* 条件 */ }, function (){})
db.collections( " users " ).update({ /* 条件 */ },{$set:{ /* 内容 */ }})
db.collections( " users " ).remove({ /* 条件 */ }, function (){})
db.collections( " users " ).update({ /* 条件 */ },{$set:{ /* 内容 */ }})
7、div通过float左右分屏的时候,必须要在它们的父div添加fixClear类。通过添加一个隐藏的元素在父div最下方,让浏览器检测到两个左右浮动的div的高度,从而不会出现显示错误。
.clearfix:after
{
content : "." ;
display : block ;
clear : both ;
visibility : hidden ;
line-height : 0 ;
height : 0 ;
}
.clearfix {
display : inline-block ;
}
content : "." ;
display : block ;
clear : both ;
visibility : hidden ;
line-height : 0 ;
height : 0 ;
}
.clearfix {
display : inline-block ;
}
8.express的session,默认是存为持久的,像cookie一样要到一定时间才过期。在存session的时候,通过把req.session.cookie.expires设置成为false,可以将session设置为非持久,这样在浏览器关闭的时候,session就会消掉。