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

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);
         });
      });
   });
};


主要的代码就这些了,跟书中的差别还是很大的,主要模块更新太快,书更新的速度跟不上技术的更新。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值