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

2021/3/15 Nodekoa2

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

# 一、安装Koa

  • npm install koa-generator -g
  • koa2 blog-koa2
  • cd blog-koa2
  • npm install
  • npm i cross-env --save-dev 在这里插入图片描述
  • 启动项目npm run dev 在这里插入图片描述
  • 代码复用 在这里插入图片描述

# 二、登录验证

  • 下载插件 koa-generic-session、koa-redis、redis npm i koa-generic-session koa-redis redis --save
  • 配置环境(app.js)
const session = require('koa-generic-session')
const redisStore = require('koa-redis')
const REDIS_CONF = require('./conf/db')
//session 与  redis
app.keys = ['dfhQWE_123#df']
app.use(session({
  //配置cookie
  cookie:{
    path:"/",
    httpOnly:true,
    maxAge:24 * 60 * 60 * 1000
  },
  //配置redis
  store: redisStore({
    all:`${REDIS_CONF.host}:${REDIS_CONF.port}`
  })
}))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  • 中间键
const {ErrorModel} = require('../model/resModel')

module.exports = async (ctx, next) => {
    if (ctx.session.username) {
        await next()
        return 
    }
    ctx.body = new ErrorModel('尚未登陆') 
}
1
2
3
4
5
6
7
8
9

# 三、修改 controller 层代码

  • 获取博客列表
const getList = async (author, keyword) => {
    let sql = `select * from blogs where 1=1 `
    if (author) {
        author = escape(author)
        sql += ` and author = ${author} `
    }
    if (keyword) {
        keyword = escape(keyword)
        sql += ` and title like %${keyword}%`
    }
    sql += 'order by createtime desc; '

    return await exec(sql)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  • 获取博客详细内容
const getDetail = async (id) => {
    id = escape(id)
    let sql = `select content,title,author,id from blogs where id = ${id}`
    const rows = await exec(sql)
    return rows[0]
}
1
2
3
4
5
6
  • 更新博客
const updateBlog = async (id, blogData = {}) => {
    const content = escape(xss(blogData.content))
    const title = escape(xss(blogData.title))
    id = escape(xss(id))
    let sql = `update blogs set title=${title}, content=${content} where id=${id}`
    const updateData = await exec(sql)
    if (updateData.affectedRows > 0) {
        return true
    }
    return false
}
1
2
3
4
5
6
7
8
9
10
11
  • 删除博客
const delBlog = async (id, author) => {
    id = escape(xss(id))
    author = escape(xss(author))
    let sql = `delete from blogs where id=${id} and author=${author};`
    const delData = exec(sql)
    if (delData.affectedRows > 0) {
        return true
    }
    return false
}
1
2
3
4
5
6
7
8
9
10
  • 增加博客
const newBlog = async (blogData = {}) => {
    const title = escape(xss(blogData.title))
    const content = escape(xss(blogData.content))
    const author = escape(xss(blogData.author))
    const createTime = Date.now()
    const sql = `insert into blogs (title, content, createtime, author)
                values (${title}, ${content}, ${createTime}, ${author})`
    const insertData = await exec(sql)
    return {
        id: insertData.insertId
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
  • 用户登录
const {exec,escape} = require('../db/mysql')
const xss = require('xss')
const login = async(username,paasword) => {
    username = escape(xss(username))
    paasword = escape(xss(paasword))
    let sql = `select username, realname from users where username=${username} and password=${password}`
    const row = await exec(sql)
    return row[0] || {}
}
1
2
3
4
5
6
7
8
9

# 四、router 层

  • 查看博客列表
router.get('/list', async (ctx, next) => {
    let author = ctx.query.author || ''
    const keyword = ctx.query.keyword || ''
    if (ctx.query.isadmin) {
        if (ctx.session.username == null) {
            ctx.body = new ErrorModel('尚未登录')
        }
        author = ctx.session.username
    }
    const listData = await getList(author, keyword)
    ctx.body = new SuccessModel(listData)
})
1
2
3
4
5
6
7
8
9
10
11
12
  • 查看博客详细信息
router.get('/detail', async (ctx, next) => {
    const { id } = ctx.query
    const detail = await getDetail(id)
    ctx.body = new SuccessModel(detail)
})
1
2
3
4
5
  • 增加博客
const loginCheck = require('../middleware/loginCheck')
router.post('/new', loginCheck, async (ctx, next) => {
    ctx.request.body.author = ctx.session.username
    const id = await newBlog(ctx.request.body)
    if (id > 0) {
        ctx.body = new SuccessModel()
        return
    } else {
        ctx.body = new ErrorModel('增加博客失败')
    }
})
1
2
3
4
5
6
7
8
9
10
11
  • 删除博客
const loginCheck = require('../middleware/loginCheck')
router.post('/del', loginCheck, async (ctx, next) => {
    const { id } = ctx.query
    const author = ctx.session.username
    const val = await delBlog(id, author)
    if (val) {
        ctx.body = new SuccessModel()
        return
    } else {
        ctx.body = new ErrorModel('删除博客失败')
    } 

})
1
2
3
4
5
6
7
8
9
10
11
12
13
  • 更新博客
const loginCheck = require('../middleware/loginCheck')
router.post('/update', loginCheck, async (ctx, next) => {
    const { id } = ctx.query
    ctx.request.body.author = ctx.session.username
    const val = await updateBlog(id, ctx.request.body)
    if (val) {
        ctx.body = new SuccessModel()
        return
    } else {
        ctx.body = new ErrorModel('更新博客失败')
    }
})
1
2
3
4
5
6
7
8
9
10
11
12
  • 用户登录
router.post('/login', async(ctx, next) => {
   //获取请求数据
   const {username, password} = ctx.request.body
   const data = await login(username,password)
   if (data.username) {
      ctx.session.username = data.username
      ctx.session.realname = data.realname

      ctx.body= new SuccessModel()
      return
   }
   ctx.body = new ErrorModel('登录失败')
})
1
2
3
4
5
6
7
8
9
10
11
12
13

# 五、接口测试

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

  • 查看博客详细内容

在这里插入图片描述


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

  • 增加博客 在这里插入图片描述

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

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

  • 未登录进行博客操作

在这里插入图片描述


# 六、使用 morgan 写日志

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

在这里插入图片描述

使用express重构博客项目 (opens new window)

源码下载 (opens new window)