得益于 JavaScript 加入的 decorator 特性,可以使我们跟 Java/C# 一样,更加直观自然的,做面向切面编程。而随着 TypeScript 的成熟,类型系统也让我们增强了信心,面对复杂的业务逻辑,也更有底气。

egg-controller 是集合了一些在 Controller 层开发中常见问题解决方案的插件。

Controller 路由定义

export class HomeController {
@route('/api/xxx', { name: '获取XXX数据' })
async getXXX(size: number, page: number) {
return 'homeIndex';
}
}

可以看到,使用 decorator 的形式来声明 Controller 非常直观,而且方便扩展,添加/修改 Controller 规则直接修改 decorator 的类型定义就好。这种形式也是 Java/C# 的常规操作。

这里的改进除了使用 decorator 替代了 router.js 来进行 Controller 声明以外,还添加了出入参支持,省去了需要手动读写 ctx 的过程,非常直观的声明 Controller 函数的参数需求,以及返回数据类型。

基于 decorator 的写法与之前最大的区别是,在 Controller 这个横切面,之前只有 loader 可以掌控,而现在可以在 decorator 中加以集中控制,再结合 TypeScript 的元信息,可以做出很多扩展,比如:

参数格式化

在 eggjs 中,因为没有类型信息的原因,从 params 和 query 中获取的信息都会是字符串类型,都需要在 Controller 中手动转换。而改造之后的写法,参数直接暴露在函数入参里,我们就可以直接拿写在入参的类型定义作为格式化的依据,根据类型尝试转换,保证参数类型正确,可以初步防止类型不符的参数进入到 Controller,省去手动判断、转换的逻辑。

参数校验

参数格式化只能保证参数的类型一致性,而我们的需求不止这些,比如必选参数为空时需要拦截,有时参数是复杂对象为了防止恶意构造数据,需要对数据格式做深度检测,所以这里引入了参数校验库,parameter,通过它来解决复杂的校验问题。

export class HomeController {
@route('/api/xxx', { name: '获取XXX数据', validateMetaInfo: [{
name: 'data',
rule: {
type: 'object',
str: { type: 'string', max: 20 },
count: { type: 'number', max: 10, required: false },
},
}] })
async getXXX(data: { str: string, count?: number }>) {
return data.str;
}
}

这里有个问题,在类型是复杂类型时,TypeScript 默认生成的元数据里,获取不到类型的具体字段属性信息,而且前端直接引入复用后端的类型定义也比较麻烦。所以,想要在定义类型的同时,复用类型的定义,只能在编译时做工作,TypeScript 也开放出了编译时插件API,在不用编译时插件的情况下,就需要单独写一份规则的数据。

有插件后:

export class HomeController {
@route('/api/xxx', { name: '获取XXX数据' })
async getXXX(data: BaseValidateRule<{
type: 'object',
rule: {
str: { type: 'string', max: 20 },
count: { type: 'number', max: 10, required: false },
},
}>) {
return data.str;
}
}

路由级中间件

函数类型跟 egg 定义稍有不同:

(app: Application, typeInfo: RouteType) => (ctx: any, next: any) => any

egg 已经定义了中间件,为什么在路由上还定义一个?在路由定义的中间件跟全局的中间件区别在于范围,全局中间件更适合大规模的统一处理,用来统一处理特定业务功能接口就大材小用了,还需要设置过滤逻辑,甚至需要在 config 中设置黑白名单。而路由级中间件适合只有部分接口需要的统一处理,配合从 @route 上收集的类型信息处理更佳。

API文档 & 前端SDK

既然已经收集到了那么多元数据,根据这些数据生成API文档就很简单了无非就是前端的展示,也可以把数据转换对接其他的API文档平台。

更近一步,直接生成前端调用SDK?当然没问题。本插件支持通过模板生成,如果没有找到模板,会在SDK生成目录生成默认模板。

// Controller
export class MetaController { @route({ url: '/meta/index', name: '首页' })
async index(id: string, n: number, e: 'enumA' | 'enumB', d: Date) {
return 'metaIndex';
} } // 生成代码
export class MetaService extends Base { /** 首页 */
async index(id: string, n: number, e: string, d: Date) {
const __data = { id, n, e, d };
return await this.request({
method: `get`,
url: `/meta/index`,
data: __data,
});
} } export const metaService = new MetaService();
export default new MetaService();

开发时

在配置中开启即可,根据需要自定义其他配置。当 Controller 中文件修改时,会同时重新生成对应的前端SDK文件。

构建打包时

在 前端打包流程前 可以使用 egg-controller gensdk 命令生成前端sdk,需要注意,如果为 TypeScript 项目,需要先将 TypeScript 编译,然后执行生成命令。

Controller 作为请求的起点,这只是个开始。

egg 框架

egg-controller 详细文档

Egg 中 Controller 最佳实践的更多相关文章

  1. Spring Batch在大型企业中的最佳实践

    在大型企业中,由于业务复杂.数据量大.数据格式不同.数据交互格式繁杂,并非所有的操作都能通过交互界面进行处理.而有一些操作需要定期读取大批量的数据,然后进行一系列的后续处理.这样的过程就是" ...

  2. Require.js中的路径在IDEA中的最佳实践

    本文主要讲述require.js在IDEA中路径智能感知的办法和探索中遇到的问题. 测试使用的目录结构:一种典型的thinkphp 6的目录结构,如下图. 现在我通过在 vue-a.js 中运用不同的 ...

  3. C#异步编程中的最佳实践(做法)

    原文地址Stephen Cleary 写得很详细,尤其讲到了 GUI 上下文调用,在APS.NET中它会阻塞 GUI 线程,从而导致死锁.而控制台中却不存在这个问题. 比如开发过程中本地写控制台程序测 ...

  4. 【活动】美团技术沙龙第49期:AI在外卖场景中的最佳实践

    美团技术沙龙第49期开始啦! 本次沙龙,美团外卖技术部专家会深入介绍AI在对话系统.图像处理.个性化推荐.智能营销等方向在外卖业务中的实践,希望与业界技术同学一起交流学习. 无论你从事智能搜索,或是算 ...

  5. Git 在团队中的最佳实践--如何正确使用Git Flow

    我们已经从SVN 切换到Git很多年了,现在几乎所有的项目都在使用Github管理, 本篇文章讲一下为什么使用Git, 以及如何在团队中正确使用. Git的优点 Git的优点很多,但是这里只列出我认为 ...

  6. Android应用中MVP最佳实践

    转自:http://www.jianshu.com/p/ed2aa9546c2c 文/Jude95(简书作者)原文链接:http://www.jianshu.com/p/ed2aa9546c2c著作权 ...

  7. GIT在团队中的最佳实践

    我们已经从SVN 切换到Git很多年了,现在几乎所有的项目都在使用Github管理, 本篇文章讲一下为什么使用Git, 以及如何在团队中正确使用. Git的优点 Git的优点很多,但是这里只列出我认为 ...

  8. 一文搞懂 Python 的模块和包,在实战中的最佳实践

    最近公司有个项目,我需要写个小爬虫,将爬取到的数据进行统计分析.首先确定用 Python 写,其次不想用 Scrapy,因为要爬取的数据量和频率都不高,没必要上爬虫框架.于是,就自己搭了一个项目,通过 ...

  9. Git 在团队中的最佳实践--如何正确使用Git Flow[转]

    原文地址:http://www.cnblogs.com/cnblogsfans/p/5075073.html Git的优点 Git的优点很多,但是这里只列出我认为非常突出的几点. 由于是分布式,所有本 ...

随机推荐

  1. pyspider

    Linux系统我使用CentOS.对于pycurl安装问题比较好解决,只需要先安装对应的开发包即可.执行如下命令: yum install python-devel curl-devel 分别安装py ...

  2. VMware workstation 上克隆CentOS 6.x 系统后网卡无法启动的问题

    在日常学习中,我们往往没有足够的物理机资源来搭建多节点的实验环境,一个比较好的解决方案就是利用虚拟机来模拟物理机完成实验. 这样一来,多节点操作系统的部署就可以利用VMware 自带的系统“克隆”功能 ...

  3. VS 编码规范---- 代码注释设置

    一个良好的代码风格在开发过程和后期维护过程中是必不可少的.每次在添加新类的时候都需要添加一些关于类的注释,包括创建时间.创建人.类的功能介绍.修改时间等一系列的信息,以方便以后的查找和快速了解.在Co ...

  4. 使用Set集合对List集合进行去重

    /** * 使用Set集合对List集合进行去重 **/ public class SetTest { /** * List集合的泛型为Integer类型 * * @author hongwei.li ...

  5. ASP.NET Core微服务 on K8S学习笔记(第一章:详解基本对象及服务发现)

    课程链接:http://video.jessetalk.cn/course/explore 良心课程,大家一起来学习哈! 任务1:课程介绍 任务2:Labels and Selectors 所有资源对 ...

  6. Spring boot 学习笔记 1 - 自定义错误

    Spring Boot提供了WebExceptionHandler一个以合理的方式处理所有错误的方法.它在处理顺序中的位置就在WebFlux提供的处理程序之前,这被认为是最后一个处理程序. 对于机器客 ...

  7. 基于 EntityFramework、Autofac 的 UnitOfWork 框架(一)

    之前公司项目参考 NopCommerce 开发了一套系统,但是不支持 UnitOfWork,最近想开发新的项目,所以就基于原有的基础上又添加 UnitOfWork 支持,由于目前正在逐步完善中,所以可 ...

  8. 关于tomcat WEB-INF/lib下类加载顺序

    关于tomcat WEB-INF/lib下类加载顺序问题 问题描述 smc应用最近碰到一个线上问题,预发机器规则测试接口没问题,但是线上机器就是调用有问题,表面上看,maven模块引用的是自己想要的j ...

  9. MSSql-1内部数据库版本号

    源SQL Server版本 内部数据库版本 SQL Server 2017 869 SQL Server 2016 782 SQL Server 2012 706 SQL Server 2008 R2 ...

  10. php unicode编码和字符串互转

    php字符串转Unicode编码, Unicode编码转php字符 百度了很多,都一样, 要么不对, 要不就是只是把字符串的汉字转Unicode 经过多次试验查找, 找到了如下方法, 注意:字符串编码 ...