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 %>
时间: 2024-10-17 09:32:40

Node.js 一个简单的博客实例的相关文章

基于Node.js的ghost开源博客平台

Ghost 是一套基于Node.js 构建的开源博客平台(Open source blogging platform),具有易用的书写界面和体验. 1.安装node windows 下安装npm:http://blog.csdn.net/yczz/article/details/6938260 第一步: 下载node.js的windows版当前最新版本是http://nodejs.org/dist/v0.5.10/node.exe 第二步:设置环境变量把node.exe所在目录加入到PATH环境

Ubuntu14.04LTS下安装Node.js&amp;NPM以及个人博客hexo的初始化配置

什么是hexo Hexo 是一款基于node 的静态博客网站生成器作者 :tommy351是一个台湾的在校大学生...相比其他的静态网页生成器而言有着,生成静态网页最快,插件丰富(已经移植了大量Octopress插件).同其他很多轻量级博客如jekyll.octopress.jekyllbootstrap等一样,也是 使用Markdown语法进行编辑博文,关于Markdown不用怕,推荐搜索维基上面的语法示例,有中文版本http://zh.wikipedia.org/wiki/Markdown,

用Node.JS+MongoDB搭建个人博客(万众期待的router.js)(四)

万众期待的router.js,是我现在最想写的一个博客.因为他包含了整个个人博客的精髓.在这里,所有的请求配置,返回的参数等等所做的业务逻辑都在这个文件里实现. 我会详细说明这些代码的作用,所以这篇博客会有点长,但看完之后受益肯定也不少! 第一部分:引用文件 formidable是一个很出名的NPM包.它在node里作为表单内容接收做处理的一个中间件,功能很强大. db.js是我在网上仿写的一个对数据库的统一操作的函数库. md5是用于数据加密的文件(现在反对用md5加密,因为可以被破解)推荐用

设计node.js搭建多人博客的思路(不讲数据库)

1.1.4:搭建多人博客 1.功能分析 搭建一个简单的多人注册,登录,发表文章及登出功能的博客 2.设计目标 未登录:主页左侧导航显示home.login.register,右侧显示已发表文章,发表日期及作者 登陆后:主页左侧导航显示home.post.logout,右侧显示已发表文章,发表日期及作者 用户登录.注册.发表成功后 以及登出后都返回到主页 (1)未登录 主页 登录页 注册页 (2)登录后 主页 发表页 注意:没有登出页,点击logout后,退出登录并返回首页 3.路由规划 既然把设

node.js + webstorm 开发个人博客:配置开发环境

一.配置开发环境: 1.先安装node (1).访问http://nodejs.org打开安装包,正常安装,点击next即可. 为了测试是否安装成功,打开命令提示符,输入node,则进入node.js交互模式,如图: 通过这种方式安装node.js还自动附带了npm (2).安装node.js包管理器(Express) 新开一个命令行窗口 在命令行输入 npm install -g express Express 目录结构 t-1 目录/文件 说明 ./  根目录,我们的node.js代码都会方

【我的笔记BLOG1】配置webstorm + node.js +express + mongodb开发博客的环境

1. 安装webstorm 并破解 2. 安装node (以及express框架) 至官网下载并安装.(http://nodejs.org)v0.10.32   msi 安装后测试,打开命令行, c:\users\Iris804>  node >console.log("hello") 输出 hello undefined 安装node.js 包管理器(Express) ctrl+d, 回到初始窗口,输入  npm install -g express-gengerator

用Node.JS+MongoDB搭建个人博客(安装环境)(一)

Node.JS是什么? Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境. Node.js 使用了一个事件驱动.非阻塞式 I/O 的模型,使其轻量又高效. Node.js是由C++开发的,其实是一个JS运行环境,可以让JavaScript运行在服务器上. 安装环境 安装Node.JS和NPM 首先进入NodeJS官网选择自己对应的系统下载最新版,我现在用的是window64位系统,所以选择了window64位版的msi文件.下载完成后安装 安装成功后检查是否

用Node.JS+MongoDB搭建个人博客(model目录)(三)

model目录主要是封装一些经常使用的方法,便于使用. setting.js文件: 很简单,就单单封装了一个url作为公用,以后改就方便改了. md5.js(不推荐用): db.js文件: db.js文件主要是封装一些对数据库的连接操作,要不然都写在router.js上会造成非常大的代码冗余而且代码都一样. 对数据库操作,第一步当然是连接数据库: __connectDB作为一个内部函数,方便被引用. 然后用MongoClient.connect所提供的方法连接数据库,connect接收两个参数(

使用node+mongodb搭建简单个人博客——第一章遇到的问题

问题一: express-session deprecated undefined resave option; provide resave option app.js:39:9express-session deprecated undefined saveUninitialized option; provide saveUninitialized option app.js:39:9