使用express4.x版、Jade模板以及mysql重写《nodejs开发指南》微博实例

  最近阅读《nodejs开发指南》一书,书是不错的,然而其微博代码示例用的是express3.x,用些过时了,运行代码出现不少bug(我电脑安的是express4.x),于是用express4.x+jade模板重写一遍(原代码使用的是ejs模板)。因为想体验一下node结合MySQL开发,于是将mongodb改为mysql。下面进入正文

  1、安装express框架与生成器:

  

  

  2、进入网站目录,创建项目:

  

  3、安装中间件与依赖项:

  

  package.json如下

  

  单独安装时记得加上--save,便于项目迁移重新安装中间件。

  4、启动项目:

  先安装supervisor,启动实时监控文件修改并重新启动服务器,这样就不用每次修改文件都重新启动服务器。

  

  启动项目

  

  5、看看我的项目目录

  

  configs放配置文件,写法遵循commonjs规范。

  install放安装所需文件,安装时读取sql代码连接数据库创建数据表并插入数据,有后台管理时创建保存管理员账号,完成安装时声称lock.txt文件。方便项目迁移。

    log放日志文件,access是访问日志,error是错误日志

  public放静态资源文件。

  models为模型操作文件,相当于为MVC中的M;routes为路由文件,相当于为MVC中的C以及路由解析分发;view为V,视图层。

  utils防止工具类文件以及第三方工具类文件

  cluster.js为充分调用电脑多核资源所写,根据核数量创建相应数量进程运行app.js。运行 supervisor cluster.js

  6、下面看源代码:

  cluster.js

var cluster  = require('cluster');
var os = require('os');
var cpuNum = os.cpus().length;

var workers = {};

if(cluster.isMaster){  //主进程
    //当一个进程结束,重启工作进程
    cluster.on('death',function(worker){
        delete workers[worker.pid];
        worker = cluster.fork();
        workers[worker.pid] = worker;
    })

    //根据CPU数量创建相应数量的进程
    for(var i=0; i<cpuNum;i++){
        var worker = cluster.fork();
        workers[worker.pid] = worker;
    }

}else{//工作进程
    var app = require('./app');
    app.listen(3000);

}

//当主进程终止,关闭所有主进程
process.on('SIGTERM',function(){
    for(var pid in workers){
        precess.kill(pid);
    }
    process.exit(0);
})

 

  app.js

var express = require('express');
var logger = require('morgan');  
var fs = require('fs');
var fileStreamRotator = require('file-stream-rotator')
var cookieParser = require('cookie-parser');
var session = require('express-session');
var bodyParser = require('body-parser');
var path = require('path');
var favicon = require('serve-favicon');
var flash  = require('connect-flash');

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

var app = express();

// 设置模板引擎与模板目录
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

// 日志输出到文件系统,每日一个日志文件
var accessLogDirectory = __dirname + '/logs/access';
fs.existsSync(accessLogDirectory) || fs.mkdirSync(accessLogDirectory);
var errorLogDirectory = __dirname + '/logs/error';
fs.existsSync(errorLogDirectory) || fs.mkdirSync(errorLogDirectory);

var accessLogStream = fileStreamRotator.getStream({
    filename:accessLogDirectory+'/access-%DATE%.log',
    frequency:'daily',
    verbose:false
})
app.use(logger('combined',{stream:accessLogStream}));
// 设置错误日志文件地址
var errorLogStream = fs.createWriteStream(errorLogDirectory+'/error.log',{'flags':'a'});

//将请求体放入request.body
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
//处理cookie
app.use(cookieParser());
//处理session
app.use(session({
    secret:'testexpress',
    cookie: { maxAge: 60000 }, 
    resave: true, 
    saveUninitialized: true
}))

// 设置icon图标
app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
//flash支持
app.use(flash());
//静态文件借口
app.use(express.static(path.join(__dirname, 'public')));

// 挂靠路由中间件
app.use('/', index);
app.use('/index', index);
app.use('/user', user);

//404错误处理句柄
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

//错误处理
app.use(function(err, req, res, next) {

  var error = (req.app.get('env') === 'development' )? err : {};
  
  //写错误日志
  var errorMes = '['+Date()+']'+req.url+'\n'+'['+error.stack+']'+'\n';
  errorLogStream.write(errorMes);

  // 写回错误处理代码
  res.status(err.status || 500);
  res.render('error',{'message':err.message,'error':error});
});

//防止服务器自启动。只许在外部模块调用
if(!module.parent){
    app.listen(3000,function(){    
        console.log("Server listening on port %d in %s",3000,app.settings.env);
    });
}


module.exports = app;

 

   routes/index.js

var express = require('express');
var router = express.Router();

var News = require('../models/news');


/* GET home page. */
router.get('/', function(req, res, next) {
    News.get(null,function(err,news){
        var user = null;
        if(err){
            news = [];
        }
        if(req.session.user){
            user = req.session.user;
        }
        res.render('index/index', { 
              title: '微博首页',
              news:news,
              user:user
          });
    })
});

module.exports = router;

 

  routes/user.js

var express = require('express');
var router = express.Router();

var User = require('../models/user');
var News = require('../models/news');

var crypto = require('crypto');

//访问用户页面
router.get('/:user', function (req, res) { 
  User.get(req.params.user,  function (err, user) { 
    if (!user) { 
     console.log(req.session);
      req.flash('error', ' 用户不存在'); 
       return  res.redirect('/'); 
    } 
    console.log(user);
    News.get(user.username, function (err, news) { 
       if (err) { 
        req.flash('error', err); 
         return  res.redirect('/'); 
      } 
      res.render('user/index', { 
        username: user.username, 
        news: news
      }); 
    }); 
  }); 
});

//访问注册页
router.get("/reg",checkNotLogin);
router.get("/reg",function(req,res){
    res.render('reg',{
        'title':'用户注册'
    })
})
//提交注册信息
router.post('/reg',checkNotLogin);
router.post('/reg',function(){
    if(req.body['password-repeat']!=req.body['password']){
            req.flash('error','两次输入的口令不一致');
            return res.redirect('/reg');
        }
    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 already exists.'; 
        if (err) { 
          req.flash('error', err); 
          return res.redirect('/reg'); 
        } 
        // 如果不存在则新增用户 
        newUser.save(function (err) { 
            if (err) { 
                req.flash('error', err); 
                 return  res.redirect('/reg'); 
             } 
            req.flash('success', ' 注册成功'); 
            res.redirect('/login'); 
        });
    }); 
})

//用户访问登录页
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', ' 登入成功'); 
        res.redirect('/'); 
    }); 
})

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

//找回密码
router.get('/getPwd',checkNotLogin);
router.get('/getPwd',function(req,res){
    res.render('getpwd', { 
    title: '密码找回', 
  }); 
})

router.post('/getPwd',checkNotLogin);
router.post('/getPwd',function(req,res){
    User.get(req.body.username, function (err, user) { 
        if (!user) { 
          req.flash('error', ' 用户不存在'); 
           return  res.redirect('/getPwd'); 
        } 
        req.flash('success', '成功找回密码:'+user.password); 
        res.redirect('/login'); 
    }); 
})


//发表微博
router.post('/news', checkLogin); 
router.post('/news',  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', ' 发表成功'); 
    res.redirect('/u/' + currentUser.name); 
  }); 
});



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;

 

configs/settings.js

(function(){
   var settings;
   settings = {
          mysql:{
                  host:'localhost',
                  prot:'3306',
                  user:'root',
             password:'',
             database:'node_microblog'
          },
      mongodb:{
           host:'localhost',
           prot:'27017',
           user:'root',
          password:'',
          database:'node_microblog'
      }

   }
   module.exports = settings;
})()

 utils/database.js

 (function(){

         var settings = require('../configs/settings');
         var mysql = require('mysql');
         var client = null;

         var default_sql = require


         exports.getDbCon = function(){
             try{
                 if(client){
                     client = mysql.createConnection(settings.mysql);
                     client.connect();
                 }else{
                     client = new mysql.createConnection(settings.mysql);
                     client.connect();
                 }
             }catch(_error){
                 throw _error;
             }
             return client;
         }

         exports.install = function(){
             
         }
 })()
 

 

 models/news.js

var database = require('../utils/database');
mysql = database.getDbCon();

function News(username,content,time){
    this.username = username;
    this.content = content;
    if (time) {
        this.time = time;
    } else {
        this.time =  new Date ();
        console.log(this.time);
    }
}

//保存消息
News.prototype.save = function(callback){

    var sql = "select id from user where username = '"+this.username+"'";
    mysql.query(sql,function(err,results,fields){
        if(err){
            throw err;
        }
        if(results){
            this.uid = results[0].id;
        }   
        var  news = {
            username: this.uid,
            content: this.conetnt,
            time: this.time
         };

        sql = "insert into user(uid,content,time) values(?,?,?)";
        mysql.query(sql,[news.uid,news.content,news.time],function(err,results,fields){
            if (err) {
                throw err;
            } else {
                //返回用户id
                return callback(err,fields);
            }
        })
    })
};

//获取消息
News.get = function(username,callback){
    
      
    var sql ="select * from news";
    if( username){
        sql +=" join user on user.id=news.uid where username='"+username+"'";
    }
    mysql.query(sql,function(err,results,fields){
        if(err){
            throw err;
        }else{
            callback(err,results,fields);
        }
    })
}

module.exports = News;

 

models/user.js

var database = require('../utils/database');
mysql = database.getDbCon();

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

//保存用户
User.prototype.save = function(callback){
    var  user = {
        username: this.username,
        password: this.password
    };

    var sql ="insert into user (username,password) values(?,?)";

    mysql.query(sql,[user.username,user.password],function(err,results,fields){
        if (err) {
            throw err;
        } else {
            //返回用户id
            return callback(err,fields);
        }
    });
};

//获取用户
User.get = function(id,callback){
    var sql = "select * from user where id='"+id+"'";
        mysql.query(sql,function(err,results,fields){
            if(err){
                throw err;
            }else{
                callback(err,results[0],fields);
            }
        })
}


module.exports = User;

 

 

  源代码下载:https://github.com/yujon/node_microblog

 

  

  

posted on 2016-12-05 22:27  yujon  阅读(1250)  评论(2编辑  收藏  举报

导航