您的位置:首页 > Web前端 > Node.js

对于node.js开发指南中博客案例的修改实现(二)--代码

2015-06-26 20:57 656 查看
OK,废话少说,直接上代码

首先是app.js,里面很多与书中介绍的不同,不过看起来都很容易懂。首先是各种模块引用,然后就是使用session保存状态。

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var session = require('express-session');//需要项目目录下npm install  安装模块
var MongoStore = require('connect-mongo')(session);//需要项目目录下npm install connect-mongo 安装模块
var settings = require("./settings");
var flash = require('connect-flash');//需要项目目录下npm install connect-flash 安装模块

var routes = require('./routes/index');
var users = require('./routes/users');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(require('less-middleware')(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'public')));
app.use(flash());

app.use(session({
secret:settings.coolieSecret,//express.cookieParser()  是 Cookie 解析的中间件

//store参数为MongoStore实例,把会话信息存储到数据库中,以避免丢失。
store:new MongoStore({
db:settings.db
}),
resave:true,
saveUninitialized:true
}));

//获取状态
app.use(function(req,res,next){
console.log("app.user local");
res.locals.user = req.session.user;
res.locals.post = req.session.post;

var error = req.flash('error');
res.locals.error = error.length?error:null;

var success = req.flash('success');
res.locals.success = success.length?success:null;

next();
});

app.use('/', routes);
app.use('/users', users);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});

module.exports = app;


下面看看路由控制routes/index.js:代码中都有注释。其中需要注意的是中文参数的处理(先base64编码再解码)

var express = require('express');
var crypto = require('crypto');
var router = express.Router();
var settings = require("../settings");
var User = require("../models/user.js");
var Post = require("../models/post.js");
var iconv = require('iconv-lite');
/* GET home page. */
/*
router.get('/', function(req, res, next) {
res.render('index', { title: settings.title });
});
*/
router.get('/',function(req,res){
Post.get(null,function(err,posts){
if(err){
posts = [];
}
res.render('index',{title:"首页",posts:posts});
});

});

router.get('/reg',checkNotLogin);
router.get('/reg',function(req,res){
res.render('reg',{title:"注册"});
});

//注册事件处理
router.post('/reg',checkNotLogin);
router.post('/reg',function(req,res){
console.log(req.body);
//检测两次输入的密码是否相同
//req.body 就是 POST 请求信息解析过后的对象,例如我们要访问用户传递的password 域的值,只需访问 req.body['password'] 即可。
if(req.body['password-repeat'] != req.body['password']){
//req.flash 是 Express 提供的一个奇妙的工具,通过它保存的变量只会在用户当前和下一次的请求中被访问,之后会被清除,
//通过它我们可以很方便地实现页面的通知和错误信息显示功能
req.flash('error','两次输入的口令不一致');
return res.redirect('/reg');
}
//生成口令的散列值
//crypto 是 Node.js 的一个核心模块,功能是加密并生成各种散列,
//使用它之前首先要声明 var crypto = require('crypto')。我们代码中使用它计算了密码的散列值。
var md5 = crypto.createHash('md5');
var password = md5.update(req.body.password).digest('base64');

var newUser = new User({
name : req.body.username,
password : password
});

//检查用户名是否存在
User.get(newUser.name,function(err,user){
if(user){
err = "username is already exists. ";
}
if(err){
req.flash('error',err);
console.log(err);
return res.redirect('/reg');
}
console.log("save");
//不存在则保存新用户
newUser.save(function(err){
if(err){
req.flash('error',err);
console.log(err);
console.log("save err");
return res.redirect('/reg');
}
req.session.user = newUser;
req.flash('success','注册成功');
return res.redirect('/');
});

});
});

//登录
router.get('/login',checkNotLogin);
router.get('/login',function(req,res){
res.render('login',{title:'登录'});
});

//响应登录事件
router.post('/login',checkNotLogin);
router.post('/login',function(req,res){
var md5 = crypto.createHash('md5');
var password = md5.update(req.body.password).digest('base64');
User.get(req.body.username,function(err,user){
if(!user){
req.flash('error','用户名不存在');
return res.redirect('/login');
}
if(user.password != password){
req.flash('error','密码错误');
return res.redirect('/login');
}
req.session.user = user;
req.flash('success','登录成功');
return res.redirect('/');
})
});

//登出
router.get('/logout',checkLogin);
router.get('/logout', function (req,res) {
req.session.user = null;
req.flash('success','登出成功');
res.redirect('/');
});

//发表处理
router.post('/post',checkLogin);
router.post('/post',function(req,res){
var currentUser = req.session.user;
var post = new Post(currentUser.name,req.body.post);
post.save(function(err){
if(err){
req.flash('error',err);
return res.redirect('/');
}
req.flash('success','发表成功');
console.log('/u/'+currentUser.name);
var pramsUserNnametemp = new Buffer(currentUser.name);
var pramsUserNname = pramsUserNnametemp.toString('base64');//为了解决中文参数问题将参数base64编码,然后解码
// res.redirect('/u/'+currentUser.name);
res.redirect('/u/'+pramsUserNname);
});
});

router.get("/u/:user",function(req,res){
var uNametemp = new Buffer(req.params.user,'base64');//base64解码
var uName = uNametemp.toString();
//User.get(req.params.user, function(err,user){
User.get(uName, function(err,user){
if(!user){
req.flash('error','用户不存在');
res.redirect('/');
}
Post.get(user.name,function(err,posts){
if(err){
req.flash('error',err);
res.redirect('/');
}
res.render('user',{title:user.name,posts:posts});
});
});
});

function checkLogin(req,res,next){
if(!req.session.user){
req.flash('error',"未登录");
return res.redirect('/login');
}
next();
}
function checkNotLogin(req,res,next){
if(req.session.user){
req.flash('error',"已登录");
return res.redirect('/');
}
next();
}
module.exports = router;


在看一下models目录下的user.js,就是对mongodb的操作,保存查询

var mongodb = require('./db');

function User(user){
this.name = user.name;
this.password = user.password;
};

module.exports = User;

User.prototype.save = function save(callback){
//存入mongodb的文档
var user = {
name:this.name,
password:this.password
};
mongodb.open(function(err,db){
if(err){
return callback(err);
}

//读取users集合
db.collection('users',function(err,collection){
if(err){
mongodb.close();
return callback(err);
}
//为name属性添加索引,新版本的ensureIndex方法需要一个回调函数
collection.ensureIndex('name',{unique:true},function(err){
//写入user文档
collection.insert(user,{safe:true},function(err,user){
mongodb.close();
callback(err,user);
});
});

});
});
};

User.get = function get(username,callback){
mongodb.open(function(err,db){
if(err){
return callback(err);
}
//读取users集合
db.collection('users',function(err,collection){
if(err){
mongodb.close();
return callback(err);
}

//查找name属性为username的文档
collection.findOne({name:username},function(err,doc){
mongodb.close();
if(doc){
//封装文档为User对象
var user = new User(doc);
callback(err,user);
}
else{
callback(err,null);
}
});
});
});
};

post.js:

var mongodb = require("./db");

function Post(username,post,time){
this.user = username;
this.post = post;
if(time){
this.time = time;
}
else{
this.time = new Date();
}
};

module.exports = Post;

Post.prototype.save = function save(callback){
//存入Mongodb的文档
var post = {
username:this.user,
post:this.post,
time:this.time
};

mongodb.open(function(err,db){
if(err){
return callback(err);
}

//读取posts集合
db.collection('posts',function(err,collection){
if(err){
mongodb.close();
return callback(err);
}
//为user属性添加索引
collection.ensureIndex('user',function(err){
//写入post文档
collection.insert(post,{safe:true},function(err,post){
mongodb.close();
callback(err,post);
});
});

});

});
};

Post.get = function get(username,callback){
mongodb.open(function(err,db){
if(err){
return callback(err);
}
//读取posts集合
db.collection('posts',function(err,collection){
if(err){
mongodb.close();
return callback(err);
}
//查找user属性为username的文档,如果sername是null则全部匹配
var query = {};
if(username){
query.username = username;
}
collection.find(query).sort({time:-1}).toArray(function(err,docs){
mongodb.close();
if(err){
callback(err,null);
}
//封装posts为Post对象
var posts = [];
docs.forEach(function(doc,index){
var post = new Post(doc.username,doc.post,doc.time);
posts.push(post);
});
callback(null,posts);
});
});
});
};


主要的代码就这些了,跟书中的差别还是很大的,主要模块更新太快,书更新的速度跟不上技术的更新。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: