项目开始
- 项目 主要由
koa2 + sequelize + mysql
简单博客项目 koa2 koa-pure-blog
生成项目
{
"name": "koa-pure-blog",
"version": "0.1.0",
"private": true,
"scripts": {
"start": "node bin/www",
"dev": "cross-env NODE_ENV=dev ./node_modules/.bin/nodemon bin/www",
"prd": "pm2 start bin/www",
"test": "echo \"Error: no test specified\" && exit 1"
},
"dependencies": {
"debug": "^4.1.1",
"koa": "^2.7.0",
"koa-bodyparser": "^4.2.1",
"koa-convert": "^1.2.0",
"koa-generic-session": "^2.3.0",
"koa-json": "^2.0.2",
"koa-logger": "^3.2.0",
"koa-onerror": "^4.1.0",
"koa-redis": "^4.0.1",
"koa-router": "^7.4.0",
"koa-static": "^5.0.0",
"koa-views": "^6.2.0",
"mysql2": "^2.3.3",
"pug": "^2.0.3",
"sequelize": "^6.25.8"
},
"devDependencies": {
"cross-env": "^7.0.3",
"nodemon": "^1.19.1"
}
}
添加用户和博客路由
- 用户路由只有登录
- 博客路由有增删改查
const router = require('koa-router')()
const { login } = require('../controller/user')
router.prefix('/api/user')
const { SuccessModel, ErrorModel } = require('../model/resModel')
// 登录
router.post('/login', async (ctx, next) => {
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
const router = require('koa-router')()
const {
getList,
getDetail,
newBlog,
updateBlog,
delBlog,
} = require('../controller/blog')
router.prefix('/api/blog')
const { SuccessModel, ErrorModel } = require('../model/resModel')
// 登录中间件
const checkLogin = require('../middleware/checkLogin')
// 博客列表
router.get('/list', async (ctx, next) => {
const author = ctx.query.author || ''
const keyword = ctx.query.keyword || ''
const listData = await getList(author, keyword)
ctx.body = new SuccessModel(listData)
})
// 博客详情
router.get('/detail', async (ctx, next) => {
const data = await getDetail(ctx.query.id)
ctx.body = new SuccessModel(data)
})
// 新建一篇博客
router.post('/new', checkLogin, async (ctx, next) => {
const author = ctx.session.username
ctx.request.body.author = author
const data = await newBlog(ctx.request.body)
ctx.body = new SuccessModel(data)
})
// 更新一篇博客
router.post('/update', checkLogin, async (ctx, next) => {
const val = await updateBlog(ctx.query.id, ctx.request.body)
if (val) {
ctx.body = new SuccessModel()
} else {
ctx.body = new ErrorModel('更新博客失败')
}
})
// 删除一篇博客
router.post('/del', async (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
class BaseModel {
constructor(data, message) {
if (typeof data === 'string') {
this.message = data
data = null
message = null
}
if (data) {
this.data = data
}
if (message) {
this.message = message
}
}
}
class SuccessModel extends BaseModel {
constructor(data, message) {
super(data, message)
this.errno = 0
}
}
class ErrorModel extends BaseModel {
constructor(data, message) {
super(data, message)
this.errno = -1
}
}
module.exports = {
SuccessModel,
ErrorModel,
}
添加用户和博客控制器
const User = require('../db/model/User')
const { SuccessModel, ErrorModel } = require('../model/ResModel')
// 用户登录
const login = async (username, password) => {
const data = await User.findOne({
where: {
username,
password,
},
})
if (data === null) return null
return data.dataValues
}
module.exports = {
login,
}
const Sequelize = require('sequelize')
const Blog = require('../db/model/Blog')
const { SuccessModel, ErrorModel } = require('../model/resModel')
// 获取博客列表
const getList = async (author = '', keyword = '') => {
const whereOpt = {}
if (author) {
whereOpt.author = author
}
if (keyword) {
whereOpt.title = {
[Sequelize.Op.like]: `%${keyword}%`,
}
}
const list = await Blog.findAll({
where: whereOpt,
order: [['id', 'desc']],
})
return list.map((item) => item.dataValues)
}
// 获取博客详情
const getDetail = async (id) => {
const detail = await Blog.findOne({
where: {
id,
},
})
return detail.dataValues
}
// 新建一篇博客
const newBlog = async (blogData = {}) => {
const { title, content, author } = blogData
const result = await Blog.create({
title,
content,
author,
})
return result.dataValues
}
// 更新一篇博客
const updateBlog = async (id, blogData = {}) => {
const { title, content } = blogData
const result = await Blog.update(
{
title,
content,
},
{
where: {
id,
},
}
)
return result[0] > 0
}
// 删除一篇博客
const delBlog = async (id, author) => {
const result = await Blog.destroy({
where: {
id,
author,
},
})
return result > 0
}
module.exports = {
getList,
getDetail,
newBlog,
updateBlog,
delBlog,
}
连接数据库建立表
- 安装
sequelize
和mysql2
const Sequelize = require('sequelize')
const { MYSQL_CONF } = require('../config/db')
// 配置
const conf = {
host: MYSQL_CONF.host,
dialect: 'mysql',
}
// 线上环境,使用连接池
if (process.env.NODE_ENV === 'production') {
conf.pool = {
max: 5, // 连接池中最大的连接数量
min: 0, // 最小
idle: 10000, // 如果一个连接池 10s 之内没有被使用,则释放
}
}
// 创建连接
const seq = new Sequelize(
MYSQL_CONF.database,
MYSQL_CONF.user,
MYSQL_CONF.password,
conf
)
module.exports = seq
const Sequelize = require('sequelize')
const seq = require('../seq')
// 创建 User 模型
const User = seq.define('pure_user', {
// id 会自动创建,并设为主键,自增
//
username: {
type: Sequelize.STRING, // varchar(255)
allowNull: false,
},
password: {
type: Sequelize.STRING,
allowNull: false,
},
realname: {
type: Sequelize.STRING,
},
})
module.exports = User
const Sequelize = require('sequelize')
const seq = require('../seq')
// 创建 Blog 模型
const Blog = seq.define('pure_blog', {
// id 会自动创建,并设为主键,自增
//
title: {
type: Sequelize.STRING, // varchar(255)
allowNull: false,
},
content: {
type: Sequelize.TEXT, // longtext
allowNull: false,
},
author: {
type: Sequelize.STRING,
allowNull: false,
},
})
module.exports = Blog
const seq = require('./seq')
// 需要同步的模型列表
require('./model/Blog')
require('./model/User')
// 测试连接
seq
.authenticate()
.then(() => {
console.log('ok')
})
.catch(() => {
console.log('err')
})
// 执行同步
seq.sync({ force: true }).then(() => {
console.log('sync ok')
process.exit()
})
使用 redis 保存 session
- 安装
koa-generic-session
和koa-redis
const session = require('koa-generic-session')
const redisStore = require('koa-redis')
const { REDIS_CONF } = require('./config/db')
...
// session 配置
app.keys = ['WJiol#231_']
app.use(
session({
key: 'w23423423',
prefix: 'weibo:sess:',
// 配置 cookie
cookie: {
path: '/',
httpOnly: true,
maxAge: 24 * 60 * 60 * 1000,
},
// 配置 redis
store: redisStore({
all: `${REDIS_CONF.host}:${REDIS_CONF.port}`,
}),
})
)
// 路由注册之前
接口测试工具
### 变量
@BASE_URL = http://localhost:3000/api
### 测试
GET http://localhost:3000/ HTTP/1.1
### 博客列表
GET {{BASE_URL}}/blog/list HTTP/1.1
### 博客详情
GET {{BASE_URL}}/blog/detail?id=1 HTTP/1.1
### 新建博客
POST {{BASE_URL}}/blog/new HTTP/1.1
Content-Type: application/json
{
"title": "测试标题 koa sequelize",
"content": "测试内容3324koa sequelize",
"createtime": 1560000000000
}
### 修改博客
POST {{BASE_URL}}/blog/update?id=1 HTTP/1.1
Content-Type: application/json
{
"title": "测试标题koa",
"content": "测试内容koa",
"author": "admin"
}
### 删除博客
POST {{BASE_URL}}/blog/delete?id=1
### 用户登录
POST {{BASE_URL}}/user/login
Content-Type: application/json
{
"username": "admin",
"password": "admin"
}
### 用户注册
POST {{BASE_URL}}/user/register
Content-Type: application/json
{
"username": "admin",
"password": "admin"
}