02-博客api接口项目实战之用户注册

辰漪
2022-01-20 / 0 评论 / 36 阅读 / 正在检测是否收录...

1. 安装数据库及可视化数据库管理工具(navicat)

数据库管理工具(Navicat 15)安装激活教程

2. 创建数据库及表

创建一个名为blog的数据库

kymnoqu6.png

双击打开blog数据库,右键表,新建表,创建一个名为users的数据表

kymnp6ik.png

kymnpaik.png

3. 实现注册功能

注册功能其实就是给users表中插入数据

注册所需字段:username password

所需npm包:

​ bcryptjs 用来给密码进行加密

​ mysql 用来连接数据库,操作数据库

​ joi 用来数据校验

​ body-parser 用来提交表单数据,处理表单数据,处理完之后挂载到req.body上

npm install bcryptjs mysql joi body-parser
3.1 实现步骤
3.1.1. 数据库连接

在db文件夹下创建文件index.js

// db/index.js
const mysql = require('mysql')

const db = mysql.createConnection({ // 连接数据库
  host: '127.0.0.1', // 127.0.0.1 / localhost
  user: 'root', // 数据库用户名
  password: '123456', // 密码
  database: 'blog' // 数据库名称
})

module.exports = db

操作数据库通过 db.query()方法

mysql详细api文档:https://www.npmjs.com/package/mysql

3.1.2. 创建用户注册字段校验函数和时间格式化函数

joi详细api文档:https://joi.dev/api/?v=17.5.0

在utils中创建validate.js用来校验字段,当做中间件使用

// 校验数据

// schemas 校验对象
const joi = require('joi')
const validateJoi = function (schemas) {
  // TODO: 用户指定了什么 schema,就应该校验什么样的数据
  return function (req, res, next) {
      ;['query', 'body', 'params'].forEach((key) => {
        // 如果当前循环的这一项 schema 没有提供,则不执行对应的校验
        if (!schemas[key]) return
        // 执行校验
        const schema = joi.object(schemas[key])
        const { error, value } = schema.validate(req[key])
        if (error) {
          // 校验失败
          throw error
        } else {
          // 校验成功,把校验的结果重新赋值到 req 对应的 key 上
          req[key] = value
        }
      })
    // 校验通过
    next()
  }
}

module.exports = validateJoi

在utils中添加时间格式化函数

/*
*@params date {Date Object} 日期
*@params fmt {String} 格式化方式
*@params bool {Boolean} 是否返回周几
*/
function dateFormat(date, fmt, bool) {
  date = new Date(date)
  var o = {
      "M+": date.getMonth() + 1, //月份
      "d+": date.getDate(), //日
      "h+": date.getHours(), //小时
      "m+": date.getMinutes(), //分
      "s+": date.getSeconds(), //秒
      "q+": Math.floor((date.getMonth() + 3) / 3), //季度
      S: date.getMilliseconds(), //毫秒
  }
  let weekStr = "" // 星期几
  const weekList = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']
  weekStr = weekList[date.getDay()]
  if (/(y+)/.test(fmt)) {
      fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length))
  }

  for (var k in o) {
      if (new RegExp("(" + k + ")").test(fmt)) {
          fmt = fmt.replace(
              RegExp.$1,
              RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length)
          )
      }
  }
  if (bool) fmt = fmt + " " + weekStr
  return fmt
}
module.exports = dateFormat
// console.log(dateFormat(+new Date(), "yyyy-MM-dd hh:mm:ss", 1))

在schema文件夹下创建user.js存放用户相关的字段校验对象

// schema/user.js
// 用户相关的字段校验
const joi = require('joi')
// username password
const reg = {
  body: {
    // 只能包含字母数字最小为1最大为10的字符串,并且必填
    username: joi.string().alphanum().min(1).max(10).required(), 
    // 符合正则的字符串,并且必填
    password: joi.string().pattern(/^[\S]{6,12}$/).required()
  }
}
module.exports = {
  reg
}
3.1.3. 在router文件夹下创建文件 user.js 专门存放用户相关的路由
// router/user.js
// 用户相关的路由
const { Router } = require('express')
const router = Router()
const validateJoi = require('../utils/validate') // 校验数据
// 路由处理函数
const user_handler = require('../router_handler/user')
const userSchema = require('../schema/user') // 用户相关的校验对象
// 用户注册
router.post('/reguser', validateJoi(userSchema.reg), user_handler.regUser)
3.1.4. 在router_handler文件夹下创建文件 user.js 专门存放用户相关的路由处理函数
// touter_handler/user.js

const bcrypt = require('bcryptjs') // 密码加密和解密
const db = require('../db/index') // 导入数据库对象
const dateFormat = require('../utils/dateFormat') // 时间格式化
// 注册
const regUser = (req, res) => {
  // 用户名密码校验正确
  const userInfo = req.body
  const sql = `insert into users set ?`
  userInfo.reg_time = dateFormat(new Date(), 'yyyy-MM-dd hh:mm:ss')
  userInfo.password = bcrypt.hashSync(userInfo.password, 10) // 对密码加密
  db.query(sql, userInfo, (err, result) => {
    if (err && err.code === 'ER_DUP_ENTRY') {
      const arr = err.sqlMessage.split(' ')
      return arr[arr.length - 1] === "'username'" ? res.cc('用户名重复,换一个叭!') : res.cc(err.sqlMessage)
    }
    if (result.affectedRows !== 1) return res.cc('注册失败,请稍后重试!')
    res.cc('注册成功!', 0)
  })
}


module.exports = {
  regUser
}
3.1.5 在app.js中挂载路由,添加错误级别中间件,以及错误输出状态函数
...
const joi = require('joi')
const bodyParser = require('body-parser')
const userRouter = require('./router/user') // 用户相关的路由
// 定义输出错误状态的中间件
app.use((req, res, next) => {
  // 挂载函数,全局能用
  res.cc = function (err, status = 1) {
    res.send({
      status,
      msg: err instanceof Error ? err.message : err
    })
  }
  next()
})
// 处理表单数据
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
app.use('/api', userRouter)

// 定义错误级别中间件 放在所有路由后边
app.use((err, req, res, next) => {
  // joi校验错误
  if (err instanceof joi.ValidationError) return res.cc(err)
})
...
3.1.6 测试注册接口: http://127.0.0.1:8086/api/reguser
  • 请求路径:/api/reguser
  • 请求方法:post
  • 请求参数:
请求参数参数类型参数说明备注
usernameString用户名不能为空 长度1-10位
passwordString密码不能为空 长度6-12位
0
选择打赏方式:
微信

评论 (0)

取消