1、前言
这记录的是我使用koa2写后端接口的一些步骤。
- 结合这篇使用ejs实现一键自动化生成代码模版阅读更佳噢!!!
- 完整毕设后端项目见此:点击跳转
前期简单安装一些依赖(根据需要再添加)
-
npm init -y
-
npm install koa
-
npm install nodemon -D
--开发依赖 -
npm install dotenv
,可加载根目录下的.env
文件,将里面的直接加载到环境变量里面process.env
-
npm install koa-router
路由库 -
npm install koa-bodyparser
:中间件,解析json
数据 -
npm install mysql2
连接数据库
2、文件目录拆分
-
src
app
:主体部分constants
:放一些常量controller
:控制器,写一些逻辑操作,比如,获取我们输入的信息,再调用service
中操作数据库的方法middleware
:中间件,比如验证授权、验证输入的账号密码是否正确/存在、验证token
是否已过期等router
:路由层,在这个文件夹中写路由service
:service
层,就是操作数据库的一些方法utils
:放一些可以用到的方法,比如读取文件的方法main.js
:程序的入口,这个入口,越简单越好
-
.env
:一些不能写死的环境变量,比如,服务端口port
,数据库的一些信息,抽离到这个文件中
3、写接口的步骤
-
习惯性依次的创建
xxx.router.js
、xxx.middleware.js
、xxx.controller.js
、xxx.service.js
这几个文件,当然xxx.middleware.js
这个可根据需求决定是否需要创建,或者引用已经创建好的中间件文件 -
事例如下:
(1)在router
文件夹中创建文件,如:department.router.js
// 请求路径 中间件处理的 映射
const Router = require('koa-router');
// 中间件
// 具体的处理逻辑 增删改查
const {
list,
create,
update,
remove
} = require('../controller/department.controller');
// 前缀:
const deportmentRouter = new Router({
prefix: '/api/department'
});
deportmentRouter.post('/', create);
deportmentRouter.get('/list', list);
deportmentRouter.patch('/:departmentId', update);
deportmentRouter.delete('/:departmentId', remove);
// 导出
module.exports = deportmentRouter;
(2)在middleware
文件夹下创建auth.middleware.js
文件
- 未进行鉴权
(3)在controller
文件夹中创建文件,如:department.controller.js
const departmentService = require('../service/department.service')
class DepartmentController {
async list(ctx, next) {
// 1.获取数据(offset/size)
const {
offset,
size
} = ctx.query;
// 2.查询列表
const {
result,
count
} = await departmentService.getDepartmentList(offset, size);
ctx.body = {
code: 200,
data: result,
totalCount: count[0].total
};
}
async create(ctx, next) {
// 获取用户请求传递的参数
const department = ctx.request.body;
// 查询数据库 -> 抽离到service
const result = await departmentService.create(department);
// 返回结果
ctx.body = {
code: 200,
data: result
};
}
async update(ctx, next) {
const {
departmentId
} = ctx.params;
const {
departmentName,
principal,
adviser,
departmentTotal
} = ctx.request.body;
const result = await departmentService.update(departmentName, principal, adviser, departmentTotal, departmentId);
ctx.body = {
code: 200,
data: result
};
}
async remove(ctx, next) {
// 1.
const {
departmentId
} = ctx.params;
// 2.删除内容
const result = await departmentService.remove(departmentId);
ctx.body = {
code: 200,
data: result
};
}
}
module.exports = new DepartmentController();
(4)在service
文件夹下创建department.service.js
文件
const connection = require('../app/database');
class DeportmentService {
async getDepartmentList(offset, size) {
const statement = `
SELECT
d.id id, d.department_name departmentName, d.principal principal, d.adviser adviser, d.department_total departmentTotal, d.createAt createAt, d.updateAt updateAt
FROM department d
LIMIT ?, ?;
`;
const state = `SELECT COUNT(*) total FROM department`;
const [result] = await connection.execute(statement, [offset, size]);
const [count] = await connection.execute(state);
return {
result,
count
};
}
async create(deportment) {
const {
departmentName,
principal,
adviser,
departmentTotal
} = deportment;
// 使用sql语句将user存储到数据库中
const statement = `INSERT INTO department (department_name, principal, adviser, department_total) VALUES (?, ?, ?, ?);`;
const result = await connection.execute(statement, [departmentName, principal, adviser, departmentTotal]);
return result[0];
}
async update(departmentName, principal, adviser, departmentTotal, deportmentId) {
const statement = `UPDATE department SET department_name = ?, principal = ?, adviser = ?, department_total = ? WHERE id = ?;`;
const [result] = await connection.execute(statement, [departmentName, principal, adviser, departmentTotal, deportmentId]);
return result;
}
async remove(deportmentId) {
const statement = `DELETE FROM department WHERE id = ?;`;
const [result] = await connection.execute(statement, [deportmentId]);
return result;
}
}
module.exports = new DeportmentService();
4、app文件夹中的一些内容
(1)index.js
const Koa = require('koa');
// 导入bodyParser中间件,解析json
const bodyParser = require('koa-bodyparser')
// 导入错误信息处置方法
const errorHandler = require('./error-handle');
// 导入路由 升级版 动态加载路由
const useRoutes = require('../router');
const app = new Koa();
app.use(bodyParser());
useRoutes(app);
app.on('error', errorHandler);
module.exports = app;
(2)database.js
const mysql = require('mysql2');
const config = require('./config');
// 创建连接池,与数据库进行连接
const connections = mysql.createPool({
host: config.MYSQL_HOST,
port: config.MYSQL_PORT,
database: config.MYSQL_DATABASE,
user: config.MYSQL_USER,
password: config.MYSQL_PASSWORD
});
// 测试
connections.getConnection((err, conn) => {
// err为空即为成功
conn.connect((err) => {
if (err) {
console.log("数据库连接失败", err)
} else {
console.log("数据库连接成功")
}
})
});
// 通过promise操作数据库
module.exports = connections.promise();
(3)config.js
// 可加载根目录下的.env文件,将里面的直接加载到环境变量里面
const dotenv = require('dotenv');
const fs = require('fs');
const path = require('path');
dotenv.config();
module.exports = {
APP_HOST,
APP_PORT,
MYSQL_HOST,
MYSQL_PORT,
MYSQL_DATABASE,
MYSQL_USER,
MYSQL_PASSWORD,
} = process.env;
(4)error-handle.js
const errorType = require('../constants/error-types');
const errorHandler = (error, ctx) => {
let status, message;
switch (error.message) {
case errorType.NAME_OR_PASSWORD_IS_REQUIRED:
status = 400; // Bad Request
message = "用户名或者密码不能为空!";
break;
case errorType.USER_ALREADY_EXISTS:
status = 409; // Conflict 冲突
message = "用户名已存在!";
break;
case errorType.USER_DOES_NOT_EXISTS:
status = 400; // 参数错误
message = "用户名不存在!";
break;
case errorType.PASSWORD_IS_INCORRENT:
status = 400; // 参数错误
message = "密码错误!";
break;
case errorType.UNAUTHORIZATION:
status = 401; // 参数错误
message = "无效的token!";
break;
case errorType.UNPERMISSION:
status = 401; // 参数错误
message = "你不具备操作权限!";
break;
default:
status = 404;
message = "NOT FOUND";
}
ctx.status = status;
ctx.body = message;
}
module.exports = errorHandler;
5、.env文件中的内容
APP_HOST = http://localhost
APP_PORT = 9999
MYSQL_HOST = localhost
MYSQL_PORT = 3306
MYSQL_DATABASE = kylinKoa
MYSQL_USER = root
MYSQL_PASSWORD = root
6、读取文件的方法
// 读取文件的工具方法
const fs = require('fs')
module.exports.getFileJsonData = (filePath) => {
// 根据文件的路径, 读取文件的内容
return new Promise((resolve, reject) => {
fs.readFile(filePath, 'utf-8', (error, data) => {
if(error) {
// 读取文件失败
reject(error)
} else {
// 读取文件成功
resolve(data)
}
})
})
}