日常作业中免不了频繁处理 GET/POST 的入参,你当然可以每个 action 中都重复地去做这些事情,

  • 从 query 或 body 取出入参,
  • 对可选的入参进行判空,
  • 处理入参的类型转换,
  • 对入参进行逻辑校验,数字是否超限,类型是否非法等...

但这些通用的逻辑可通过抽取到插件或服务中,避免代码冗余和重复劳动。

egg-validation

Egg.js 中可通过 egg-validation 插件来减少这部分的工作量。通过该插件,上面大部分工作可转成简单的配置。

安装插件

$ yarn add egg-validate

配置插件

启用:

config/plugin.ts

const plugin: EggPlugin = {
// ...
validate: {
enable: true,
package: 'egg-validate',
},
// ...
}; export default plugin;

配置插件:

config/config.default.ts

export default (appInfo: EggAppInfo) => {
const config = {} as PowerPartial<EggAppConfig>; // ...

config.validate = {

convert: true,

widelyUndefined:true

}; // ...

};

其配置项为 node-modules/parameter 的所有可用配置项,因为该插件其实就是后者的 Egg.js 封装。

  • convert 会对入参进行转换,建议开启。举个例子,使用表单中默认的 submit 类型按钮提交表单时,提交过来的往往是序列化后的字符串,那些期望是数字类型的字段就会始终验证不过。而开启此项后,会对入参按希望的类型进行转换。
  • widelyUndefined 开启后,会把空字符串,NaN,null 这些转成 undefined,将这些异常的数据进行了统一,方便后续处理。

使用

插件在 appcontext 上扩展了 validator 对象,通过调用 validator.validate(rules,data) 来进行验证。

比如接收一个名为 name 的字符串入参:

app/controller/home.ts

const errors = this.app.validator.validate({ name: 'string' }, this.request.body);
if (errors) {
this.ctx.body = errors;
}

验证规则

validate 第一个参数为规则,它是个对象。其每个字段对应同名的入参。字段的值可以是简单的字符串,指定字段的类型,也可以是对象,在这个对象里进行更加详细的规则指定。

const rules = {
param1: 'string', // 必填的字符串入参
param2: 'string?', // 可选的字符串入参
param3: {
type: 'int', // 整形入参
required: false, // 该入参可选
min: 0, // 该入参的最小值
max: 10, // 该入参的最大值
},
};

规则默认入参是必填的,对于可选的入参,可通过在类型后加问号,与 TypeScript 类似,也可以显式指定 required: false

预设可用的参数类型参见 parameter

针对参数的规则配置,根据参数的类型,有不同的配置顶,比如对于数字类型,可配置其最大最小值;对于枚举,可定义其候选值,一旦入参不在这些值之内,便验证不通过。每种类型可用的配置项参见 parameter

自定义验证规则

如果上面文档中预设的这些类型无法满足需求,可通过 validator.addRule(type,checker) 自定义规则来扩充。

其中 type 为新增规则的类型名, checker 为用来校验的正则或方法。如果是个方法,其入参为规则本身及需要校验的数据,文档里没有体现其入参,可参考源码

checker.call(self, rule, obj[key], obj);

比如增加一种类型为 jsonString 的验证规则,限定入参必需为合法的 JSON 数据。

app.ts

export default (app) => {
app.validator.addRule('jsonString', (_rule, value) => {
try {
JSON.parse(value);
} catch (err) {
return 'must be json string';
}
});
};

示例代码

一个可本地运行调试,配合了预设的验证规则及自定义的规则的示例,完整代码可在 GitHub 找到。

结论

写了过多的重复的代码后,比如这种入参的校验,就应该想想如何优雅地来处理这些重复的工作,无论是自己造轮子,还是找轮子。入参的校验如此之常见,进而,甚至可以去追求一套前后台通用的校验逻辑,将浏览器端的 JavaScript 与 Node.js 的逻辑进行统一。

相关资源

Egg.js 中入参的校验的更多相关文章

  1. 在egg.js中使用mongodb

    1.egg.js官网只推荐了mysqle,要用mongodb得另找资料.通过查找,大家都在用Mongoose连接,于是乎学习. 网站链接:https://www.npmjs.com/package/e ...

  2. Egg.js中使用sequelize事务

    对数据库的操作很多时候需要同时进行几个操作,比如需要同时改动几张表的数据,或者对同一张表中不同行(row)或列(column)做不同操作,比较典型的例子就是用户转账问题(A账户向B账号汇钱): 1 从 ...

  3. SpringBoot2 参数管理实践,入参出参与校验

    一.参数管理 在编程系统中,为了能写出良好的代码,会根据是各种设计模式.原则.约束等去规范代码,从而提高代码的可读性.复用性.可修改,实际上个人觉得,如果写出的代码很好,即别人修改也无法破坏原作者的思 ...

  4. egg.js路由的优雅改造

    引言 在使用express,koa, 或者是egg.js进行node server开发的过程中,我们的路由基本上都是定义在controller层的,框架对于 node 原生路由都会进行一层封装,一版都 ...

  5. vue+egg.js+mysql一个前后端分离留言板项目

    一.前序 我相信每个人前端搬运工和我想法都是一样的,都有一个做全栈的梦,无奈面对众多的后台语言,却不从下手,今天由我来带你们潜入全栈的门槛,注意是门槛.能不能学的会后面的内容全靠坚持了. 我今天主要做 ...

  6. springboot项目中接口入参的简单校验

    .katex { display: block; text-align: center; white-space: nowrap; } .katex-display > .katex > ...

  7. js的replace函数入参为function时的疑问

    近期在写js导出excel文件时运用到replace方法,此处详细的记录下它各个参数所代表的的意义. 定义和用法 replace() 方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式 ...

  8. js中函数传参的情况

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  9. (一)将mockjs集成到VUE中后,怎样根据接口入参返回mock结果

    1)安装mockjs,这一步跳过 2)在项目中建立mock模块,笔者的目录结构如下 mock模块与接口模块一一对应,有一个接口,就有一个mock 3)编写登陆模块mock接口,代码如下: import ...

随机推荐

  1. Visual Studio Code Tips

    新项目要用到Visual Studio Code, 在使用的过程中有些tips, 记录下来以便查阅. 1. 自动保存代码 文件 => 自动保存 2. 帮助输入代码模式 扩展 => 安装HT ...

  2. 基于ELK5.1(ElasticSearch, Logstash, Kibana)的一次整合测试

    前言开源实时日志分析ELK平台(ElasticSearch, Logstash, Kibana组成),能很方便的帮我们收集日志,进行集中化的管理,并且能很方便的进行日志的统计和检索,下面基于ELK的最 ...

  3. [Active Learning] Multi-Criteria-based Active Learning

    目录 1 Informativeness 2 Representativeness 3 Diversity 3.1 Global consideration 3.2 Local considerati ...

  4. SpringBoot之旅第六篇-启动原理及自定义starter

    一.引言 SpringBoot的一大优势就是Starter,由于SpringBoot有很多开箱即用的Starter依赖,使得我们开发变得简单,我们不需要过多的关注框架的配置. 在日常开发中,我们也会自 ...

  5. php架构之路

    鉴于最近跟小伙伴聊了很多PHP架构发展方向的问题,相关技术整理了一下,也顺便规划了一下自己的2019年. 一.常用的设计模式以及使用场景 以下是我用到过的   工厂,单例,策略,注册,适配,观察者,原 ...

  6. 死磕 java集合之ConcurrentLinkedQueue源码分析

    问题 (1)ConcurrentLinkedQueue是阻塞队列吗? (2)ConcurrentLinkedQueue如何保证并发安全? (3)ConcurrentLinkedQueue能用于线程池吗 ...

  7. WinForm的DataGirdView判断CheckBox是否被选中

    首先我们先设置下DataGirdView的列. 然后启动下编辑,就可以选中与不选中了.在之后通过. #region 便利被选中的行,然后导出 DataTable dtreport = new Data ...

  8. Android 网络优化,使用 HTTPDNS 优化 DNS,从原理到 OkHttp 集成

    一.前言 谈到优化,首先第一步,肯定是把一个大功能,拆分成一个个细小的环节,再单个拎出来找到可以优化的点,App 的网络优化也是如此. 在 App 访问网络的时候,DNS 解析是网络请求的第一步,默认 ...

  9. PdfReader按页将PDF切割成多个PDF

    private MemoryStream GetNewPdfByPageNum(PdfReader pdfReader, int pageNum) { MemoryStream memoryStrea ...

  10. 使用Elasticsearch的动态索引和索引优化

    关于映射 实际工作中使用过ES的朋友可能会有和静儿一样的感受.ES存储更新从编码上是很方便.如下,Kubernetes的yaml文件完全可以通过json直接序列化一下,一行代码存入ES. 剩下的工作可 ...