原教程 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 博客实例(一)简单博客相关推荐

  1. node.js创建网站实例3

    node.js访问mysql数据库并把查询结果返回给前端 1.cmd中运行:npm install mysql -s 2.修改api.js的代码 // 1.先引入express模块,express是一 ...

  2. Node.js 从零开发web server博客项目--项目初始化

    本篇博客记录了<Node.js 从零开发web server博客项目>的原生开发系列内容. 开篇主要介绍原生项目的搭建,以及初步的项目结构设计. 一.项目初始化 新建项目目录,并进入到项目 ...

  3. 图解基于 Node.js 实现前后端分离 - CSDN博客

    因为会上出了个意外,ppt图片全部丢失,只好对着白板跟大家交流了半个多小时.由于我做演讲不喜欢写太多的文字,没有图片的情况下讲漏了一些内容.这篇文章是我在会上分享内容对照ppt进行地整理. 基本介绍 ...

  4. 10+ 最佳的 Node.js 教程和实例

    如果你正在找Node.js的学习资料及指南,那么请继续(阅读),我们的教程将会覆盖即时聊天应用.API服务编写.投票问卷应用.人物投票APP.社交授权. Node.js on Raspberry Pi ...

  5. node.js入门 - 2.创建一个简单聊天室

    这篇文章将通过开发一个简单聊天室的方式,介绍node.js的net模块. 一.第一版,只向客户端发送信息   我们先实现一个简单的版本,代码如下: var net=require('net'); va ...

  6. 《Node.js 入门系列》—— 一些简单的排错方法(一)

    目录 TypeError: undefined is not a function TypeError: Cannot read property 'xxx' of undefined 或者 Type ...

  7. node.js当中net模块的简单应用(基于控制台的点对点通信)

    我们可以使用node.js当中内置的net模块来创建socket服务端和socket客户端,实现一个简单的基于控制台的点对点通信. 一.利用net模块建立socket客户端 1.引包 const ne ...

  8. node如何输出html页面,【自己的整理】node.js直接输出一个非常简单的HTML页面-Go语言中文社区...

    刚开始接触nodejs,先记录一下最开始用node输出一个很简单的界面 在远程服务器上先创建一个js文件 helloworld.js [root@towrabbit nodejsLearn]# vi ...

  9. Node JS和MongoDB的集成简单示例

    In this post, we will discuss about how to integration Node JS Platform with MongoDB NoSQL Database ...

  10. Node.js 模块化的操作,简单明了的代码帮助你明白后端的实现和前端之前的交互,及解决跨域等问题

      Node.JS 模块化 1.require 导入模块const http=require('http')2.exports 导出模块db={name:'jine',age:22} module.e ...

最新文章

  1. SDwebimage使用原理(转载)
  2. 那些伤害不大,侮辱性极强的瞬间
  3. hibernate savealiasentity 保存后id为空_好程序员Java教程分享Java面试题之Hibernate
  4. PID1 / 明明的随机数
  5. 计算机设计目的和意义,程序设计的目的和意义.doc
  6. springboot quartz 动态配置_springboot集成quartz实现动态任务调度
  7. Android之实现RTL的ViewPager
  8. 全面拥抱 FastApi — 多应用程序项目结构规划
  9. 《流浪地球》内地票房超《红海行动》北美上映11天成绩不俗
  10. 【机器学习-西瓜书】二、偏差-方差分解;泛化误差
  11. Android实现EditText插入表情、超链接等格式
  12. 阿里云服务器安装mysql数据库及连接使用
  13. Nginx源码包软件安装步骤
  14. python not_刚接触Python,python中not in怎么解释?求解释一下?
  15. 关于word使用之三线表制作
  16. 分享餐饮管理组织结构流程图模板
  17. 计算机没有安装cad2006,win7系统不能正常安装cad2006的解决方法
  18. 日常食物软分类与烹饪方法的思考——预防肥胖
  19. PMP项目管理是什么?
  20. 梯田油菜花海距杭州仅120公里

热门文章

  1. 新发传染病临床案例研究 Emerging Infectious Diseases. Clinical Case Studies
  2. Notepad++安装教程
  3. C语言 | 编译与预处理指令(宏定义完整讲解:#define)
  4. 树莓派4b设置RTC时钟模块DS3231
  5. 程序设计语言编译原理_编译原理学习笔记(二):高级程序设计语言
  6. python浏览上一句_python一句话启动http服务
  7. 基于连通域字符分割的流程_基于连通域的版面分割研究
  8. 计算机比赛的评分办法,汉字录入比赛评分规则方案
  9. python3精要(54)-文件读写与异常处理
  10. C指针原理(44)-汇编基础