项目开始

  • 项目 主要由 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

  • 安装 redisconnect-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"
}