统一规范
异常处理
一般异常 都是全局处理
先写工具类
- 在
app/exception
文件夹 新建一个http.js
文件
js
class HttpException extends Error {
constructor(
code = 50000,
message = "服务器异常",
stack = null,
httpCode = 500
) {
super();
this.code = code;
// 自定义状态码
this.msg = message;
// 自定义返回消息
this.stack = stack;
// 自定义返回数据
this.httpCode = httpCode;
// http状态码
}
}
module.exports = HttpException;
写中间件
- 在
app/middleware
文件夹 新建一个error.js
文件
js
const HttpException = require("../exception/http");
module.exports = () => {
return async function errorHandler(ctx, next) {
const method = ctx.request.method;
// 当请求方法为OPTIONS,通常为axios做验证请求,直接响应httpStatus204 no content即可
if (method === "OPTIONS") {
ctx.status = 204;
return;
}
try {
// 在这里捕获程序中的异常
await next();
// 404 页面就自己定义
if (ctx.status === 404 && !ctx.body) {
console.log(ctx);
if (ctx.request.header["content-type"]) {
ctx.body = { code: 404, msg: "接口不存在", data: "" };
} else {
// 跳转到404页面
ctx.redirect("/");
}
}
} catch (err) {
console.log(err);
// 判断异常是不是自定义异常
if (err instanceof HttpException) {
ctx.status = err.httpCode;
console.log(err.httpCode);
ctx.body = { code: err.code, msg: err.msg, data: err.stack };
return;
}
// ... 其他异常处理,例如egg参数校验异常,可以在这里处理 // 最后其他异常统一处理
ctx.status = 500;
ctx.body = {
code: 500,
msg: err.message || "服务器异常",
data: err.stack,
};
}
};
};
挂载到全局
- 在
config/config.default.js
文件中添加
js
config.middleware = ["error"];
返回格式
继承
- 在 controller 文件夹中新建一个
base.js
文件作为基类
js
"use strict";
const Controller = require("egg").Controller;
class ResponsedataController extends Controller {
async response(data = null, message = "success", code = 200) {
const { ctx } = this;
ctx.status = 200;
ctx.body = {
code,
message,
data,
};
}
}
module.exports = ResponsedataController;
- 在其他 controller 文件中继承
js
"use strict";
const Controller = require("egg").Controller;
const Base = require("../controller/base");
class HomeController extends Base {
async index() {
const { ctx } = this;
this.response(1, "成功", 200);
}
}
module.exports = HomeController;
静态类
- 在 utils 文件夹中新建一个
tool.js
文件
js
class ResponsedataController {
static async succss(data = null, message = "success", code = 200) {
return {
code,
message,
data,
};
}
}
module.exports = ResponsedataController;
- 在其他 controller 文件中调用
js
"use strict";
const Controller = require("egg").Controller;
const Tool = require("../utils/tool");
class HomeController extends Controller {
async index() {
const { ctx } = this;
ctx.body = Tool.succss(1, "成功", 200);
}
}
module.exports = HomeController;
参数校验
安装
bash
npm i egg-validate -S
配置
- 在
config/plugin.js
文件中添加
js
// 验证插件
exports.validate = {
enable: true,
package: "egg-validate",
};
- 在
config/config.default.js
中写入
js
// 验证配置
config.validate = {
// 配置项
// 配置参数校验器,基于parameter
convert: false, // 对参数可以使用 convertType 规则进行类型转换,类似数字666会转换成字符
// validateRoot: false, // 限制被验证值必须是一个对象。
widelyUndefined: true, // 开启后,会把空字符串,NaN,null 这些转成 undefined,将这些异常的数据进行了统一,方便后续处理。
};
使用
- 控制器里面调用
js
const BaseController = require("../base/base");
class ValidateController extends BaseController {
// 默认post
async post1() {
const { ctx, app } = this;
// 不执行了
const errors = app.validator.validate(
{
username: { type: "string", required: true },
password: { type: "string", required: true, min: 6, max: 10 },
},
ctx.request.body
);
if (errors) {
ctx.body = {
status: 200,
msg: errors,
};
} else {
const data = "通过了12121";
this.response(data, "通过了", 5000);
// throw new NotFoundException("没有找到数据");
}
}
// 自定义用户名规则
async post2() {
const { ctx, app } = this;
// 校验用户名是否正确
// 自定义post
app.validator.addRule("userName", (rule, value) => {
// value就是待检验的数据
if (/^\d+$/.test(value)) {
return "用户名应该是字符串";
} else if (value.length < 3 || value.length > 10) {
return "用户名的长度应该在3-10之间";
}
});
const errors = app.validator.validate(
{
username: { type: "userName" },
password: { type: "string", required: true },
},
ctx.request.body
);
if (errors) {
ctx.body = {
status: 200,
msg: errors,
};
} else {
ctx.body = "验证通过";
}
}
async get1() {
// 默认自由get
const { ctx, app } = this;
const errors = app.validator.validate(
{
username: { type: "string", required: true },
password: { type: "string", required: true },
},
ctx.request.query
);
if (errors) {
ctx.body = {
status: 200,
msg: errors,
};
} else {
ctx.body = "验证通过";
}
}
async get2() {
const { ctx, app } = this;
// 自定义 严格get
// 校验用户名是否正确
app.validator.addRule("userName", (rule, value) => {
// value就是待检验的数据
if (/^\d+$/.test(value)) {
return "用户名应该是字符串";
} else if (value.length < 3 || value.length > 10) {
return "用户名的长度应该在3-10之间";
}
});
const errors = app.validator.validate(
{
username: { type: "userName" },
password: { type: "string", required: true },
},
ctx.params
);
if (errors) {
ctx.body = {
status: 200,
msg: errors,
};
} else {
ctx.body = "验证通过";
}
}
}
module.exports = ValidateController;
- 路由
js
module.exports = (app) => {
const { router, controller } = app;
// router
const validateRouter = router.namespace("/validate");
validateRouter.post("/post1", controller.validate.validate.post1);
validateRouter.post("/post2", controller.validate.validate.post2);
validateRouter.get("/get1", controller.validate.validate.get1);
validateRouter.get(
"/get2/:username/:password",
controller.validate.validate.get2
);
};
- 调用
bash
http://127.0.0.1:7001/validate/get1?username=admin&password=admin
http://127.0.0.1:7001/validate/get2/admin/123456
http://127.0.0.1:7001/validate/post1/
http://127.0.0.1:7001/validate/post2/