zoukankan      html  css  js  c++  java
  • 使用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+'
    '+'['+error.stack+']'+'
    ';
      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

      

      

  • 相关阅读:
    会议记录-5月20日
    会议记录-5月19日
    会议记录—5月18日
    会议记录-5月17日
    会议记录-5月16日
    会议记录-5月13日
    团队博客
    学习进度总结
    校外实习总结
    校外实习报告(二十)
  • 原文地址:https://www.cnblogs.com/yujon/p/6135789.html
Copyright © 2011-2022 走看看