项目开始
- 项目 主要由
express + mongodb
简单博客项目 express express-pure-blog
生成项目
{
"name": "express-pure-blog",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node ./bin/www",
"dev": "cross-env NODE_ENV=dev nodemon ./bin/www",
"prd": "cross-env NODE_ENV=production nodemon ./bin/www"
},
"dependencies": {
"connect-redis": "^6.1.3",
"cookie-parser": "~1.4.4",
"debug": "~2.6.9",
"express": "~4.16.1",
"express-session": "^1.17.3",
"http-errors": "~1.6.3",
"jade": "~1.11.0",
"mongoose": "^6.7.3",
"morgan": "~1.9.1",
"redis": "^2.8.0"
},
"devDependencies": {
"cross-env": "^7.0.3",
"nodemon": "^2.0.20"
}
}
添加用户与博客路由
- 用户路由只有登录
- 博客路由有增删改查
var express = require('express')
var router = express.Router()
const { login, register } = require('../controllers/users')
const { SuccessModel, ErrorModel } = require('../model/resModel')
// 登录
router.post('/login', function (req, res, next) {
const { username, password } = req.body
const result = login(username, password)
return result.then((data) => {
if (data.username) {
// 设置 session
req.session.username = data.username
req.session.realname = data.realname
res.json(new SuccessModel())
return
}
res.json(new ErrorModel('登录失败'))
})
})
module.exports = router
var express = require('express')
var router = express.Router()
const {
getList,
getDetail,
newBlog,
updateBlog,
delBlog,
} = require('../controllers/blogs')
const { SuccessModel, ErrorModel } = require('../model/resModel')
// 登录验证函数
const loginCheck = require('../middleware/loginCheck')
// 博客列表
router.get('/list', (req, res, next) => {
const author = req.query.author || ''
const keyword = req.query.keyword || ''
const result = getList(author, keyword)
return result.then((listData) => {
res.json(new SuccessModel(listData))
})
})
// 博客详情
router.get('/detail', (req, res, next) => {
const id = req.query.id
const result = getDetail(id)
return result.then((data) => {
res.json(new SuccessModel(data))
})
})
// 新建博客
router.post('/new', loginCheck, (req, res, next) => {
const author = req.session.username
req.body.author = author
const result = newBlog(req.body)
return result.then((data) => {
res.json(new SuccessModel(data))
})
})
// 更新博客
router.post('/update', loginCheck, (req, res, next) => {
const result = updateBlog(req.query.id, req.body)
return result.then((val) => {
if (val) {
res.json(new SuccessModel())
} else {
res.json(new ErrorModel('更新博客失败'))
}
})
})
// 删除博客
router.post('/del', (req, res, next) => {
const author = req.session.username
const result = delBlog(req.query.id, author)
return result.then((val) => {
if (val) {
res.json(new SuccessModel())
} else {
res.json(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/models/User')
const { SuccessModel, ErrorModel } = require('../model/resModel')
// 登录
const login = async (username, password) => {
const data = await User.findOne({
where: {
username,
password,
},
})
if (data === null) return {}
console.log('data', data)
return data
}
module.exports = {
login,
}
const Blog = require('../db/models/Blog')
const { SuccessModel, ErrorModel } = require('../model/resModel')
// 获取博客列表
const getList = async (author, keyword) => {
let whereOpt = {}
if (author) {
whereOpt.author = author
}
if (keyword) {
whereOpt.title = new RegExp(keyword)
}
const data = await Blog.find({
where: whereOpt,
order: [['createtime', 'DESC']],
})
return data
}
// 获取博客详情
const getDetail = async (id) => {
const data = await Blog.findById(id)
return data
}
// 新建一篇博客
const newBlog = async (blogData = {}) => {
const data = await Blog.create(blogData)
return data
}
// 更新一篇博客
const updateBlog = async (id, blogData = {}) => {
const data = await Blog.findByIdAndUpdate(id, blogData)
return data
}
// 删除一篇博客
const deleteBlog = async (id, author) => {
const data = await Blog.destroy({
where: {
id,
author,
},
})
return data
}
module.exports = {
getList,
getDetail,
newBlog,
updateBlog,
deleteBlog,
}
连接数据库建立 models
- 安装
mongoose
const mongoose = require('mongoose')
const url = 'http://localhost:27017/pureBlog'
// 连接
mongoose.connect(url, {
useNewUrlParser: true,
useUnifiedTopology: true,
})
// 连接成功
const db = mongoose.connection
db.on('error', console.error.bind(console, 'connection error:'))
// db.once('open', function () {
// console.log('mongodb connected')
// })
module.exports = mongoose
// blog 集合
const mongoose = require('../db')
const blogSchema = new mongoose.Schema(
{
title: {
type: String,
required: true,
},
content: String,
author: {
type: String,
required: true,
},
createtime: {
type: Date,
default: Date.now,
},
},
{ timestamps: true }
)
const Blog = mongoose.model('Blog', blogSchema)
module.exports = Blog
// 用户集合
const mongoose = require('../db')
const userSchema = new mongoose.Schema(
{
username: {
type: String,
required: true,
},
password: {
type: String,
required: true,
},
realname: String,
},
{ timestamps: true }
)
const User = mongoose.model('User', userSchema)
module.exports = User
使用 redis 保存 session
- 安装
redis
和connect-redis
- 安装
express-session
const redis = require('redis')
const { REDIS_CONF } = require('../config/db')
// 创建客户端 port 6379 可以使用本地 host localhost
const redisClient = redis.createClient(REDIS_CONF.port, REDIS_CONF.host)
redisClient.on('error', (err) => {
console.error(err)
})
module.exports = redisClient
// session
const session = require('express-session')
const redisStore = require('connect-redis')(session)
...
// session 配置
const redisClient = require('./db/redis')
const sessionStore = new redisStore({
client: redisClient,
})
app.use(
session({
//处理错误express-session deprecated undefined resave option; provide resave option app.js
resave: false, //添加这行
saveUninitialized: true, //添加这行
secret: 'WJiol_877_#',
cookie: {
// path : '/', // 默认配置
// httpOnly : true, // 默认配置
maxAge: 24 * 60 * 60 * 1000,
},
store: sessionStore,
})
)
// 3) "sess:rgcM5NdtaWl4RV44mRdnlV_ne7zdKa-a"
// 127.0.0.1:6379> get sess:rgcM5NdtaWl4RV44mRdnlV_ne7zdKa-a
// "{\"cookie\":{\"originalMaxAge\":86400000,\"expires\":\"2022-11-24T06:25:36.209Z\",\"httpOnly\":true,\"path\":\"/\"}}"
// 路由注册之前
接口测试工具
### 变量
@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=637e3818ff141e84ffe127f3
### 新建博客
POST {{BASE_URL}}/blog/new HTTP/1.1
Content-Type: application/json
{
"title": "测试标题2211",
"content": "测试内容3324",
"createtime": 1560000000000
}
### 修改博客
POST {{BASE_URL}}/blog/update?id=637e3818ff141e84ffe127f3 HTTP/1.1
Content-Type: application/json
{
"title": "测试标题133 express",
"content": "测试内容1 express",
"createtime": 1560000000000,
"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"
}