【Node】:使用 express 重构博客项目

2021/3/15 Nodeexpress

不使用框架完成博客项目(原生nodejs) (opens new window)

# 一、安装 express

  • npm install express-generator -g --registry=https://registry.npm.taobao.org
  • express express-test
  • cd express-test
  • npm install --registry=https://registry.npm.taobao.org 在这里插入图片描述
  • npm start (启动项目)
  • 访问 localhost:3000 (bin/www.js) 在这里插入图片描述

在这里插入图片描述

# 二、express的入口文件


var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');

//路由文件
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');

var app = express();

//view engine setup (前端文件 html,css,js)
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

//打印日志
app.use(logger('dev'));

//解析请求数据
app.use(express.json());
app.use(express.urlencoded({ extended: false }));

//解析cookie
app.use(cookieParser());

//加载静态文件
app.use(express.static(path.join(__dirname, 'public')));

//父路由
app.use('/', indexRouter);
app.use('/users', usersRouter);


// 路由不存在是,返回404及对应的404页面
app.use(function(req, res, next) {
  next(createError(404));
});

// error handler 程序有问题的化会进行处理
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'dev' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

# 三、express 处理路由

//get请求
router.get('/list', function(req, res, next) {
    //返回数据
  res.json({
      error:0,
      data:[1,2,3]
  })
});

//post请求
router.post('/login', function (req, res, next) {
    //获取post数据
    const { username, password } = req.body
    res.json({
        error: 0,
        data: {
            username,
            password
        }
    })
})

//app.js
const blogRouter = require('./routes/blog')
const userRouter = require('./routes/user')
app.use('/api/user',userRouter)
app.use('/api/blog',blogRouter)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

在这里插入图片描述

# 四、express 中间件

//模拟登录验证
function loginCheck(req, res, next) {
  console.log('进行登录验证')
  //登录成功
  next()
  //登陆失败 不执行next()
  res.json({
       error:-1,
       msg:"没有进行登录"
      })
}

app.use('/api/blog/del', loginCheck, (req, res, next) => {
       res.json({
           error:0,
           msg:"删除博客成功"
       })
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

中间件的好处就是在于:

  • 所有路由中一旦有部分业务逻辑(比如验证是否登录成功)有交叉,就可以通过中间进行处理。
  • 而next()的作用是:一旦这部分业务逻辑满足条件(比如登录成功),就执行下一部分路由(比如删除博客内容),反之在中间件就返回提示信息,不会进入到下一步操作。

# 五、初始化环境

  • 安装插件mysql xss(npm install mysql xss --save)
  • mysql contriller resModel 相关代码可以复用 在这里插入图片描述

# 六、登录验证

  • 使用express-session 和 connect-redis ,简单方便
插件 命令
express-session npm i express-session --save
connect-redis redis npm i redis connect-redis --save
  • req.session保存登录信息,登录校验做成 express 中间件

  • 注册express-session 和 connect-redis中间件

//app.js
const session = require('express-session')
const RedisStore = require('connect-redis')(session)
const redisClient = require('./db/redis')

const sessionStore = new RedisStore({
  client:redisClient
})

app.use(session({
  secret:'WSDfre1234#_12',//密匙
  cookie:{
  //path:'/',//默认配置
  //httpOnly:true,//默认配置
  maxAge:24 * 60 * 60 * 1000
  },
   store:sessionStore;//自动将信息存放到 redis 中
}))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

注意: (1)此时,router层不用手动的去将 session 信息存放到 redis 中,也不用手动去 redis 中取出来存放到 session。 (2)redis.js文件只需要编写连接 redis 的方法即可。 在这里插入图片描述 在这里插入图片描述

  • 登录验证中间件
const {ErrorModel} = require('../model/resModel')

module.exports = (req, res,next) => {
    if (req.session.username) {
        next()
        return
    }
    res.json(
        new ErrorModel('尚未登录')
    )
}
1
2
3
4
5
6
7
8
9
10
11

# 七、初始化路由

const loginCheck = require('../middleware/loginCheck')

//获取博客列表
router.get('/list', (req, res, next) => {
   const { author, keyword } = req.query
   //管理员界面
   if (req.query.isadmin) {
      if (req.session.username == null) {
         res.json(
            new ErrorModel('未登录')
         )
         return
      }
   }
   //强制查询自己的博客
   author = req.session.username
   const result = getList(author, keyword)
   return result.then(listData => {
      res.json(
         new SuccessModel(listData)
      )
   })
});

//获取博客详情
router.get('/detail', (req, res, next) => {
   const { id } = req.query
   const result = getDetail(id)
   return result.then(detail => {
      res.json(
         new SuccessModel(detail)
      )
   })
})

//删除博客
router.post('/del', loginCheck, (req, res, next) => {
   const { id } = req.query
   const author = req.session.username
   const result = delBlog(id, author)
   return result.then(val => {
      if (val) {
         res.json(
            new SuccessModel()
         )
         return
      } else {
         res.json(
            new ErrorModel('删除博客失败')
         )
      }
   })
})

//更新博客
router.post('/update', loginCheck, (req, res, next) => {
   const { id } = req.query
   const postData = req.body
   const result = updateBlog(id, postData)
   return result.then(data => {
      if (val) {
         res.json(
            new SuccessModel()
         )
         return
      } else {
         res.json(
            new ErrorModel('更新博客失败')
         )
      }
   })
})

//增加博客
router.post('/new', loginCheck, (req, res, next) => {
   req.body.author = req.session.username
   const result = newBlog(req.body)
   return result.then(id => {
         res.json(
            new SuccessModel()
         )
         return
   })
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84

# 八、测试功能是否调通

  • 获取博客详细内容 在这里插入图片描述

  • 查看博客列表 在这里插入图片描述

  • 用户登录 在这里插入图片描述

  • 更新博客 在这里插入图片描述

  • 删除博客 在这里插入图片描述

  • 增加博客

在这里插入图片描述


  • 未登录对博客进行操作 在这里插入图片描述

# 九、使用 morgan 写日志

const ENV = process.env.NODE_ENV
if (ENV !== 'production') {
  app.use(logger(dev),{
    stream:process.stdout //打印到控制台 (默认)
  })
} else {
  //线上环境
  const logfileName = path.join(__dirname, "logs","access.log")
  const writeStream = fs.createWriteStream(logfileName, {
    flags:'a'
  })
  app.use(logger('combined',{
    stream:writeStream
  }))
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

在这里插入图片描述