热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Node.js博客实例(一)简单博客

原教程https:github.comnswbmwN-blogwiki_pages的第一章

原教程 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 ? &#39;0&#39; + 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(&#39;posts&#39;, 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(&#39;posts&#39;, 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(&#39;./db&#39;);

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(&#39;users&#39;, 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(&#39;users&#39;, 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(&#39;crypto&#39;),
    User = require(&#39;../models/user.js&#39;),
    Post=require(&#39;../models/post.js&#39;);

	
module.exports = function(app) {
    app.get(&#39;/&#39;, function (req, res) {
			Post.get(null, function (err, posts) {
    		if (err) {
     		 posts = [];
   			} 
    		res.render(&#39;index&#39;, {
     	 		title: &#39;主页&#39;,
      		user: req.session.user,
      		posts: posts,
      		success: req.flash(&#39;success&#39;).toString(),
      		error: req.flash(&#39;error&#39;).toString()
    		});
  		});
    });
	
	app.get(&#39;/reg&#39;, checkNotLogin);
    app.get(&#39;/reg&#39;, function (req, res) {
		res.render(&#39;reg&#39;, {
			title: &#39;注册&#39;,
			user: req.session.user,
			success: req.flash(&#39;success&#39;).toString(),
			error: req.flash(&#39;error&#39;).toString()
		});
    });
	
	app.post(&#39;/reg&#39;, checkNotLogin);
    app.post(&#39;/reg&#39;, function (req, res) {
		var name = req.body.name,
        password = req.body.password,
        password_re = req.body[&#39;password-repeat&#39;];
		//检验用户两次输入的密码是否一致
		if (password_re != password) {
			req.flash(&#39;error&#39;, &#39;两次输入的密码不一致!&#39;); 
			return res.redirect(&#39;/reg&#39;);//返回注册页
		}
		//生成密码的 md5 值
		var md5 = crypto.createHash(&#39;md5&#39;),
		password = md5.update(req.body.password).digest(&#39;hex&#39;);
		var newUser = new User({
			name: name,
			password: password,
			email: req.body.email
		});
		//检查用户名是否已经存在 
		User.get(newUser.name, function (err, user) {
			if (user) {
				req.flash(&#39;error&#39;, &#39;用户已存在!&#39;);
				return res.redirect(&#39;/reg&#39;);//返回注册页
			}
			//如果不存在则新增用户
			newUser.save(function (err, user) {
				if (err) {
					req.flash(&#39;error&#39;, err);
					return res.redirect(&#39;/reg&#39;);//注册失败返回主册页
				}
				req.session.user = user;//用户信息存入 session
				req.flash(&#39;success&#39;, &#39;注册成功!&#39;);
				res.redirect(&#39;/&#39;);//注册成功后返回主页
			});
		});
    });
	
    app.get(&#39;/login&#39;, checkNotLogin);
    app.get(&#39;/login&#39;, function (req, res) {
		res.render(&#39;login&#39;, {
        title: &#39;登录&#39;,
        user: req.session.user,
        success: req.flash(&#39;success&#39;).toString(),
        error: req.flash(&#39;error&#39;).toString()});
	});
	
	app.post(&#39;/login&#39;, checkNotLogin);
	app.post(&#39;/login&#39;, function (req, res) {
		//生成密码的 md5 值
		var md5 = crypto.createHash(&#39;md5&#39;),
		password = md5.update(req.body.password).digest(&#39;hex&#39;);
		//检查用户是否存在
		User.get(req.body.name, function (err, user) {
			if (!user) {
				req.flash(&#39;error&#39;, &#39;用户不存在!&#39;); 
				return res.redirect(&#39;/login&#39;);//用户不存在则跳转到登录页
			}
			//检查密码是否一致
			if (user.password != password) {
				req.flash(&#39;error&#39;, &#39;密码错误!&#39;); 
				return res.redirect(&#39;/login&#39;);//密码错误则跳转到登录页
			}
			//用户名密码都匹配后,将用户信息存入 session
			req.session.user = user;
			req.flash(&#39;success&#39;, &#39;登陆成功!&#39;);
			res.redirect(&#39;/&#39;);//登陆成功后跳转到主页
		});
	});
	
	app.get(&#39;/post&#39;, checkLogin);
	app.get(&#39;/post&#39;, function (req, res) {
		res.render(&#39;post&#39;, { 
			title: &#39;发表&#39; ,
			user: req.session.user,
			success: req.flash(&#39;success&#39;).toString(),
			error: req.flash(&#39;error&#39;).toString()});
		
		console.log("222");
	});
	
	app.post(&#39;/post&#39;, checkLogin);
	app.post(&#39;/post&#39;, 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(&#39;error&#39;, err); 
				return res.redirect(&#39;/&#39;);
			}
			req.flash(&#39;success&#39;, &#39;发布成功!&#39;);
			res.redirect(&#39;/&#39;);//发表成功跳转到主页
		});
	});
	
	app.get(&#39;/logout&#39;, checkLogin);
	app.get(&#39;/logout&#39;, function (req, res) {
		req.session.user = null;
		req.flash(&#39;success&#39;, &#39;登出成功!&#39;);
		res.redirect(&#39;/&#39;);//登出成功后跳转到主页
	});
	
	function checkLogin(req, res, next) {
		if (!req.session.user) {
			req.flash(&#39;error&#39;, &#39;未登录!&#39;); 
			res.redirect(&#39;/login&#39;);
		}
		next();
	}

	function checkNotLogin(req, res, next) {
		if (req.session.user) {
			req.flash(&#39;error&#39;, &#39;已登录!&#39;); 
			res.redirect(&#39;back&#39;);
		}
		next();
	}
};

blog/views/

blog/views/header.ejs






blog/views/footer.ejs



blog/views/index.ejs

<%- include header %>
<% posts.forEach(function (post, index) { %>
  

blog/views/reg.ejs

<%- include header %>

  用户名:  
密码:
确认密码:
邮箱:
<%- include footer %>

blog/views/login.ejs

<%- include header %>

  用户名:
密码:
<%- include footer %>

blog/views/post.ejs

<%- include header %>

  TITLE:

DETAIL:

<%- include footer %>


推荐阅读
  • 基于Node.js、Express、MongoDB和Socket.io的实时聊天应用开发
    本文详细介绍了使用Node.js、Express、MongoDB和Socket.io构建的实时聊天应用程序。涵盖项目结构、技术栈选择及关键依赖项的配置。 ... [详细]
  • 利用 Jest 和 Supertest 实现接口测试的全面指南
    本文深入探讨了如何使用 Jest 和 Supertest 进行接口测试,通过实际案例详细解析了测试环境的搭建、测试用例的编写以及异步测试的处理方法。 ... [详细]
  • Mongoose 5.12.10 发布:MongoDB 异步对象模型工具的新特性与修复
    Mongoose 是一款专为异步环境设计的 MongoDB 对象模型工具,支持 Promise 和回调函数。最新版本 Mongoose 5.12.10 带来了多项修复和改进,包括查询选项中的默认值设置、嵌入式判别器填充、以及 TypeScript 定义文件的优化。 ... [详细]
  • 本文探讨了Web开发与游戏开发之间的主要区别,旨在帮助开发者更好地理解两种开发领域的特性和需求。文章基于作者的实际经验和网络资料整理而成。 ... [详细]
  • 本文探讨了如何在Node.js环境中,通过Tor网络使用的SOCKS5代理执行HTTP请求。文中不仅提供了基础的实现方法,还介绍了几种常用的库和工具,帮助开发者解决遇到的问题。 ... [详细]
  • 了解如何快速搭建属于自己的个人博客,无需编程基础,适合Mac和Windows用户。通过本文,您将学会使用GitHub Pages和Hexo构建一个完全自主的在线空间。 ... [详细]
  • 扫描线三巨头 hdu1928hdu 1255  hdu 1542 [POJ 1151]
    学习链接:http:blog.csdn.netlwt36articledetails48908031学习扫描线主要学习的是一种扫描的思想,后期可以求解很 ... [详细]
  • This document outlines the recommended naming conventions for HTML attributes in Fast Components, focusing on readability and consistency with existing standards. ... [详细]
  • 在现代网络环境中,两台计算机之间的文件传输需求日益增长。传统的FTP和SSH方式虽然有效,但其配置复杂、步骤繁琐,难以满足快速且安全的传输需求。本文将介绍一种基于Go语言开发的新一代文件传输工具——Croc,它不仅简化了操作流程,还提供了强大的加密和跨平台支持。 ... [详细]
  • VSCode与Gitee集成:项目提交的高效实践
    本文介绍如何利用VSCode内置的Git工具将项目提交到Gitee,简化Git命令的使用,提升代码管理效率。同时分享一些常见的踩坑经验和解决方案。 ... [详细]
  • Composer Registry Manager:PHP的源切换管理工具
    本文介绍了一个用于Composer的源切换管理工具——Composer Registry Manager。该项目旨在简化Composer包源的管理和切换,避免与常见的CRM系统混淆,并提供了详细的安装和使用指南。 ... [详细]
  • 本文详细介绍了如何在 Windows 环境下使用 node-gyp 工具进行 Node.js 本地扩展的编译和配置,涵盖从环境搭建到代码实现的全过程。 ... [详细]
  • 本文介绍如何在PostgreSQL数据库中正确插入和处理JSON数据类型,确保数据完整性和避免常见错误。 ... [详细]
  • Node.js 中 GET 和 POST 请求的数据处理
    本文详细介绍了如何在 Node.js 中使用 GET 和 POST 方法来处理客户端发送的数据。通过示例代码展示了如何解析 URL 参数和表单数据,并提供了完整的实现步骤。 ... [详细]
  • 本文深入探讨了 Prototype.js 框架及其与 JavaScript 原生 toString() 方法之间的区别,适合对前端开发感兴趣的开发者阅读。文章将帮助读者理解两者在功能实现和应用场景上的不同,从而更好地利用这些工具进行高效编程。 ... [详细]
author-avatar
大眼睁睁
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有