Nodejs+express+mongodb+mongoose实现个人博客

周作人
2023-12-01

1.技术框架介绍

  • NodeJS   版本v6.9.5  基础核心开发语言
  • Express  一个简洁而灵活的 node.js Web应用框架, 提供了一系列强大特性帮助你创建各种 Web 应用,和丰富的 HTTP 工具。
  • Mongodb 版本v4.9.6
  • 第三方模块 & 中间插件
       bodyParser:解析post请求数据
       cookies:读/写cookie
       swig:模板解析引擎
       mono goose:操作mongodb数据
       markdown:markdown语法解析生成模块

2.安装模块

   npm install
   npm init  初始化完成后生成package.json文件
   npm install --save express 安装完成后package.json中dependencies中多对应的版本号
将所用到的模块都安装好。注:安装过程要联网

3.项目目录结构

 

4.app.js

 

5.模板引擎的配置和使用

在后端中写前端的内容对于后期的维护不好,如
res.send('<h1>Welcom to my Blog</h2>');

所以,将界面和逻辑分开

注册这一步其实就是将定义好的模板引擎配置到app中
  •   5.1.加载模板
  •   5.2.配置应用模板
还可以传递第二个参数,传递给模板使用的数据
在views里面新建index.html
 
原理:app应用在读取模板的时候第一次读取模板文件(index.html)以后并且把它解析后保存在内存中,下一次再次访问的时候,同样的路径解析同样的模板就不会在文件当中读取解析的,而是从已经存在于内存当中的数据中直接读取然后返回。所以重启应用。但是在实际工作中,常常会不断的修改模板,那么就需要不断的重启服务,很麻烦。
 
在开发过程中,需要取消模板缓存
//在开发过程中需要取消模板缓存
swig.setDefaults({cache: false});

这样,每次就不需要重新去运行app.js,而是保存模板文件即可。

6.静态文件托管
写模板文件的时候经常会引入外部文件,如图片,css等。
那么头部需要去解析css文件。同时,在后端(app.js)中要写css
 
但是如果有多个css的话就会写很多get请求,很麻烦。
我们要请求的css和js是静态文件,不需要用这种动态的方法,只需要在后端获取,然后向前端发送。
当用户访问的url以/public开始,那么直接返回对应__dirname+'/public'下的文件
梳理一下这个过程: 用户发送http请求->url->解析路由->找到匹配的规则->执行指定的绑定函数,返回对应内容至用户
 
在public中新建main.css文件
 
// app.js

/**
* Created by xiaofeng on 2017/5/1 0001.
*/

/*
* 应用程序的启动(入口)文件
* */

// 加载express模板
var express=require('express');
//创建app应用 => NodeJS Http.createServer();
var app=express();
// 加载模板引擎
var swig=require('swig');
// 设置静态文件托管
// 当用户访问的url以/public开始,那么直接返回对应_dirname+'/public'下的文件
app.use('/public',express.static(__dirname+'/public'));

/*
* 处理请求输出
* */

/*
* 首页
* req request对象
* res  response对象
* next函数
* */
// app.get('/',function (req,res,next) {
//    // res.send('<h1>欢迎来到我的Blog,这是通过NodeJS搭建的</h1>');
// });
/*
* 配置应用模板
* 定义当前应用所使用的模板引擎
* 第一个参数:模板名称,也是文件后缀名,第二个参数用于解析处理模板的内容的方法
* */
app.engine('html',swig.renderFile);
// 设置模板文件存放的目录,第一个参数必须是views,第二个参数是目录
app.set('views','./views');
// 注册所使用的模板引擎,第一个参数必须的view engine,第二个参数必须和app.engine这个方法中定义的模板名称一致
app.set('view engine','html');
swig.setDefaults({cache:false});
app.get('/',function (req,res,next) {
    res.render('index');
});
// 比较麻烦
// app.get('/main.css',function (req,res,next) {
//    res.setHeader('content-type','text/css');
//    res.send("h1 {text-align:center;}");
// });
// 监听端口 http请求
app.listen(8081);

7.分模块开发与实现

比如: 在router/admin.js
 
访问 localhost:8081/admin/user
注意:如果现在只是测试,访问admin.js,那么就要将
app.use('/api',require('./routers/api'));
app.use('/',require('./routers/main'));
进行注释,否则会报错。
 
如果不写这一句,也会报错
module.exports=router;
 
模块划分
在schema文件夹中新建users.js文件。
连接数据库之前在app.js中加载数据库
var mongoose=require('mongoose');
然后使用mongoose中的connect方法连接数据库。当然,在连接数据库之前要开启数据库。开启数据库先进行数据库的安装。

8.数据库连接、表结构Schema定义、Model创建

mongoose模块进行数据库操作
在官网下载mongodb并且安装;
安装好后找到MongoDB->Server->3.4->bin,有客户端,服务端。通过命令行启动服务端。mongod.exe
 
等待连接
 
我们可以通过命令行的方式连接。也可以通过可视化界面连接,如Robomongo
 
点击“connect”。连接成功后,
 
接下来是app.js连接数据库
 
 
在schemas中新建users.js文件,定义用户的表结构通过Schema方法,仅仅定义表结构不够,需要模型类对数据进行增删改查等操作。在models中新建User.js创建模型类
var mongoose=require('mongoose');
var userSchema=require('../schemas/users');
//创建模型类
module.exports = mongoose.model('User',userSchema );

9.用户注册前端页面逻辑

将静态页面拷贝到Blog相应的文件夹中。
编辑index.js的内容
注册面板中的“注册”按钮是通过ajax实现的,
// index.js

$(function () {
    var $loginBox=$('#loginBox');
    var $registerBox=$('#registerBox');

    //切换到注册面板
    $loginBox.find('a').on('click',function () {
        $registerBox.show();
        $loginBox.hide();
    });
    $registerBox.find('a').on('click',function () {
        $loginBox.show();
        $registerBox.hide();
    });
    //注册,通过ajax实现
    $registerBox.find('button').on('click',function () {
        //通过ajax提交数据
        $.ajax({
            type: 'post',
            url: '/api/user/register',
            data: {
                username: $registerBox.find('[name="username"]').val(),
                password: $registerBox.find('[name="password"]').val(),
                repassword: $registerBox.find('[name="repassword"]').val()
            },
            dataType: 'json',
            success: function (result) {
                console.log(result);
            }
        });
    });
})

10.body-parser模块的使用和后端用户名注册的基本验证

测试一下,在api.js中作出修改
// app.js

var express=require('express');
var router=express.Router();

/*
* 用户注册
* 这里router(路由)使用的方法要和index中ajax type属性一致,否则会报错
* */
router.post('/user/register',function (req,res,next) {
    res.send('register');
    console.log('register');
});
module.exports=router;

接下来需要获取前端提交过来的post数据,如何获取?

需要用到一个第三方模块body-parser,用来处理post提交过来的数据
app.js
 
// app.js

/*
* 应用程序的启动(入口)文件
* */

//加载express模板
var express=require('express');
//加载模板引擎
var swig=require('swig');
//加载数据库
var mongoose=require('mongoose');
//加载body-parser解析post数据
var bodyParser=require('body-parser');
//创建app应用 => NodeJS Http.createServer();
var app=express();
//设置静态文件托管
//当用户访问的url以/public开始,那么直接返回对应_dirname+'/public'下的文件
app.use('/public',express.static(__dirname+'/public'));

/*
* 配置应用模板
* 定义当前应用所使用的模板引擎
* 第一个参数:模板名称,也是文件后缀名,第二个参数用于解析处理模板的内容的方法
* */
app.engine('html',swig.renderFile);
//设置模板文件存放的目录,第一个参数必须是views,第二个参数是目录
app.set('views','./views');
//注册所使用的模板引擎,第一个参数必须的view engine,第二个参数必须和app.engine这个方法中定义的模板名称一致
app.set('view engine','html');
swig.setDefaults({cache:false});

//body-parser设置
app.use(bodyParser.urlencoded({extended:true}));

app.use('/admin',require('./routers/admin'));
app.use('/api',require('./routers/api'));
app.use('/',require('./routers/main'));

//监听端口 http请求
mongoose.connect('mongodb://localhost:27017/blog',function (err) {
    if (err){
        console.log('数据库连接失败');
    }else {
        console.log('数据库连接成功');
        app.listen(8081);
    }
});
api.js
var express=require('express');
var router=express.Router();

/*
* 用户注册
* 这里router(路由)使用的方法要和index中ajax type属性一致,否则会报错
* */
router.post('/user/register',function (req,res,next) {
    //res.send('register');
    console.log(req.body);
});
module.exports=router;

点击“注册”后,

用户注册: 注册逻辑的简单实现
var express = require('express');
var router = express.Router();

//统一返回格式
var responseData;
router.use(function (req,res,next) {
    responseData = {
        code: 0,
        message: ''
    }
    next();
});
/*
* 用户注册
*  注册逻辑:对字符进行验证,并且返回给前端
*  1.用户名不能为空
*  2.密码不能为空
*  3.两次输入的密码必须一致
*
*  1.用户已经被注册
*      数据库中进行查询
*
* 这里router(路由)使用的方法要和index中ajax type属性一致,否则会报错
*
* */
router.post('/user/register', function (req, res, next) {
    var username = req.body.username;
    var password = req.body.password;
    var repassword = req.body.repassword;
    //用户名是否为空
    if (username == '') {
        responseData.code = 1;
        responseData.message = "用户名不能为空";
        res.json(responseData);
        return;
    }
    //密码不能为空
    if (password == '') {
        responseData.code = 2;
        responseData.message = "密码不能为空";
        res.json(responseData);
        return;
    }
    if (password != repassword) {
        responseData.code = 3;
        responseData.message = "两次输入密码不一致";
        res.json(responseData);
        return;
    }
    responseData.message="注册成功";
    res.json(responseData);
});
module.exports = router;

 

 
重启app.js进行测试
 
 
 
 类似资料: