Skip to content

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为定义

image.png

解决方法:注释plugins: [createdPlugin, [updatedPlugin, pluginOptions]],,具体原因我也暂时没找到,但是注释掉使用不受影响

警告二: useUnifiedTopology: true

image.png

解决方法: 给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;

进阶使用

基本思路:

  1. 封装baseController基类,基类里面添加validate方法,和fail方法,validate方法进行参数校验, 校验失败直接返回用户失败原因
  2. 某个模块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文档

image.png

添加自定义规则

若是不能满足要求,可以自定义校验规则,并在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 ,';
        }
    }
};