Node.js 博客实例(一)简单博客
原教程?https://github.com/nswbmw/N-blog/wiki/_pages的第一章。因為版本號等的原因,在原教程基礎上稍加修改就可以實現。
環境:
win7旗艦版64位
Node.js:0.10.31
mongodb:2.6.4
express:3.×
效果:
注冊界面:登錄界面:
登錄成功:
發表博客:
發表成功:
源碼:
blog/
blog/package.json
{"name": "blog","version": "0.0.1","private": true,"scripts": {"start": "node app.js"},"dependencies": {"express": "3.16.7","ejs": "*","mongodb":"*","connect-mongo":"*","connect-flash":"*"} }blog/app.js
/*** Module dependencies.*/var express = require('express'); var routes = require('./routes'); var http = require('http'); var path = require('path'); var MongoStore=require('connect-mongo')(express); var settings=require('./settings'); var flash=require('connect-flash'); var app = express();// all environments app.set('port', process.env.PORT || 3000); app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'ejs'); app.use(flash()); app.use(express.favicon()); app.use(express.logger('dev')); app.use(express.bodyParser()); app.use(express.methodOverride());app.use(express.static(path.join(__dirname, 'public'))); app.use(express.cookieParser()); app.use(express.session({secret: settings.cookieSecret,key: settings.db,//cookie namecookie: {maxAge: 1000 * 60 * 60 * 24 * 30},//30 daysstore: new MongoStore({db: settings.db}) })); //此句寫在session前面就會出錯 為啥捏 app.use(app.router);// development only if ('development' == app.get('env')) {app.use(express.errorHandler()); }routes(app);http.createServer(app).listen(app.get('port'), function(){console.log('Express server listening on port ' + app.get('port')); });blog/settings.js
module.exports={cookieSecret:'myblog',db:'blog',host:'localhost' };blog/models/
blog/models/db.js
var settings=require('../settings'),Db=require('mongodb').Db,Connection=require('mongodb').Connection,Server=require('mongodb').Server; module.exports=new Db(settings.db,new Server(settings.host,Connection.DEFAULT_PORT), {safe: true});blog/models/post.js
var mongodb = require('./db');function Post(name, title, post) {this.name = name;this.title = title;this.post = post; }module.exports = Post;//存儲一篇文章及其相關信息 Post.prototype.save = function(callback) {var date = new Date();//存儲各種時間格式。方便以后擴展var time = {date: date,year : date.getFullYear(),month : date.getFullYear() + "-" + (date.getMonth() + 1),day : date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate(),minute : date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate() + " " + date.getHours() + ":" + (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()) }//要存入數據庫的文檔var post = {name: this.name,time: time,title: this.title,post: this.post};//打開數據庫mongodb.open(function (err, db) {if (err) {return callback(err);}//讀取 posts 集合db.collection('posts', function (err, collection) {if (err) {mongodb.close();return callback(err);}//將文檔插入 posts 集合collection.insert(post, {safe: true}, function (err) {mongodb.close();if (err) {return callback(err);//失敗!返回 err}callback(null);//返回 err 為 null});});}); };//讀取文章及其相關信息 Post.get = function(name, 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);}var query = {};if (name) {query.name = name;}//依據 query 對象查詢文章collection.find(query).sort({time: -1}).toArray(function (err, docs) {mongodb.close();if (err) {return callback(err);//失敗!返回 err}callback(null, docs);//成功!以數組形式返回查詢的結果});});}); };blog/models/user.js
var mongodb = require('./db');function User(user) {this.name = user.name;this.password = user.password;this.email = user.email; };module.exports = User;//存儲用戶信息 User.prototype.save = function(callback) {//要存入數據庫的用戶文檔var user = {name: this.name,password: this.password,email: this.email};//打開數據庫mongodb.open(function (err, db) {if (err) {return callback(err);//錯誤。返回 err 信息}//讀取 users 集合db.collection('users', function (err, collection) {if (err) {mongodb.close();return callback(err);//錯誤。返回 err 信息}//將用戶數據插入 users 集合collection.insert(user, {safe: true}, function (err, user) {mongodb.close();if (err) {return callback(err);//錯誤,返回 err 信息}callback(null, user[0]);//成功!
err 為 null,并返回存儲后的用戶文檔 }); }); }); }; //讀取用戶信息 User.get = function(name, callback) { //打開數據庫 mongodb.open(function (err, db) { if (err) { return callback(err);//錯誤,返回 err 信息 } //讀取 users 集合 db.collection('users', function (err, collection) { if (err) { mongodb.close(); return callback(err);//錯誤。返回 err 信息 } //查找username(name鍵)值為 name 一個文檔 collection.findOne({ name: name }, function (err, user) { mongodb.close(); if (err) { return callback(err);//失敗!
返回 err 信息 } callback(null, user);//成功!
返回查詢的用戶信息 }); }); }); };
blog/public/
blog/public/stylesheets/style.css
/* inspired by http://yihui.name/cn/ */ *{padding:0;margin:0;} body{width:600px;margin:2em auto;padding:0 2em;font-size:14px;font-family:"Microsoft YaHei";} p{line-height:24px;margin:1em 0;} header{padding:.5em 0;border-bottom:1px solid #cccccc;} nav{position:fixed;left:12em;font-family:"Microsoft YaHei";font-size:1.1em;text-transform:uppercase;width:9em;text-align:right;} nav a{display:block;text-decoration:none;padding:.7em 1em;color:#000000;} nav a:hover{background-color:#ff0000;color:#f9f9f9;-webkit-transition:color .2s linear;} article{font-size:16px;padding-top:.5em;} article a{color:#dd0000;text-decoration:none;} article a:hover{color:#333333;text-decoration:underline;} .info{font-size:14px;}blog/routes/
blog/routes/index.js
/** GET home page.*/ var crypto = require('crypto'),User = require('../models/user.js'),Post=require('../models/post.js');module.exports = function(app) {app.get('/', function (req, res) {Post.get(null, function (err, posts) {if (err) {posts = [];} res.render('index', {title: '主頁',user: req.session.user,posts: posts,success: req.flash('success').toString(),error: req.flash('error').toString()});});});app.get('/reg', checkNotLogin);app.get('/reg', function (req, res) {res.render('reg', {title: '注冊',user: req.session.user,success: req.flash('success').toString(),error: req.flash('error').toString()});});app.post('/reg', checkNotLogin);app.post('/reg', function (req, res) {var name = req.body.name,password = req.body.password,password_re = req.body['password-repeat'];//檢驗用戶兩次輸入的密碼是否一致if (password_re != password) {req.flash('error', '兩次輸入的密碼不一致!'); return res.redirect('/reg');//返回注冊頁}//生成密碼的 md5 值var md5 = crypto.createHash('md5'),password = md5.update(req.body.password).digest('hex');var newUser = new User({name: name,password: password,email: req.body.email});//檢查username是否已經存在 User.get(newUser.name, function (err, user) {if (user) {req.flash('error', '用戶已存在!');return res.redirect('/reg');//返回注冊頁}//假設不存在則新增用戶newUser.save(function (err, user) {if (err) {req.flash('error', err);return res.redirect('/reg');//注冊失敗返回主冊頁}req.session.user = user;//用戶信息存入 sessionreq.flash('success', '注冊成功!');res.redirect('/');//注冊成功后返回主頁});});});app.get('/login', checkNotLogin);app.get('/login', function (req, res) {res.render('login', {title: '登錄',user: req.session.user,success: req.flash('success').toString(),error: req.flash('error').toString()});});app.post('/login', checkNotLogin);app.post('/login', function (req, res) {//生成密碼的 md5 值var md5 = crypto.createHash('md5'),password = md5.update(req.body.password).digest('hex');//檢查用戶是否存在User.get(req.body.name, function (err, user) {if (!user) {req.flash('error', '用戶不存在!'); return res.redirect('/login');//用戶不存在則跳轉到登錄頁}//檢查密碼是否一致if (user.password != password) {req.flash('error', '密碼錯誤!'); return res.redirect('/login');//密碼錯誤則跳轉到登錄頁}//username密碼都匹配后,將用戶信息存入 sessionreq.session.user = user;req.flash('success', '登陸成功!');res.redirect('/');//登陸成功后跳轉到主頁});});app.get('/post', checkLogin);app.get('/post', function (req, res) {res.render('post', { title: '發表' ,user: req.session.user,success: req.flash('success').toString(),error: req.flash('error').toString()});console.log("222");});app.post('/post', checkLogin);app.post('/post', function (req, res) {var currentUser = req.session.user, post = new Post(currentUser.name, req.body.title, req.body.post);post.save(function (err) {if (err) {req.flash('error', err); return res.redirect('/');}req.flash('success', '公布成功!');res.redirect('/');//發表成功跳轉到主頁});});app.get('/logout', checkLogin);app.get('/logout', function (req, res) {req.session.user = null;req.flash('success', '登出成功!');res.redirect('/');//登出成功后跳轉到主頁});function checkLogin(req, res, next) {if (!req.session.user) {req.flash('error', '未登錄!'); res.redirect('/login');}next();}function checkNotLogin(req, res, next) {if (req.session.user) {req.flash('error', '已登錄!'); res.redirect('back');}next();} };blog/views/
blog/views/header.ejs
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>Blog</title> <link rel="stylesheet" href="/stylesheets/style.css"> </head> <body><header> <h1><%= title %></h1> </header><nav> <span><a title="主頁" href="/">home</a></span> <% if (user) { %><span><a title="發表" href="/post">post</a></span><span><a title="登出" href="/logout">logout</a></span> <% } else { %><span><a title="登錄" href="/login">login</a></span><span><a title="注冊" href="/reg">register</a></span> <% } %> </nav><article><% if (success) { %><div><%= success %></div> <% } %> <% if (error) { %><div><%= error %> </div> <% } %>blog/views/footer.ejs
</article> </body> </html>blog/views/index.ejs
<%- include header %> <% posts.forEach(function (post, index) { %><p><h2><a href="#"><%= post.title %></a></h2></p><p class="info">作者:<a href="#"><%= post.name %></a> | 日期:<%= post.time.minute %></p><p><%- post.post %></p> <% }) %> <%- include footer %>blog/views/reg.ejs
<%- include header %> <form method="post" url='/reg'>username: <input type="text" name="name"/><br />密碼: <input type="password" name="password"/><br />確認密碼:<input type="password" name="password-repeat"/><br />郵箱: <input type="email" name="email"/><br /><input type="submit" value="注冊"/> </form> <%- include footer %>blog/views/login.ejs
<%- include header %> <form method="post">username:<input type="text" name="name"/><br />密碼: <input type="password" name="password"/><br /><input type="submit" value="登錄"/> </form> <%- include footer %>blog/views/post.ejs
<%- include header %> <form method="post" url='/post'>TITLE:<br /><input type="text" name="title" /><br />DETAIL:<br /><textarea name="post" rows="20" cols="100"></textarea><br /><input type="submit" value="POST" /> </form> <%- include footer %>關于這個疑問
找到答案了
router is executed without session executed while session is used in router , i think
總結
以上是生活随笔為你收集整理的Node.js 博客实例(一)简单博客的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 前端project师养成记:开发环境搭建
- 下一篇: linux网络编程-socket(2)