主题
Egg实践
一. Egg是什么
Egg是阿里基于koa封装的一个企业级框架,Egg 以 Koa 作为其基础框架,在它的模型基础上,进一步对它进行了一些增强。 更多信息直接查看官方文档:https://www.eggjs.org/zh-CN/intro
二. Egg实践
Egg连接mongoDB
插件egg-mongoose
,插件地址
步骤一:下载安装egg-mongoose
js
npm i egg-mongoose --save
步骤二:更改{app_root}/config/plugin.js启用egg-mongoose插件:
js
// config/plugin.js
module.exports = {
mongoose: {
enable: true,
package: "egg-mongoose"
}
};
步骤三:配置数据库连接
若是生产环境下的配置,在config.prod.js下下配置,开发环境则在config.local.js下写配置,公共配置在config.default.js下配置,项目启动后,egg会根据运行环境,合并config.default.js与对应环境的配置
js
// {app_root}/config/config.default.js
/* 配置方式一 */
exports.mongoose = {
url: 'mongodb://127.0.0.1/example', // 无密码 example是数据,若不存在则会自动创建
// url: 'mongodb://username:password@127.0.0.1:27017/example', // 有密码 example是数据,若不存在则会自动创建
options: {},
// mongoose global plugins, expected a function or an array of function and options
plugins: [createdPlugin, [updatedPlugin, pluginOptions]],
};
/* 配置方式二 */
exports.mongoose = {
client: {
url: 'mongodb://127.0.0.1/example',
options: {},
// mongoose global plugins, expected a function or an array of function and options
plugins: [createdPlugin, [updatedPlugin, pluginOptions]],
},
};
说明:
- ① url字段中
example
是数据,若不存在则会自动创建。
特别注意:
报错一:按照上面的配置写可能会报错,createdPlugin为定义
解决方法:注释plugins: [createdPlugin, [updatedPlugin, pluginOptions]],,具体原因我也暂时没找到,但是注释掉使用不受影响
警告二: useUnifiedTopology: true
解决方法: 给options添加配置 useUnifiedTopology: true
,
最终配置:
js
config.mongoose = {
url: "mongodb://user:123456@180.76.177.217:27017/blog-2022",
options: {
useUnifiedTopology: true,
useNewUrlParser: true
}
// mongoose global plugins, expected a function or an array of function and options
// plugins: [createdPlugin, [updatedPlugin, pluginOptions]]
};
egg-validate校验参数
egg-validate是基于parameter的。 egg-validate插件的地址:https://github.com/eggjs/egg-validate
步骤一:下载安装
bash
npm i egg-validate --save
步骤二:启用插件
js
// config/plugin.js
exports.validate = {
enable: true,
package: 'egg-validate',
};
步骤三:配置插件
js
// config/config.default.js
exports.validate = {
convert: true, // 开启参数可以使用convertType规则进行类型转换类型转换 ,例如:("1"->1)
validateRoot: false, // 限制被验证值必须是一个对象,建议关闭。
widelyUndefined: true, // 将'', null NaN 统一转换成undefined,方便处理
};
使用
js
// app/controller/home.js
const Controller = require('egg').Controller;
class HomeController extends Controller {
async index() {
const { ctx, app } = this;
ctx.validate({ id: 'int' },ctx.request.body); // ctx.validate(rules: any, data?: any): void
// or
const errors = app.validator.validate({ id: 'int' }, ctx.request.body);
}
}
module.exports = HomeController;
进阶使用
基本思路:
- 封装baseController基类,基类里面添加validate方法,和fail方法,validate方法进行参数校验, 校验失败直接返回用户失败原因
- 某个模块controller继承基类,需要校验参数的地方直接调用validate方法进行参数校验即可
基类的封装
js
"use strict";
const Controller = require("egg").Controller;
class BaseController extends Controller {
/**
* 参数校验
* @param {Object} rules 校验规则
* @param {Object} params 前端传入参数
* @returns Boolean 通过-true 不通过-false
*/
valieate(rules, params) {
const { ctx } = this;
try {
ctx.validate(rules, params);
return true;
} catch (error) {
// console.log(error.errors); // [ { message: 'should be an integer', code: 'invalid', field: 'id' } ]
let invalid = error.errors[0];
if(invalid !== null && typeof invalid === 'object') {
let msg = `参数${invalid.field}校验失败,${invalid.message}`;
this.fail(msg);
}else{
this.fail(invalid)
}
return false;
}
}
fail(msg = "") {
return (this.ctx.body = {
code: 1,
msg
});
}
success(data = null, msg = "") {
return (this.ctx.body = {
code: 0,
data,
msg
});
}
}
module.exports = Base_controllerController;
参数校验
js
"use strict";
const Base_Controller = require("../BassClass/base_controller");
class HomeController extends Base_Controller {
async index() {
const paramsRules = {
id: "int"
};
const { ctx } = this;
if (!this.valieate(paramsRules, ctx.query)) return;
// 请求走到这儿,说明参数校验已经符合校验规则paramsRules
this.success('hi Egg')
}
}
module.exports = HomeController;
校验规则
parameter提供了一些常用的校验规则,具体参见parameter文档,
添加自定义规则
若是不能满足要求,可以自定义校验规则,并在app.js
文件内进行添加,当egg项目启动后,会加载addRules里面的规则
例如:
js
//app.js
app.validator.addRule('jsonString', (rule, value) => {
try {
JSON.parse(value);
} catch (err) {
return 'must be json string';
}
});
const customRule = require('../app/utils/customRule.js')
// 注册validator自定义rule
for (let [rule, checker] of Object.entries(customRule)) {
app.validator.addRule(rule, checker);
}
// 或者自动加载
// /app/utils/customRule.js
module.exports = {
articleName: (rule, value) => {
if (typeof value !== 'string') {
return 'must be string';
}
if (value.match(/\d/g) && value.match(/[^\d,]/g)) {
return 'should only contain integer and ,';
}
}
};