Node系列学习之MySQL复盘

182 阅读3分钟

这是我参与更文挑战的第12天,活动详情查看:更文挑战

花了两天时间简单学习了一下Node中如何使用MySQL,可以看下我的两篇文章: Node系列学习之MySQL Node系列学习之MySQL(二) , 今天回家第一天, 早起+舟车劳顿+做饭, 比较累, 学不动了~ 所以今天先简单复盘一下这两天的学习!

文件分析

image-20210612232353331

conf/db.js

存储环境变量与SQL链接数据库的相关配置

const env = process.env.NODE_ENV // 获取环境参数

let MYSQL_CONF

if (env == 'dev') {
  MYSQL_CONF = {
    host: 'localhost',
    user: 'root',
    password: '111',
    port: '3306',
    database: 'myblog'
  }
}
if (env == 'production') {
  MYSQL_CONF = {
    host: 'localhost',
    user: 'root',
    password: '111',
    port: '3306',
    database: 'myblog'
  }
}

module.exports = {
  MYSQL_CONF
}

controller

目录下的文件与 router 目录下的路由文件遥相对应, 只关心数据,从数据库拿到数据后返回, 不作任何处理

crotroller/blog.js

const {exec} = require('../db/mysql.js')

const getList = (author, keyword) => {
  
  let sql = `
    select * from blogs where 1=1 
  `
  if (author) {
    sql += `and author='${author}' `
  }
  if(keyword) {
    sql += `and title like '%${keyword}%' `
  }
  sql += `order by createtime desc;`
  // 返回的是个Promise
  return exec(sql)
  
}
// 博客详情
const getDetail = id => {
  const sql = `select * from blogs where id='${id}' `
  return exec(sql).then(rows => {
    return rows[0]
  })
}
// 新建博客
const newBlog = (blogData = {}) => {
  const title = blogData.title
  const content = blogData.content
  const author = blogData.author
  const createTime = Date.now()
  const sql = `
    insert into blogs (title,content,createtime,author) values ('${title}','${content}',${createTime}, '${author}');
  `
  return exec(sql).then(insertData => {
    // console.log('insertData',insertData);
    return {
      id: insertData.insertId
    }
  })
}
const updateBlog = (id,blogData= {}) => {
  const title= blogData.title
  const content = blogData.content
  const sql = `
    update blogs set title='${title}', content='${content}' where id=${id}; 
  `
  return exec(sql).then(updateData => {
    // console.log('updateData', updateData);
    if(updateData.affectedRows > 0) {
      return true
    }
    return false
  })

}
const delBlog = (id,author) => {
  const sql = `
    delete from blogs where id='${id}' and author='${author}';
  `
  return exec(sql).then(delData => {
    if(delData.affectedRows > 0) {
      return true
    }
    return false
  })
}
module.exports = {
  getList,
  getDetail,
  newBlog,
  updateBlog,
  delBlog
}

controller/user.js

const {exec} = require('../db/mysql.js')
const loginCheck = (username, password) => {
  const sql = `
    select username, realname from users where username='${username}' and password='${password}';
  `
  return exec(sql).then(rows => {
    return rows[0] || {}
  })
}
module.exports = {
  loginCheck
}

db/mysql.js

mysql的封装函数, 返回Promise, 将数据库返回的结果带入.

const mysql = require('mysql')
const { MYSQL_CONF } = require('../conf/db')
// 创建链接对象
const con = mysql.createConnection(MYSQL_CONF)

// 开始连接
con.connect()

// 同意执行 sql 的函数

function exec(sql) {
  return new Promise((resolve, reject) => {
    con.query(sql, (err, result) => {
      if (err) {
        reject(err)
        return
      }
      resolve(result)
    })
  })
}
module.exports = {
  exec
}

model

model/resModel.js

接口回复的统一模板, 有成功返回模板和失败返回模板

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
}

router

对路由接口处理, 通过引入 controller 下同名文件暴露的相关方法来获取数据,并对数据进行处理与最终返回

router/user.js

const { loginCheck } = require('../controller/user')
const { SuccessModel, ErrorModel } = require('../model/resModel')
const handleUserRouter = (req, res) => {
  const method = req.method

  // 登录
  if (method == 'POST' && req.path == '/api/user/login') {
    const { username, password } = req.body
    const result = loginCheck(username,password)
    return result.then(data => {
      if(data.username) {
        return new SuccessModel()
      }
      return new ErrorModel('登录失败~')
    })
  }
}
module.exports = handleUserRouter

router/blog.js

const { getList, getDetail, newBlog, updateBlog, delBlog } = require('../controller/blog')
const { SuccessModel, ErrorModel } = require('../model/resModel')
const handleBlogRouter = (req, res) => {
  const method = req.method
  const id = req.query.id
  // 获取博客列表
  if (method == 'GET' && req.path == '/api/blog/list') {
    const author = req.query.author || ''
    const keyword = req.query.keyword || ''
    // const listData = getList(author, keyword)
    // return new SuccessModel(listData)
    const result = getList(author,keyword)
    return result.then(listData => {
      return new SuccessModel(listData)
    })
  }
  // 获取博客详情
  if (method == 'GET' && req.path == '/api/blog/detail') {
    // const data = getDetail(id)
    // return new SuccessModel(data)
    const result = getDetail(id)
    return result.then(data => {
      return new SuccessModel(data)
    })
  }
  // 新建一篇博客
  if (method == 'POST' && req.path == '/api/blog/new') {
    // const data = newBlog(req.body)
    // return new SuccessModel(data)
    req.body.author = 'tmier' // 待开发登录完成后再改成真实数据
    const result = newBlog(req.body)
    return result.then(data => {
      return new SuccessModel(data)
    })
  }

  // 更新一篇博客
  if (method == 'POST' && req.path == '/api/blog/update') {
    const result = updateBlog(id, req.body)
    return result.then(val => {
      if(val) {
        return new SuccessModel()
      }
      return new ErrorModel('更新博客失败~')
    })
  }

  // 删除一篇博客
  if (method == 'POST' && req.path == '/api/blog/del') {
    let author = 'tmier'
    const result = delBlog(id,author)
    return result.then(val => {
      if(val) {
        return new SuccessModel()
      }
      return new ErrorModel('删除博客失败~')
    })
  }
}

module.exports = handleBlogRouter

app.js

对接受的req与返回的res进行统一设置与处理, 设置未命中路由

const querystring = require('querystring')
const handleBlogRouter = require('./src/router/blog.js')
const handleUserRouter = require('./src/router/user.js')

// 用于处理 postData
const getPostData = req => {
  return new Promise((resolve, reject) => {
    if (req.method !== 'POST') {
      resolve({})
      return
    }
    // 非json数据类型,忽略并返回{}
    if (req.headers['content-type' !== 'application/json']) {
      resolve({})
      return
    }
    // 正确的
    let postData = ''
    req.on('data', chunk => {
      postData += chunk.toString()
    })
    req.on('end', () => {
      if (!postData) {
        resolve({})
        return
      }
      // 成功返回
      resolve(JSON.parse(postData))
    })
  })
}

const serverHandle = (req, res) => {
  res.setHeader('Content-Type', 'application/json')

  // 获取path
  const url = req.url
  req.path = url.split('?')[0]

  // 解析 query
  req.query = querystring.parse(url.split('?')[1])

  // 处理 postData
  getPostData(req).then(postData => {
    req.body = postData
    // 处理 blog 路由 旧

    // const blogData = handleBlogRouter(req, res)
    // if (blogData) {
    //   res.end(JSON.stringify(blogData))
    //   return
    // }

    // 处理 blog 路由 新
    const blogResult = handleBlogRouter(req, res)
    if (blogResult) {
      blogResult.then(blogData => {
        res.end(JSON.stringify(blogData))
      })
      return
    }

    // 处理 user 路由
    // const userData = handleUserRouter(req, res)
    // if (userData) {
    //   res.end(JSON.stringify(userData))
    //   return
    // }
    const userResult = handleUserRouter(req,res)
    if(userResult) {
      userResult.then(userData => {
        res.end(JSON.stringify(userData))
      })
      return 
    }

    // 未命中路由, 返回404
    res.writeHead(404, { 'Content-Type': 'text/plain' })
    res.write('404 Not Found\n')
    res.end()
  })
}
module.exports = serverHandle