中间件简单来说就是一个函数 自带参数
ctx,next
ctx 接收前端参数,同时可以在 ctx 上添加属性这样其他中间件都可以获取例如下方 ctx.state.userInfo
中间件逻辑处理好需要 await next();
放行
例:验证 token
middleware/auth.js
import response from "../utils/response.js";
import { checkToken } from "../utils/token.js";
const auth = async (ctx, next) => {
try {
const { authorization } = ctx.request.header;
const token = authorization.replace("Bearer ", "");
const userInfo = checkToken(token);
ctx.state.userInfo = userInfo;
await next();
} catch (error) {
let message = "";
switch (error.name) {
case "TokenExpiredError":
message = "token 过期";
break;
default:
message = "token 错误";
break;
}
response.error(ctx, { message, data: error });
}
};
export { auth };
router/user.js
import { auth } from "../middleware/auth.js";
// 获取用户列表
router.get("/", auth, userController.index);
package.json
{
"type": "module"
}
引入文件路径要写全不能省略如 index
index.js
全局变量不能使用
import { fileURLToPath } from "url";
import path from "path";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(fileURLToPath(import.meta.url));
console.log(__filename);
console.log(__dirname);
npm install @koa/router
src/router/user.js
import KoaRouter from "@koa/router";
// 路由前缀
const router = new KoaRouter({ prefix: "/users" });
router.get("/", (ctx) => {
ctx.body = {
msg: "123",
};
});
export default router;
注册
import router from "./router/user.js";
app.use(router.routes());
实现了不管 router 下有多少路由文件,都可以自动导入
src/router/index.js
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";
import KoaRouter from "@koa/router";
const router = new KoaRouter();
const __dirname = path.dirname(fileURLToPath(import.meta.url));
fs.readdirSync(__dirname).forEach(async (file) => {
if (file !== "index.js") {
const r = await import("./" + file);
router.use(r.default.routes()); // require 没有 default
}
});
export default router;
注册
import router from "./router/index.js";
app.use(router.routes()).use(router.allowedMethods());
npm i sequelize mysql2
src/db/index.js
import { Sequelize } from "sequelize";
import config from "../config/index.js";
const sequelize = new Sequelize(config.MYSQL_DB, config.MYSQL_USER, config.MYSQL_PWD, {
host: config.MYSQL_HOST,
dialect: "mysql",
});
// 测试连接
// (async function () {
// try {
// await sequelize.authenticate();
// console.log("Connection has been established successfully.");
// } catch (error) {
// console.error("Unable to connect to the database:", error);
// }
// })();
export default sequelize;
src/model/userModel.js
import { DataTypes } from "sequelize";
import sequelize from "../db/index.js";
import { crpytPassword } from "../utils/crypt.js";
const User = sequelize.define(
"xr_user",
{
// 在这里定义模型属性
userName: {
type: DataTypes.STRING,
// 不允许为 null 默认为 true
unique: true,
allowNull: false,
comment: "用户名",
},
password: {
type: DataTypes.STRING,
allowNull: false,
comment: "密码",
set(val) {
this.setDataValue("password", crpytPassword(val));
},
},
isAdmin: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: 0,
comment: "是否为管理员 1是 0不是",
},
},
{
// 这是其他模型参数
}
);
// 生成表
// User.sync({ alter: true });
export default User;
src/service/userService
import User from "../model/userModel.js";
class UserService {
// 获取所有用户
async findAll({ page, limit }) {
try {
const offset = (page - 1) * limit;
const { count, rows } = await User.findAndCountAll({
limit: ~~limit,
offset,
attributes: ["id", "userName", "isAdmin"],
});
return { count, rows };
} catch (error) {
console.error("error", error);
}
}
// 查找用户
async find(userName) {
try {
const res = await User.findOne({
where: {
userName,
},
});
if (res !== null) return res?.dataValues;
else return false;
} catch (error) {
console.error("error", error);
}
}
// 创建用户
async create(data) {
try {
const res = await User.create(data);
// 取消 password 字段返回
const { password, ...rest } = res?.dataValues;
return rest;
} catch (error) {
console.error("error", error);
}
}
}
export default new UserService();
get/set 中使用其他属性 - this.userName
password: {
type: DataTypes.CHAR(128),
allowNull: false,
comment: "密码",
get() {
// 获取值
let name = this.getDataValue("password");
return name ? name + "abc" : "zs";
},
},
password: {
type: DataTypes.CHAR(128),
allowNull: false,
comment: "密码",
set(val) {
// 设置值
this.setDataValue("password", crpytPassword(val));
},
},
invented: {
type: DataTypes.VIRTUAL,
get() {
return `${this.userName} - ${this.password}`;
},
},