【Node.js实战】一文带你开发博客项目(API 对接 MySQL)

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
云数据库 RDS MySQL Serverless,价值2615元额度,1个月
简介: 【Node.js实战】一文带你开发博客项目(API 对接 MySQL)

一、前言

前面我们已经使用了 假数据去处理路由接口,并学习了开发博客路由相关 MySQL的基础知识。

下面我们就可以 整合改进 这两部分,实现 API 和 MySQL 的对接 工作。

二、Node.js 连接 MySQL

安装 MySQL

npm install mysql

e1907777aa8044b48b0002b3b23b2cf1.png

在 src 目录下创建 ./conf/db.js 文件,用于连接数据库的配置

cbf179082c394233bed152901634946f.png

db.js 文件

  • 线上环境与开发环境的配置是不一样的
  • 这里写的是一样的,因为项目没有上线
// 获取环境参数, process 为 node.js 进程的一些信息
const env = process.env.NODE_ENV
// 配置
let MYSQL_CONF
// 开发环境下
if (env === 'dev') {
    MYSQL_CONF = {
        host: 'localhost',
        user: 'root',
        password: '1234abcd',
        port: '3306',
        database: 'myblog'
    }
}
// 线上环境下
if (env === 'production') {
    MYSQL_CONF = {
        host: 'localhost',
        user: 'root',
        password: '1234abcd',
        port: '3306',
        database: 'myblog'
    }
}
// 导出共享
module.exports = {
    MYSQL_CONF
}

在 src 目录下创建 ./db/mysql.js 文件,用于存放一些数据

32dfc3aa816c4f63b90ae3381092e26e.png

mysql.js 文件

  • 引入 mysql 和连接数据库
  • 封装 sql 函数,用于统一执行
// 引入 MySQL
const mysql = require('mysql')
// 引入数据库连接配置
const { MYSQL_CONF } = require('../conf/db')
// 创建连接对象
const con = mysql.createConnection(MYSQL_CONF)
// 开始连接
con.connect()
// 统一执行 sql 的函数
function exec(sql) {
    const promise = new Promise((resolve, reject) => {
        con.query(sql, (err, result) => {
            if (err) {
                reject(err)
                return
            }
            resolve(result)
        })
    })
    return promise
}
// 导出共享
module.exports = {
    exec
}

三、API 对接 MySQL

1、文件目录

36cd0666c29f4a8082803ef212a4b9f3.png

2、控制器_controller

blog.js 文件

  • blog 相关 sql 逻辑
  • 返回的是 promise 实例
// 导入执行 sql 的相关内容
const { exec } = require('../db/mysql')
// 获取博客列表(通过作者和关键字)
const getList = (author, keyword) => {
    // 1=1 是为了语法的绝对正确,注意以下 sql 拼接时的空格
    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)
}
// 获取博客详情(通过 id)
const getDetail = (id) => {
    const sql = `select * from blogs where id='${id}'`
    return exec(sql).then(rows => {
        // 返回数组的对象
        return rows[0]
    })
}
// 新建博客 newBlog 若没有,就给它一个空对象
const newBlog = (blogData = {}) => {
    // blogData 是一个博客对象,包含 title content author 属性
    const title = blogData.title
    const content = blogData.content
    const author = blogData.author
    const createTime = Date.now()
    // sql 插入语句
    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
        }
    })
}
// 更新博客(通过 id 更新)
const updateBlog = (id, blogData = {}) => {
    // id 就是要更新博客的 id
    // blogData 是一个博客对象 包含 title content 属性
    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)
        // 更新的影响行数大于 0,则返回 true
        if (updateData.affectedRows > 0) {
            return true
        }
        return false
    })
}
// 删除博客(通过 id 删除)
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
}

user.js 文件

  • 登录相关 sql 逻辑
  • 返回的是 promise 实例
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] || {}
    })
}
// 导出共享
module.exports = {
    loginCheck
}

3、路由_router

blog.js 文件

  • 博客相关路由
  • 调用控制器中的方法
// 导入博客和用户控制器相关内容
const { getList, getDetail, newBlog, updateBlog, delBlog } = require('../controller/blog') 
// 导入成功和失败的模型
const { SuccessModel, ErrorModel } = require('../model/resModel')
// blog 相关路由
const handleBlogRouter = (req, res) => {
    const method = req.method // GET/POST
    const id = req.query.id // 获取 id
    // 获取博客列表 GET 请求
    if (method === 'GET' && req.path === '/api/blog/list') {
        // 博客的作者,req.query 用在 GET 请求中
        const author = req.query.author || ''
        // 博客的关键字
        const keyword = req.query.keyword || ''
        // 查询的结果
        const result = getList(author, keyword)
        return result.then(listData => {
            return new SuccessModel(listData)
        })
    }
    // 获取博客详情 GET 请求
    if (method === 'GET' && req.path === '/api/blog/detail') {
        // 获取博客详情数据
        const result = getDetail(id)
        // 创建并返回成功模型的 promise 实例对象
        return result.then(data => {
            return new SuccessModel(data)
        })
    }
    // 新建一篇博客 POST 请求
    if (method === 'POST' && req.path === '/api/blog/new') {
        // 假数据,待开发登录时再改成真实数据
        req.body.author = 'zhangsan'
        // req.body 用于获取请求中的数据(用在 POST 请求中)
        const result = newBlog(req.body)
        // 创建并返回成功模型的 promise 实例对象
        return result.then(data => {
            return new SuccessModel(data)
        })
    }
    // 更新一篇博客
    if (method === 'POST' && req.path === '/api/blog/update') {
        // 传递两个参数 id 和 req.body
        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 = 'zhangsan' 
        const result = delBlog(id, author)
        return result.then(val => {
            if (val) {
                return new SuccessModel()
            } else {
                return new ErrorModel('删除博客失败')
            }
        })
    }
}
// 导出
module.exports = handleBlogRouter

user.js 文件

  • 用户登录相关路由
  • 调用控制器中的方法
// 导入用户登录内容
const { loginCheck } = require('../controller/user')
// 导入成功和失败的模板
const { SuccessModel, ErrorModel } = require('../model/resModel')
// user 路由
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

四、各个接口的测试

查询博客列表

cbdd95b48c664c9b9dfe2410f0ba108c.png

通过关键字查询博客(模糊查询)

5fea5983115a47f2b142a879d4ec6de1.png

通过关键字查询博客(精准查询)

bca0100c6b764dc699e5ed47a20a6966.png

通过id获取博客详情

3a1c8b18e42e4ac6a044297c0b82eef9.png

通过 ApiPost/Postman 工具测试 新建博客

4bea13f4e72642ce913faa093a025eb3.png

d1f0cf6a6cff46b78ecbdf4ff489aadd.png

通过 ApiPost/Postman 工具测试 更新博客

03220e5028ee4dcea0b65e0d2449f923.png

4f36d290d70745da9d31dc86bb056d04.png

33c161927e3f467c9a8b1f0dc84b060a.png

通过 ApiPost/Postman 工具测试 删除博客

6f886b8337f94a5da0c443ad1d4ff026.png

550c25748c74481baf764de58f5da248.png

550c25748c74481baf764de58f5da248.png

通过 ApiPost/Postman 工具测试 登录

beb1a565d78f4736a31d6c6f063aa23c.png

四、写在最后(附源码)

至此,开发博客的项目(API 对接 MySQL)就完成了。


后续会对该项目进行多次重构【多种框架(express,koa)和数据库(mysql,sequelize,mongodb)】


如果你需要该项目的 源码,请通过本篇文章最下面的方式 加入 进来~~

45fc82a82c6542bdb2ff4986377d8db3.png

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
1天前
|
JavaScript 前端开发 IDE
【TypeScript技术专栏】TypeScript与Node.js后端开发
【4月更文挑战第30天】TypeScript在Node.js后端开发中日益重要,作为JavaScript超集,它提供静态类型检查和面向对象编程,增强代码可靠性和维护性。集成TypeScript能带来类型安全、更好的IDE体验、易于维护的代码以及增强工具支持。通过安装TypeScript编译器、编写TypeScript文件、配置TSconfig,开发者可以在Node.js项目中利用其高级特性,提高代码质量和开发效率。实践案例显示,TypeScript能确保路由处理器的类型正确,降低错误率。随着社区发展,TypeScript成为提升Node.js开发体验的推荐选择。
|
1天前
|
缓存 前端开发 搜索推荐
【Flutter前端技术开发专栏】Flutter中的自定义绘制与Canvas API
【4月更文挑战第30天】Flutter允许开发者通过`CustomPaint`和`CustomPainter`进行自定义绘制,以实现丰富视觉效果。`CustomPaint` widget将`CustomPainter`应用到画布,而`CustomPainter`需实现`paint`和`shouldRepaint`方法。`paint`用于绘制图形,如示例中创建的`MyCirclePainter`绘制蓝色圆圈。Canvas API提供绘制形状、路径、文本和图片等功能。注意性能优化,避免不必要的重绘和利用缓存提升效率。自定义绘制让Flutter UI更具灵活性和个性化,但也需要图形学知识和性能意识。
【Flutter前端技术开发专栏】Flutter中的自定义绘制与Canvas API
|
1天前
|
缓存 监控 JavaScript
Node.js中构建RESTful API的最佳实践
【4月更文挑战第30天】本文介绍了在Node.js中构建RESTful API的最佳实践:选择合适的框架(如Express、Koa)、设计清晰的API接口(遵循HTTP动词和资源路径)、实现认证授权(JWT、OAuth 2.0)、错误处理、限流缓存、编写文档和测试,以及监控性能优化。这些实践有助于创建健壮、可维护和易用的API。
|
1天前
|
存储 关系型数据库 Go
【Go语言专栏】基于Go语言的RESTful API开发
【4月更文挑战第30天】本文介绍了使用Go语言开发RESTful API的方法,涵盖了路由、请求处理、数据存储和测试关键点。RESTful API基于HTTP协议,无状态且使用标准方法表示操作。在Go中,通过第三方库如`gorilla/mux`进行路由映射,使用`net/http`处理请求,与数据库交互可选ORM库`gorm`,测试则依赖于Go内置的`testing`框架。Go的简洁性和并发性使得它成为构建高效API的理想选择。
|
1天前
|
JSON API 数据处理
【Swift开发专栏】Swift中的RESTful API集成实战
【4月更文挑战第30天】本文探讨了在Swift中集成RESTful API的方法,涉及RESTful API的基础概念,如HTTP方法和设计原则,以及Swift的网络请求技术,如`URLSession`、`Alamofire`和`SwiftyJSON`。此外,还强调了数据处理、错误管理和异步操作的重要性。通过合理利用这些工具和策略,开发者能实现高效、稳定的API集成,提升应用性能和用户体验。
|
1天前
|
机器学习/深度学习 算法 安全
深度学习在图像识别中的应用与挑战构建高效可扩展的RESTful API:后端开发的实战指南
【4月更文挑战第30天】 随着计算机视觉技术的飞速发展,深度学习在图像识别领域取得了显著的成果。本文将探讨深度学习技术在图像识别中的应用及其所面临的挑战。首先,我们将介绍深度学习的基本原理和关键技术,然后分析其在图像识别中的优势和应用案例。最后,我们将讨论当前深度学习在图像识别领域所面临的主要挑战和未来的发展趋势。
|
1天前
|
JavaScript API 开发者
深入了解Node.js的文件系统:Node.js文件系统API的使用与探索
【4月更文挑战第30天】本文深入探讨了Node.js的文件系统API,介绍了如何引入`fs`模块进行文件操作。内容包括异步读取和写入文件、删除文件、创建目录以及使用文件流进行高效操作。此外,还提到了文件系统的监视功能,帮助开发者全面掌握在Node.js中处理文件和目录的方法。
|
2天前
|
XML JSON API
【PHP开发专栏】PHP RESTful API设计与开发
【4月更文挑战第29天】本文探讨了在Web开发中流行的前后端分离模式,重点介绍了RESTful API的设计与实现。REST是一种基于HTTP协议的架构风格,核心概念包括资源、表述和状态转换。RESTful API设计遵循无状态、统一接口等原则,使用GET、POST、PUT、DELETE等HTTP方法执行操作,并通过状态码和JSON/XML传输数据。在PHP中实现RESTful API,可通过定义路由、创建控制器、处理请求和响应,同时注意安全性措施,如使用HTTPS。文中还提供了一个用户管理API的实战示例,以帮助读者更好地理解和应用RESTful API。
|
8天前
|
SQL 存储 关系型数据库
MySQL Cluster集群安装及使用
MySQL Cluster集群安装及使用
|
12天前
|
关系型数据库 MySQL 数据库
《MySQL 简易速速上手小册》第1章:MySQL 基础和安装(2024 最新版)
《MySQL 简易速速上手小册》第1章:MySQL 基础和安装(2024 最新版)
36 4