【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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18