【Nodejs博客项目开发】之原生nodejs实现博客系统(三)

一、nodejs操作Mysql

1、测试demo

  1. npm init -y初始化项目
  2. npm i mysql --save安装mysql
  3. 用nodejs操作mysql
const mysql = require('mysql')

// 创建连接对象
const con = mysql.createConnection({
    host: 'localhost',
    user: 'root',
    password: 'qybsjct',
    port: '3306',
    database: 'myblog'
})

// 开始连接
con.connect()

// 执行sql语句
const sql = "select * from users"
con.query(sql, (err, result) => {
    if (err) {
        console.log(err)
        return
    }
    console.log(result)
})

// 关闭连接
con.end()

注意:如果你在这运行报错是Error: ER_NOT_SUPPORTED_AUTH_MODE: Client does not support authentication protocol requested by server; consider upgrading MySQL client

解决方案:在mysql客户端中执行alter user 'root'@'localhost' identified with mysql_native_password by 'qybsjct';flush privileges; (qybsjct是我的密码)

然后,nodejs连接mysql成功:

//从数据库中获取到的数据:
[
  RowDataPacket {
    id: 1,
    username: 'zhangsan',
    password: '123',
    realname: '张三'
  },
  RowDataPacket {
    id: 2,
    username: 'lisi',
    password: '123',
    realname: '李四'
  }
]

如果你把sql语句换成:const sql = "update users set realname='李四2' where username='lisi';"更新表的时候会返回什么?

生成的node_modules在哪 node_modules .bin_生成的node_modules在哪

在后续博客操作的时候就是基于这里的数据来完成

如果你把sql语句换成:insert into blogs(title,content,createtime,author) values('标题C','内容C',1603328418920,'zhangsan')"插入数据的时候会返回什么?

生成的node_modules在哪 node_modules .bin_sql_02

2、在node博客项目中搭建mysql环境

第一步

首先在项目中npm i mysql --save安装mysql,然后安装npm install --save-dev cross-env,通过npm run dev开启程序

第二步

在项目中的src文件下创建conf文件db文件,在conf文件中创建db.js,在db文件中创建mysql.js

-- src
	-- conf
		db.js //数据库环境参数设置
	-- db
		mysql.js //nodejs连接myql
第三步

db.js

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

// 配置
let MYSQL_CONF

// 开发环境下的
if (env === 'dev') {
    MYSQL_CONF = {
        host: 'localhost',
        user: 'root',
        password: 'qybsjct',
        port: '3306',
        database: 'myblog'
    }
}

// 线上的(现在只不过是没有具体区别线上线下)
if (env === 'production') {
    MYSQL_CONF = {
        host: 'localhost',
        user: 'root',
        password: 'qybsjct',
        port: '3306',
        database: 'myblog'
    }
}

module.exports = {
    MYSQL_CONF
}

mysql.js

const mysql = require('mysql')
const { MYSQL_CONF } = require('../conf/db')

// 创建链接对象
const con = mysql.createConnection(MYSQL_CONF)

// 开始链接
con.connect()

// 统一执行sql函数
// 这个函数类似于一个单例模式,不需要.end关闭
function exec(sql) {
    // 因为要返回result,所以需要用异步promise来实现
    const promise = new Promise((resolve, reject) => {
        con.query(sql, (err, result) => {
            if (err) {
                reject(err)
                return
            }
            resolve(result)
        })
    })
    return promise 
    

}

// 暴露出去
module.exports = {
    exec
}

3、API对接mysql(博客列表)

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

// 获取博客列表接口数据
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)
}
router/blog.js
//获取博客列表
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)
    })
}
app.js
/*
处理blog路由
*/ 

// const blogData = handleBlogRouter(req, res)
// if (blogData) {
//     res.end(
//         //转换为json格式的字符串
//         JSON.stringify(blogData)
//     )
//     return
// }
const blogResult = handleBlogRouter(req, res)
	if(blogResult){
		blogResult.then(blogData => {
			res.end(
				JSON.stringify(blogData)
            )
	})
	return
}

4、API对接mysql(博客详情和新建)

controller/blog.js
// 获取博客博客详情接口数据
const getDetail = (id) => {
    const sql = `select * from blogs where id='${id}'`
    // 把数组变为对象
    return exec(sql).then(rows => {
        return rows[0]
    })
}

//==========================================

// 获取新建博客接口
const newBlog = (blogData = {}) => {
    //blogData是一个博客对象,包含:title content author..属性
    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 is', insertData)
        return {
            id : insertData.insertId
        }
    })
router/blog.js
// 获取博客详情
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 = 'zhangsan' //假数据
    const result = newBlog(req.body)
    return result.then(data => {
        return new SuccessModel(data)
    })
    }

5、API对接mysql(博客更新和删除)

controller/blog.js
// 获取更新博客接口
const updateBlog = (id, blogData = {}) => {
    // id 就是更新博客的 id
    //blogData是一个博客对象,包含:title content ```属性
    
    // console.log('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 is', updateData)
        if (updateData.affectedRows > 0) {
            return true
        }
        return false
    })
    return true
}

//===========================================

//获取删除博客接口
const delBlog = (id,author) => {
    // id 就是要删除博客的 id

    const sql = `delete from blogs where id='${id}' and author='${author}'; ` 
    return exec(sql).then(delData => {
        // console.log('delData is', delData)
        if (delData.affectedRows > 0) {
            return true
        }
        return false
    })
}
router/blog.js
// 更新博客接口
if (method === 'POST' && req.path === '/api/blog/update') {
	const result = updateBlog(id, req.body)
	return result.then(val => {
		if (val) {
			return new SuccessModel()
		} else {
			return new ErrorModel('更新博客失败')
		}
	})

}

//=======================================

// 删除一篇博客接口
if (method === 'POST' && req.path === '/api/blog/del') {

const author = 'lisi' //假数据
const result = delBlog(id, author)

return result.then(val => {
	if (val) {
		return new SuccessModel()
	} else {
		return new ErrorModel('删除博客失败')
	}
	}) 

}

6、API对接mysql实现登录

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

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] || {}
    })
}
router/user.js
// 登录
    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('登录失败')
        })
    }

7、总结

nodejs连接mysql,如何执行sql语句

根据NODE_ENV区分配置

封装exec函数,API使用exec操作数据库