使用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
使用express4.x版、Jade模板以及mysql重写《nodejs开发指南》微博实例的更多相关文章
- 《nodejs开发指南》微博实例express4.x版
之前一直执着于前端开发,最近几天,开始学起了nodejs.作为一名前端开发者,见到这样一门用javascript写的后台自然是很激动的.但是,后台毕竟不同于前端,在学习的过程中,还是会遇到不少问题. ...
- 75.《nodejs开发指南》express4.x版-微博案例完整实现
转自:https://blog.csdn.net/cgwcgw_/article/details/39317587 完整代码下载 https://github.com/haishangfeie/wei ...
- 学习Nodejs:《Node.js开发指南》微博项目express2迁移至express4过程中填的坑
<Node.js开发指南>项目地址https://github.com/BYVoid/microblog好不容易找到的基础版教程,但书中是基于express2的,而现在用的是express ...
- Node.js开发指南中的例子(mysql版)
工作原因需要用到nodejs,于是找到了<node.js开发指南>这本书来看看,作者BYVoid 为清华大学计算机系的高材生,年纪竟比我还小一两岁,中华地广物博真是人才辈出,佩服. 言归正 ...
- Jade 模板引擎使用
在 Express 中调用 jade 模板引擎 jade 变量调用 if 判断 循环 Case 选择 在模板中调用其他语言 可重用的 jade 块 (Mixins) 模板包含 (Includes) 模 ...
- zabbix利用自带的模板监控mysql数据库
zabbix利用自带的模板监控mysql数据库 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 有些东西你不会的时候觉得它特别难,但是当你去做的时候就发现如此的简单~zabbix功能 ...
- jade模板
jade 模板使用 npm install jade -g 安装到全局 jade index.jade 导出一个 index.html 压缩后的 jade -P index. ...
- 写一个迷你版Smarty模板引擎,对认识模板引擎原理非常好(附代码)
前些时间在看创智博客韩顺平的Smarty模板引擎教程,再结合自己跟李炎恢第二季开发中CMS系统写的tpl模板引擎.今天就写一个迷你版的Smarty引擎,虽然说我并没有深入分析过Smarty的源码,但是 ...
- jade模板引擎学习笔记(WebsStorm9.0.3+ nodejs+express+jade)
jade环境搭建 jade标签写法 jade注释 jade添加类名.id.属性 jade添加脚本,css jade变量 jade多行文本显示 jade流程代码:for,each,while jade流 ...
随机推荐
- Mac的环境变量
在终端输入: vim ~/.bash_profile 按i切换到INSERT模式.然后把路径按照下面的格式写进去.然后输入:wq保存退出. export PATH=${PATH}:/Users/Dru ...
- c++ zlib(qt)压缩与解压缩
#include <QtCore/QCoreApplication> #include "zlib.h" #include "stdio.h" #i ...
- 查看Ubuntu的版本
方法一: cat /etc/issue 方法二: lsb_release -a
- 使用 Git 命令去管理项目的版本控制(一)
参考资料:参考 参考 声明本文是作者原创,是自己的学习笔记,仅供学习参考. 在 10.11.2Mac系统中,要显示隐藏的文件夹使用命令行: defaults write com.apple.find ...
- Eclipse -- 自动补齐设置和其他用法
1:自动补齐设置:最简单的修改方式是:Windows——>Preferences——>Java-->Editor-->Content Asist,在Auto activatio ...
- Hearthstone
题意: 有$n$个无中生有,有$m$个不同的杀,第$i$个杀掉$X_i$滴血,敌人血量$P$,求问第一回合就将敌人杀死的概率是多少. 解法: 二进制枚举$A$类,$B$类卡的顺序,这样就确定了取了几个 ...
- HDFS源码分析三-DataNode实现
3. DataNode 实现( 未完待续 )
- python使用xlrd操作Excel文件
一.xlrd读取Excel文件 用xlrd进行读取比较方便,流程和平常手动操作Excel一样,打开工作簿(Workbook),选择工作表(sheets),然后操作单元格(cell). 例子:要打开当前 ...
- 怎样让自定义Cell的图片和文本自适应高度
Let's do it! 首先创建一个Model类 包括一个图片名称属性 还有文字内容属性 #import <Foundation/Foundation.h> @interface Mod ...
- 51nod 1068【简单博弈】
思路 手动打表, N 1 : A出1 A胜: 2 : A出2 A胜: 3 : A只能出2的整数幂&&这个数<=3,所以只能出1,2:A出1的时候,B就是2的情况,B胜:A出2的时 ...