使用nodejs、Express和MongDB搭建个人博客

来源:互联网 发布:香港域名注册有限公司 编辑:程序博客网 时间:2024/05/17 04:57

nodejs是目前前端开发中会使用的服务端语言,Express是基于nodejs产生的Web开发框架,MongoDB是一个使用较广泛的非关系型数据库,以键值对的形式存储内容。因为对express和MongoDB都不算熟悉,所以为练习和基础入门,参考网上点击打开链接及自己摸索,实现个人博客搭建,分享如下。

整个过程主要分为以下几步:

  1. nodejs安装Express并生成空项目框架
  2. nodejs安装MongoDB
  3. 规划页面
  4. 分析路由及后端方法
  5. 建立数据库操作model

1.Nodejs安装Express及空项目框架

安装完nodejs之后,使用包管理工具安装express模块,命令为npm install -g express,安装完成后为查看express的版本,需要安装独立的express版本管理模块,使用命令npm install -g express-generator,最后使用express -V查看express的版本确认安装成功。
因为上面的安装里带有参数-g表明是全局安装,这时候进入node_global文件夹,就可以使用express命令创建新的app,命令如下:
$ express -e test
在创建的过程中,可能会有没有安装的模块,可以根据提示使用npm进行安装。

创建成功之后,进入项目根目录,命令:

node ./bin/www
默认端口为3000,打开浏览器访问localhost:3000就可以访问Express的index页面。

下面看一下test项目下的文件目录:



app.js是整个项目的引导文件,里面主要加载该项目用到的所有模块,同时持久化session,设置路由文件和基本的出错处理,最后将整个文件export出来。

package.json是项目的配置信息和依赖模块的配置信息,所有信息以键值对的形式定义。当需要新的模块的时候,都需要修改依赖包文件。

routes为项目的路由文件,主要存放请求的处理。public为公共文件夹,存放前台相关的JS,CSS和图片等一系列资源。node_modules为项目的依赖模块,包含所有在package.json里声明过的模块。models为操作数据库的文件,在后面会进行详细说明。

2.安装mongodb及nodejs的mongodb操作模块

直接下载mongodb的安装包,就可以在windows下安装,安装完成后,进入安装目录,新建一个文件夹,使用这个命令
mongod --dbpath=D:\mongodb\test
因为mongodb的默认端口是27017,可以通过本地访问localhost:27017直接确定数据库是否打开。
想要操作数据库的话,就重新打开一个命令行,然后输入mongo,可以操作数据库,常见操作见链接:mongodb常见命令

Nodejs里的mongodb主要是提供操作mongodb的方法的模块有两个

使用npm安装之后,在安装依赖模块的时候,建议先使用npm安装,安装完成后查看安装模块的版本,再把版本号写入package.json里,这样避免npm找不到你想要的版本的模块。

可以在项目的根目录下创建setting.js写入数据库的配置信息,也是以键值对的形式:

module.exports = {    db: 'test',    host: 'localhost',    port: 27017};
提醒一下,mongodb是默认可以进行CURD操作的,不需要用户名和密码,如果你自己需要就创建用户,具体操作不多说。

为了保证用户登录等的会话保持和写入持久层方便操作,引入express-session 和 connect-mongo 这两个第三方中间件,方便序列化操作session等会话信息,并保存在数据库中。

创建配置信息文件之后,在app.js里写入保存会话的代码,如下:

// session的持久化防止丢失app.use(session({  secret: settings.cookieSecret,  key: settings.db,//cookie name  cookie: {maxAge: 1000 * 60 * 60 * 24 * 30},//30 days  resave: false,  saveUninitialized: true,  store: new MongoStore({    url:('mongodb://localhost:27017/test'),})}));
注意,这里的存储路径写法如下,写入的是可以直接访问的路径。

3.规划页面

博客页面的功能主要包括首页,注册,登录,登出,发表博客和获取某个用户的发表过的文章。因为所有方法都需要有页面支持用户操作,所有方法都有get方法的获取,同时对于发布内容的例如注册、发表博客及登录功能,需要有post方法支持。

根据页面的布局,我们采用ejs作为模板文件,主要规划有header,footer,index,login,logout,reg和post这些页面,以index页面为例,文件如下:

<%- 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 %>

4.分析路由及后端方法

所有对请求的操作及路由,都需要放在路由文件夹下的index文件里,因为此处方法不多,可以直接写到一个js里。在app.js里,只需要引入router下的文件保证路由可用。

var routes = require('./routes/index');
app.use('/', routes);
在routes下的index.js里,需要写入所有的路由方法,具体如下:
var express = require('express');var router = express.Router();var crypto = require('crypto');var User = require('../models/user.js');var Post = require('../models/post.js')/* GET home page. */router.get('/', function(req, res, next) {    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()        });    });});router.get('/login',checkNotLogin);router.get('/login',function(req,res){    res.render('login', {        title: '登录',        user: req.session.user,        success: req.flash('success').toString(),        error: req.flash('error').toString()});});router.post('/login',checkNotLogin);router.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('/');//登陆成功后跳转到主页    });});router.post('/reg',checkNotLogin);router.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 (err) {            req.flash('error', err);            return res.redirect('/');        }        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 = newUser;//用户信息存入 session            req.flash('success', '注册成功!');            res.redirect('/');//注册成功后返回主页        });    });});router.get('/reg',checkNotLogin);router.get('/reg', function (req, res) {    res.render('reg', {        title: '注册',        user: req.session.user,        success: req.flash('success').toString(),        error: req.flash('error').toString()    });});router.get('/post',checkLogin);router.get('/post',function(req,res){    res.render('post',{        title:'发表',        user: req.session.user,        success: req.flash('success').toString(),        error: req.flash('error').toString()    });});router.post('/post',checkLogin);router.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('/');//发表成功跳转到主页    });});router.get('/logout',checkLogin);router.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();}module.exports = router;
在所有的方法中,都将session中的user输出至页面上,同时,在查询时将查询出的数据输出出去,在view文件夹下的对应模板文件里,可以直接使用
<%= name %>
的方法显示数据。同时,针对所有页面的权限,进行了权限检查,针对注册页面和登录界面,已经登录的用户不能查看,直接使用redirect重定向至首页,对于发布博客页面,未登录用户不能查看。

5. 数据库操作方法

在model文件夹下,是所有对数据库操作的文件。首先是db.js作为基础文件链接数据库,具体代码如下:
var settings = require('../setting.js'),    Db = require('mongodb').Db,    Connection = require('mongodb').Connection,    Server = require('mongodb').Server;module.exports = new Db(settings.db, new Server(settings.host, settings.port),    {safe: true});
这里以用户为例子,主要有创建用户和用户登录两个方法,具体代码如下:
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);//成功!返回查询的用户信息            });        });    });};





0 0
原创粉丝点击