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 name cookie: {maxAge: 1000 * 60 * 60 * 24 * 30},//30 days store: 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 信息 } //查找用户名(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 }); //检查用户名是否已经存在 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;//用户信息存入 session req.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');//密码错误则跳转到登录页 } //用户名密码都匹配后,将用户信息存入 session req.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'> 用户名: <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"> 用户名:<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 %>
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。