【Node.js实战】一文带你开发博客项目之Koa2重构(实现session、开发路由、联调、日志)

03-27 1850阅读

个人简介

👀个人主页: 前端杂货铺

🙋‍♂️学习方向: 主攻前端方向,也会涉及到服务端

📃个人状态: 在校大学生一枚,已拿多个前端 offer(秋招)

🚀未来打算: 为中国的工业软件事业效力n年

🥇推荐学习:🍍前端面试宝典 🍉Vue2 🍋Vue3 🍓Vue2&Vue3项目实战 🥝Node.js🍒Three.js

🌕个人推广:每篇文章最下方都有加入方式,旨在交流学习&资源分享,快加入进来吧

Node.js系列文章目录

内容参考链接
Node.js(一)初识 Node.js
Node.js(二)Node.js——开发博客项目之接口
Node.js(三)Node.js——一文带你开发博客项目(使用假数据处理)
Node.js(四)Node.js——开发博客项目之MySQL基础
Node.js(五)Node.js——开发博客项目之API对接MySQL
Node.js(六)Node.js——开发博客项目之登录(前置知识)
Node.js(七)Node.js——开发博客项目之登录(对接完毕)
Node.js(八)Node.js——开发开发博客项目之联调
Node.js(九)Node.js——开发博客项目之日志
Node.js(十)Node.js——开发博客项目之安全
Node.js(十 一)Node.js——开发博客项目之初识 Express
Node.js(十二)Node.js——开发博客项目之 Express 重构

文章目录

  • Node.js系列文章目录
    • 一、前言
    • 二、实现 session
    • 三、开发路由
      • 1、安装 mysql 和 xss
      • 2、代码迁移
      • 3、修改 controller 控制器
      • 4、开发路由
      • 四、联调
      • 五、日志
      • 六、写在最后

        一、前言

        前面我们介绍了 await / async 的基本使用,学到了 koa2 框架的安装、项目的创建,以及路由的基本使用。

        接下来,我们正式使用 koa2 对我们的 myblog 博客项目进行重构!

        二、实现 session

        终端安装一些必要的东西(koa-generic-session、koa-redis、redis),更容易实现登录

        npm i koa-generic-session koa-redis redis
        

        修改 app.js 文件

        app.js

        const session = require('koa-generic-session')
        const redisStore = require('koa-redis')
        ......
        // session 配置(在routes前面)
        app.keys = ['Qianduan2023']
        app.use(session({
          // 配置 cookier
          cookie: {
            path: '/',
            httpOnly: true,
            maxAge: 24 * 60 * 60 * 1000
          },
          // 配置 redis
          store: redisStore({
            all: '127.0.0.1:6379' // 本地 reids
          })
        }))
        

        我们在 user.js 中创建一个 session-test 做测试

        user.js

        router.get('/session-test', async function(ctx, next) {
            if (ctx.session.viewCount == null) {
                ctx.session.viewCount = 0
            }
            
            ctx.session.viewCount++
            ctx.body = {
                errno: 0,
                viewCount: ctx.session.viewCount
            }
        })
        

        【Node.js实战】一文带你开发博客项目之Koa2重构(实现session、开发路由、联调、日志)


        三、开发路由

        1、安装 mysql 和 xss

        终端键入以下代码,安装 mysql 和 xss

        npm i mysql xss
        

        2、代码迁移

        【Node.js实战】一文带你开发博客项目之Koa2重构(实现session、开发路由、联调、日志)

        修改 app.js 文件,修改本地 redis 的写法

        app.js

        const { REDIS_CONF } = require('./conf/db')
        ......
          // 配置 redis
          store: redisStore({
            // all: '127.0.0.1:6379' // 本地 reids
            all: `${REDIS_CONF.host}:${REDIS_CONF.port}`
          })
        

        3、修改 controller 控制器

        修改 controller 文件里的内容(主要是修改成 async/await 的形式)

        ./controller.blog.js

        // 导入执行 sql 的相关内容
        const xss = require('xss')
        const { exec } = require('../db/mysql')
        // 获取博客列表(通过作者和关键字)
        const getList = async (author, keyword) => {
            // 1=1 是为了语法的绝对正确,注意以下 sql 拼接时的空格
            let sql = `select * from blogs where 1=1 `
            if (author) {
                sql += `and author='${author}' `
            }
            if (keyword) {
                sql += `and title like '%${keyword}%' `
            }
            // 以时间的倒序
            sql += `order by createtime desc;`
            // 返回 promise
            return await exec(sql)
        }
        // 获取博客详情(通过 id)
        const getDetail = async (id) => {
            const sql = `select * from blogs where id='${id}'`
            const rows = await exec(sql)
            return rows[0]
        }
        // 新建博客 newBlog 若没有,就给它一个空对象
        const newBlog = async (blogData = {}) => {
            // blogData 是一个博客对象,包含 title content author 属性
            const title = xss(blogData.title)
            const content = xss(blogData.content)
            const author = 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
            }
        }
        // 更新博客(通过 id 更新)
        const updateBlog = async (id, blogData = {}) => {
            // id 就是要更新博客的 id
            // blogData 是一个博客对象 包含 title content 属性
            const title = xss(blogData.title)
            const content = xss(blogData.content)
            const sql = `
                update blogs set title='${title}', content='${content}' where id=${id}
            `
            const updateData = await exec(sql)
            // 更新的影响行数大于 0,则返回 true
            if (updateData.affectedRows > 0) {
                return true
            }
            return false
        }
        // 删除博客(通过 id 删除)
        const delBlog = async (id, author) => {
            const sql = `delete from blogs where id='${id}' and author='${author}'`
            
            const delData = await exec(sql)
            if (delData.affectedRows > 0) {
                return true
            }
            return false
        }
        // 导出共享
        module.exports = {
            getList,
            getDetail,
            newBlog,
            updateBlog,
            delBlog
        }
        

        ./controller/user.js

        const { exec, escape } = require('../db/mysql')
        const { genPassword } = require('../utils/cryp')
        // 登录(通过用户名和密码)
        const login = async (username, password) => {
            username = escape(username)
            
            // 生成加密密码
            password = genPassword(password)
            password = escape(password)
            const sql = `
                select username, realname from users where username=${username} and password=${password}
            `
            const rows = await exec(sql)
            return rows[0]
            
        }
        // 导出共享
        module.exports = {
            login
        }
        

        4、开发路由

        开发 ./routes 文件里的路由,直接拷贝 blog-express 文件里的内容,使用 koa2 规定的格式即可

        ./routes/blog.js

        const router = require('koa-router')()
        // 导入博客和用户控制器相关内容
        const {
            getList,
            getDetail,
            newBlog,
            updateBlog,
            delBlog
        } = require('../controller/blog')
        // 导入成功和失败的模型
        const {
            SuccessModel,
            ErrorModel
        } = require('../model/resModel')
        const loginCheck = require('../middleware/loginCheck')
        // 前缀
        router.prefix('/api/blog')
        router.get('/list', async function (ctx, next) {
            // 博客的作者,req.query 用在 GET 请求中
            let author = ctx.query.author || ''
            // 博客的关键字
            const keyword = ctx.query.keyword || ''
            if (ctx.query.isadmin) {
                // 管理员界面
                if (ctx.session.username == null) {
                    // 未登录
                    ctx.body = new ErrorModel('未登录')
                    return
                }
                // 强制查询自己的博客
                author = ctx.session.username
            }
            // 查询的结果
            const listData = await getList(author, keyword)
            ctx.body = new SuccessModel(listData)
        })
        router.get('/detail', async function (ctx, next) {
            const data = await getDetail(ctx.query.id)
            ctx.body = new SuccessModel(data)
        })
        router.post('/new', loginCheck, async function (ctx, next) {
            const body = ctx.request.body
            body.author = ctx.session.username
            const data = await newBlog(body)
            ctx.body = new SuccessModel(data)
        })
        router.post('/update', loginCheck, async function (ctx, next) {
            const val = await updateBlog(ctx.query.id, ctx.body)
            if (val) {
                ctx.body = new SuccessModel()
            } else {
                ctx.body = new ErrorModel('更新博客失败')
            }
        })
        router.post('/del', loginCheck, async function (ctx, next) {
            const author = ctx.session.username
            const val = await delBlog(ctx.query.id, author)
            if (val) {
                ctx.body = new SuccessModel()
            } else {
                ctx.body = new ErrorModel('删除博客失败')
            }
        })
        module.exports = router
        

        ./routes/user.js

        const router = require('koa-router')()
        const { login } = require('../controller/user')
        const { SuccessModel, ErrorModel } = require('../model/resModel')
        // 前缀
        router.prefix('/api/user')
        // 路由的中间件必须是个 async 函数
        router.post('/login', async function (ctx, next) {
            // 通过 request.body 获取
            const { username, password } = ctx.request.body
            const data = await login(username, password)
            
            if (data.username) {
                // 设置 session
                ctx.session.username = data.username
                ctx.session.realname = data.realname
                ctx.body = new SuccessModel()
                return
            }
                ctx.body = new ErrorModel('登录失败')
        })
        module.exports = router
        

        四、联调

        启动 redis,开启 nginx

        后端:npm run dev

        前端:http-server -p 8001

        【Node.js实战】一文带你开发博客项目之Koa2重构(实现session、开发路由、联调、日志)

        【Node.js实战】一文带你开发博客项目之Koa2重构(实现session、开发路由、联调、日志)

        【Node.js实战】一文带你开发博客项目之Koa2重构(实现session、开发路由、联调、日志)


        五、日志

        终端键入安装 koa-morgan

        npm i koa-morgan
        

        修改 app.js 文件

        app.js

        const path = require('path')
        const fs = require('fs')
        const morgan = require('koa-morgan')
        ......
        // 日志记录
        const ENV = process.env.NODE_ENV
        if (ENV !== 'production') {
          // 开发环境 / 测试环境
          app.use(morgan('dev'))
        } else {
          // 线上环境使用 combined(写入文件)
          const logFileName = path.join(__dirname, 'logs', 'access.log')
          const writeStream = fs.createWriteStream(logFileName, {
            flags: 'a'
          })
          app.use(morgan('combined', {
            stream: writeStream
          }));
        }
        

        同样的,修改 package.json 文件

        package.json

        "prd": "cross-env NODE_ENV=production nodemon ./bin/www"
        

        npm run prd,运行文件,之后打开几个页面,查看 access.log 文件的内容

        【Node.js实战】一文带你开发博客项目之Koa2重构(实现session、开发路由、联调、日志)


        六、写在最后

        至此,我们明白了 如何使用 Koa2 框架对我们的 myblog 项目进行进一步的重构(实现session、开发路由、联调、日志), 本系列文章暂告一段落!

        如果你需要该项目的 源码,请通过本篇文章最下面的方式 加入 进来~~


        【Node.js实战】一文带你开发博客项目之Koa2重构(实现session、开发路由、联调、日志)


VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]