用Nodejs完成自己的个人博客

开始这个个人小项目已经有一段时间了,一直断断续续的,直到今天总算是初见雏形,所以就很想和大家分享一下实现的过程。首先这个的初衷就是学习nodejs,看了几天的书,自己就照着书上的代码来敲,可是由于自己安装的node是最新版,然而书比较旧,好多都不能正确运行,我想了解node的都知道它几乎每天都在更新,出现这样的情况也是必然的。所以想了下,还是在github上找个别人的项目拿来练练手,看一下项目是如何搭建的,经过仔细的琢磨总算是慢慢搭起来了。下来讲一下自己是如何实现的。


一. 项目所用到的技术

express框架:

(1)可以设置中间件来响应 HTTP 请求;
(2)定义路由表用于执行不同的 HTTP 请求动作;

ejs模板

用过Java的jsp的就知道,这和jsp的作用完全相同,动态生成html元素。

mongodb数据库

>
这和熟悉的mysql数据库不同,mysql是关系型数据库,没一个表的每一项时一条记录,而mongodb是集合类型的,每个集合里存储的是对象,想象一下json,就明白mongodb里存储的数据类型。

mongoose数据库操作

这个是针对mongodb的数据库驱动,里面封装了对数据库的各种基本操作。

二. 项目目录

这里写图片描述

下面介绍下,每个目录都是干什么的:
(1)node_modules:存放各种node插件和express框架;
(2)schemas:在这个文件里用mongoose封装的对象来指定,数据库里要存储的数据结构。
如下,这是一个user的数据集合里面存储的数据项的结构:

> schemas/user.js

var Schema = require('mongoose').Schema;

var userSchema = new Schema({
    name: String,
    password: String,
    icon: String,
    sex: String,
    tel: String,
    qq: String,
    weixin: String,
    weibo: String,
    email: String
});

module.exports = userSchema;

(3)models:此文件夹下的每一个js文件都映射一个对应的schemas里的文件,然后将类型暴露出去,就可以让外界进行各种数据库操做了。

> models/user.js

var mongoose = require('mongoose');
var User = require('../schemas/user');

module.exports = mongoose.model('User', User);

(3)routes:看见名字就知道这个里面是对路由的各种操作,相当于Java里面的servlet要做的事情,进行页面的跳转和数据的传送。下面看routes的目录:
这里写图片描述

在这个文件夹下,index.js是最重要的,里面是所有路由的接口,其他的都是每个路由跳转所要执行的操作。下面的代码是index.js里的部分内容:

> routes/index.js

var login = require('./login');
var blog = require('./blog');
module.exports = function (app){
    app.get('/bloglist', blog.getAllBlog);  //跳到文章列表页

    app.get('/home', function (req, res){  //跳到首页
        res.render('index', {
            title: '小静博客——首页',
        });
    });
};

app.post('/doLogin', login.checkLogin); //验证登录信息

可以看到我们传入了app参数,这个是express实例化的对象,所有http的get和post请求都是用app对象来完成的。
(4)static:里面存放的是所有静态资源,比如js,css还有图片等文件。
(5)views:里面存的是所有的html页面。
(6)app.js:这个无疑是express框架中最重要的了,是等个项目的入口文件,在这个项目中只有该文件的生命周期是直到关闭服务器,所以可见它的重要性。在这个文件中需要引入所要使用的:

  • 各种中间件:用于设置session和cookie的express-session和cookie-parser,还有body-parser,用于处理
    JSON和application/x-www-form-urlencoded 编码的数据。

  • 驱动程序包:mongodb的驱动包mongoose;

  • 页面的模板引擎:ejs;

连接并启动数据库,监听端口等都在这个入口文件中。如下代码所示:

> app.js

var express = require('express');
var ejs = require('ejs');
var bodyParser = require('body-parser');
var session = require('express-session');
var cookieParser = require('cookie-parser');
var mongoose = require('mongoose');

//将路由文件引入
var route = require('./routes/index');

//设置端口
var port = process.env.PORT || 3000;

var app = express();

//设置试图的根目录
app.set('views', './views/pages');

//设置试图的模板引擎
app.engine('.html', ejs.__express);
app.set('view engine', 'html'); 

//设置静态资源路径
app.use(express.static('./static'));  

// 解析 application/x-www-form-urlencoded 
app.use(bodyParser.urlencoded({ extended: false })); 
// 解析 application/json 
app.use(bodyParser.json()); 

//设置session和cookie
app.use(cookieParser());
app.use(session({
secret: '12345',
    name: 'testapp',
    resave: false,
    saveUninitialized: true,
}));

//监听端口 
app.listen(port);

console.log("Server is runnng on " + port);

//连接mongodb数据库
mongoose.Promise = global.Promise;  //不加这句会报错
mongoose.connect('mongodb://127.0.0.1/myblog'); 
mongoose.connection.on('open', function (){
    console.log('Connected to Mongoose');
});

route(app);  //初始化所有路由

三. 项目的难点

写这个项目最大的感受就是,node是异步的,和之前一直使用的java有很大区别,很容易出错,可是node页提供了很强大的机制, Promise
,他让所有的异步操作看起来更像是顺序的,也让代码变得可读性更强了。下面是获得某条博客信息的具体代码,来看看Promise的魅力:

//获得某条博客的信息,并更新浏览次数
exports.getBlog = function (req, res){
    var blogid = req.params.id;
    var error = '';
    var user = req.session.user || null;
    Blog.findOne({_id: blogid}, function (err, blog){
        if (blog == null){
            error = '该文章被主人删除!';
            res.render({
                error: error
            });
        }else{

            //更新文章阅读次数
            var promise1 = updateLook_num(blogid);
            //查找文章作者的信息
            var promise2 = findUser(blog.authorid);
            //查找该博客的所有评论信息
            var promise3 = findReview(blogid);
            //查看未读消息总数
            var promise4 = message.totalUnreadMess(blog.authorid);

            Promise.all([promise1, promise2, promise3, promise4]).then(function (result){
                res.render('blogdetail', {
                    title: blog.title,
                    error: error,
                    blog: blog,
                    user: user,
                    author: result[1],
                    reviewlist: result[2],
                    totalmess: result[3],
                }); 
            }).catch(function (err){
                console.log(err);
            });
        }   
    });
}

上面的每个promise对象都代表了一个异步操作,如果不适用Promise就会陷入代码嵌套的无底洞,那将会是灾难,可以有了Promise将每个异步操作都分开书写,然后在用all方法去执行,代码就很容易理解,可读性和可维护性都会大大提高。

四. 截图
附上自己的最终截图吧:

博客列表页
这里写图片描述

文章详情页

这里写图片描述

这里写图片描述

评论消息提醒页

这里写图片描述


在这篇博客中,我并没有多说代码如何编写,而是主要说了项目的架构,我想对大多数人来说明白项目的架构,就会有个整体的概念,心里就会有个模板,至于代码的具体实现就看自己的js功底了。

代码已上传至github: https://github.com/SpiritLiftedHigh/myblog
欢迎fork and star.

-------------本文结束感谢您的阅读-------------