# koa2-sql 增删改查 **Repository Path**: zhanhongzhu/koa2-sql ## Basic Information - **Project Name**: koa2-sql 增删改查 - **Description**: koa2-sql 增删改查 示例 - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 6 - **Forks**: 1 - **Created**: 2022-03-15 - **Last Updated**: 2024-06-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## 一、nodejs【Koa2+mysql 】搭建用户信息注册和登录接口服务 ## koa2 官网 [https://koa.bootcss.com/](https://koa.bootcss.com/) ## 什么是koa? Koa 是一个新的 web 框架,由 Express 幕后的原班人马打造, 致力于成为 web 应用和 API 开发领域中的一个更小、更富有表现力、更健壮的基石。 通过利用 async 函数,Koa 帮你丢弃回调函数,并有力地增强错误处理。 Koa 并没有捆绑任何中间件, 而是提供了一套优雅的方法,帮助您快速而愉快地编写服务端应用程序。 ## 初始化koa项目 ```javascript npm init ``` ## 安装koa ```javascript npm i koa ``` ## 新建一个app.js ```javascript // 导入koa const Koa = require('koa') // 创建一个koa对象 const app = new Koa() //监听端口 const port = 3000 app.listen(port); console.log(`启动成功,服务端口为:${port}`) ``` ## 运行app.js ```javascript node app.js // console.log(`启动成功,服务端口为:${port}`) ``` ## 添加启动脚本命令 ```js //package.json "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "dev":"node app.js" } ``` 可以运行 `npm run dev`启动我们的服务。 ## 使用 www 启动服务 在根目录建立 bin文件夹,然后新建 www文件 ```js // bin/www var app = require('../app'); var http = require('http'); var server = http.createServer(app); //服务监听端口 server.listen('3001'); ``` ## 配置www启动脚本 ```js //package.json "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "dev":"node bin/www" } ``` 然后 `npm run dev`就能启动了。 ## 加点服务的返回内容 ```js // 导入koa const Koa = require('koa') // 创建一个koa对象 const app = new Koa() //返回的内容 app.use(async ctx => { ctx.body = 'Hello World'; }); //监听端口 const port = 3000 app.listen(port); console.log(`启动成功,服务端口为:${port}`) ``` ![图片.png](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2fb85c60816c44d9b78e5070aabb5970~tplv-k3u1fbpfcp-watermark.image?) ## 安装中间件 koa-bodyparser 这个中间件可以将post请求的参数转为json格式返回; ```js npm install --save koa-bodyparser ``` ## bodyparser 使用 ```js // 导入koa const Koa = require('koa') const bodyParser = require('koa-bodyparser'); // 创建一个koa对象 const app = new Koa() app.use(bodyParser()); // request.method可以获取请求方法。 // get,post或者其他类型(request对象被封在ctx内,所以也可以ctx.method获取) app.use(async (ctx) => { if (ctx.url === '/' && ctx.method === 'POST') { ctx.body = ctx.request.body } else { // 其他请求显示404 ctx.body = '

404!

' } }) //监听端口 const port = 3000 app.listen(port); console.log(`启动成功,服务端口为:${port}`) ``` 开始写接口之前,我们安装一下路由 Koa-router Koa-router是 koa 的一个路由中间件,它可以将请求的URL和方法(如:`GET` 、 `POST` 、 `PUT` 、 `DELETE` 等) 匹配到对应的响应程序或页面。 ```js npm install koa-router --save ``` ## 使用koa-router ```js const Router = require('koa-router'); // 引入koa-router const router = new Router(); // 创建路由,支持传递参数 // 指定一个url匹配 router.get('/', async (ctx) => { ctx.type = 'html'; ctx.body = '

hello world!

'; }) // 调用router.routes()来组装匹配好的路由,返回一个合并好的中间件 // 调用router.allowedMethods()获得一个中间件,当发送了不符合的请求时,会返回 `405 Method Not Allowed` 或 `501 Not Implemented` app.use(router.routes()); app.use(router.allowedMethods({ // throw: true, // 抛出错误,代替设置响应头状态 // notImplemented: () => '不支持当前请求所需要的功能', // methodNotAllowed: () => '不支持的请求方式' })); ``` ## koa-router 不同请求方式 Koa-router 请求方式: get 、 put 、 post 、 patch 、 delete 、 del ,而使用方法就是 router.方式() ,比如 router.get() 和 router.post() 。而 router.all() 会匹配所有的请求方法。 ```js // 指定一个url匹配 router.get('/test', async (ctx) => { ctx.type = 'html'; ctx.body = '

hello world!

'; }) router.get("/user", async (ctx) => { ctx.body = '叫我詹躲躲'; }) ``` ![图片.png](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ff43d977ac7f495483fed3c6b458ac42~tplv-k3u1fbpfcp-watermark.image?) ## 新建router/index.js 路由文件夹 ```js // router/index.js const Router = require('koa-router') const router = new Router() //接口函数 class UserController { // 新增一条数据 async getUserName(ctx) { ctx.body = { code: 200, message: '叫我詹躲躲', type: 'warning' } } } //实例 const userController = new UserController() // 测试 router.get('/test', userController.getUserName) module.exports = router ``` 测试一下 ![图片.png](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ee690303244e447894c789b68b10300f~tplv-k3u1fbpfcp-watermark.image?) ## 安装中间件 koa2-cors cors跨域资源共享是一种机制,用来允许不同源服务器上的指定资源可以被特定的Web应用访问。 ## cors 安装 ```js npm install koa-cors --save ``` ## cors 使用 ```js //app.js const Cors = require('koa2-cors') app.use(Cors()) ``` ## koa连接数据库(mysql) 需要安装sql依赖; ```js npm install mysql --save ``` ## SQL配置 新建一个 sql文件夹,主要用于存放sql的各种操作; `sql/config.js` ```js const mysqlConfig = { user: "Koa", //账号 password: "Koa", //密码 database: "Koa", //数据库 host: "122.112.172.87", //服务器地址 port: 3306, //数据库端口 timezone: '08:00' }; module.exports = mysqlConfig; ``` ## koa封装sql数据库query函数 ```js //sql/query.js const mysql = require("mysql"); const config = require("./config"); //创建连接池 const pool = mysql.createPool(config); const query = (sql, val) => { return new Promise((resolve, reject) => { pool.getConnection(function (err, connection) { if (err) { reject(err); } else { connection.query(sql, val, (err, fields) => { if (err) { reject(err); } else { resolve(fields); } connection.release(); }); } }); }); }; module.exports = { query }; ``` ## 新增接口 - 用户信息注册 和 登录 新建两个文件夹 controller 和 model controller主要存放操作和数据处理的一些逻辑 ```js // controller/userController.js // 用户注册 const User = require('../model/userModel') class UserController { // 用户注册 async register(ctx) { let { name, tel, password } = ctx.request.body const names = await User.getUser(name) //用户名是否重复 const tels = await User.getTel(tel) //手机号是否重复 if (tels.length > 0) { ctx.body = { type: 'warning', message: '该手机号已注册' } } else { if (names.length > 0) { ctx.body = { type: 'error', message: '用户名已存在' } } else { await User.insert(name, tel, password) ctx.body = { type: 'success', code: 0, message: '注册成功' } } } } // 登录 async login(ctx) { let tel = ctx.request.body.tel let password = ctx.request.body.password const res = (await User.getTel(tel))[0] if (res) { if (res.password == password) { ctx.body = { code: 0, data: { name: res.name, tel: res.tel }, message: '登录成功', type: 'success' } } else { ctx.body = { type: 'error', message: '用户名或密码不正确' } } } else { ctx.body = { type: 'error', message: '用户名不存在' } } } } module.exports = new UserController() ``` ## model中操作数据库的函数(包含数据库语句) ```js // model/userModel.js const query = require('../sql/query') class UserModel { //获取用户 async getUser(name) { return await query(`SELECT * FROM user WHERE name = '${name}'`) } //获取用户手机号 async getTel(tel) { return await query(`SELECT * FROM user WHERE tel = '${tel}'`) } //用户注册 async insert(name, tel, password) { return await query(`INSERT INTO user(name, tel, password) VALUES('${name}', '${tel}', '${password}')`) } } module.exports = new UserModel() ``` ## 在router路由文件里面注册 ```js //router/index.js const Router = require('koa-router') const router = new Router() //用户 const UserController = require('../controller/UserController') //用户注册 router.post('/register', UserController.register) //用户信息登录 router.post('/login', UserController.login) module.exports = router ``` ## 接口调用 使用post请求就可以调用 /register 和 /login两个接口啦;当然也可以再封装其他更多的接口。 ## 结尾 到此 用户的注册和登录接口就写完了。后续继续其他功能添加。有兴趣的可以查看源码 [源码地址](https://gitee.com/zhanhongzhu/koa2-sql),一起学习,一起加油。我是叫我詹躲躲,很高兴认识你。 ## 二、【nodejs进阶之旅(2)】:使用koa2+mysql 实现列表数据分页 ## 1.展示效果(分页) ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d6911165a9044de8ac6f5ada159ba36d~tplv-k3u1fbpfcp-zoom-1.image) ## 2.分页主要字段 分页主要字段包括 pageSize 每页条数、pageNum 第几页、startRow 当前开始页编号、endRow 当前结束页编号、total 总数量。主要是根据前端分页的参数,进行处理后,返回前端正确的数据,其实是一个很常见且简单的功能。但是是非常也是非常重要的。 ```js pageSize 每页条数 pageNum 第几页 startRow 当前开始页编号 endRow 当前结束页编号 total 总数量 ``` ## 计算 3.startRow 和 endRow 封装成一个函数 ```js /* 分页公共函数*/ module.exports = handlePages = (pageNum, pageSize, total) => { let startRow = total > 0 ? ((pageNum - 1) * pageSize + 1) : 0; let endRow = pageNum * pageSize <= total ? pageNum * pageSize : total; return { pageNum, pageSize, recordCounts:total, startRow, endRow } } ``` ## 4.接口函数中使用该函数 从前端传参中获取,分页所需要的数据。 ```js let { nickname, name, role, pageSize, pageNum } = ctx.request.body; //此处进行处理 let pageNum1 = (pageNum - 1) * pageSize ``` ```js //获取用户信息列表 async getAllUserList(ctx) { let { nickname, name, role, pageSize, pageNum } = ctx.request.body let res = [] let pageNum1 = (pageNum - 1) * pageSize let total = (await User.getAllUserListTotal())[0].recordCounts if (!nickname && !name && !role) { res = (await User.getAllUserListNotCond(pageSize, pageNum1)) } else { res = (await User.getAllUserList(nickname, name, role, pageSize, pageNum1)) } ctx.body = { code: 0, data: res.map(v => { if (v.password) { delete v.password } return v }), //分页所有的参数 ...handlePages(pageNum, pageSize, total) } } ``` ## 5.分页中的MySql语句 ### 根据分页查询数据库的数据 ```js //根据分页查询用户列表 async getAllUserListNotCond(pageSize, pageNum) { return await query(`SELECT * FROM user LIMIT ${pageNum},${pageSize}`) } ``` ## mySql获取数据库数据总条数 ```js //获取用户信息列表的总条数 async getAllUserListTotal() { return await query(`SELECT COUNT(*) as recordCounts FROM user`) } ``` ## 关于mySql的COUNT()函数 作用:COUNT() 函数返回匹配指定条件的行数。 ### SQL COUNT(column_name) 语法 COUNT(column_name) 函数返回指定列的值的数目(NULL 不计入): ```js SELECT COUNT(column_name) FROM table_name ``` ### SQL COUNT(*) 语法 COUNT(*) 函数返回表中的记录数: ```js SELECT COUNT(*) FROM table_name ``` ### SQL COUNT(DISTINCT column_name) 语法 COUNT(DISTINCT column_name) 函数返回指定列的不同值的数目: ```js SELECT COUNT(DISTINCT column_name) FROM table_name ``` ## 6.切换分页的效果 切换分页后的效果 还是很正常的。 ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b32e07c525804f208e544192ea85a18b~tplv-k3u1fbpfcp-zoom-1.image) ## 7.总结 主要是包含mysql的基本使用。目前还在学习当中,有不当的地方,欢迎指正和一起交流学习。目前正在处理权限管理模块。下一篇文章将讲解如何进行权限控制,有兴趣的可以继续关注。