Midway-ModelProxy — 轻量级的接口配置建模框架

前言

使用Node做前后端分离的开发模式带来了一些性能及开发流程上的优势(见《前后端分离的思考与实践 一》), 但同时也面临不少挑战。在淘宝复杂的业务及技术架构下,后端必须依赖Java搭建基础架构,同时提供相关业务接口供前端使用。Node在整个环境中最重要的工作之一就是代理这些业务接口,以方便前端(Node端和浏览器端)整合数据做页面渲染。如何做好代理工作,使得前后端开发分离之后,仍然可以在流程上无缝衔接,是我们需要考虑的问题。本文将就该问题做相关探讨,并提出解决方案。

由于后端提供的接口方式可能多种多样,同时开发人员在编写Node端代码访问这些接口的方式也有可能多种多样。如果我们在接口访问方式及使用上不做统一架构处理,则会带来以下一些问题:

1. 每一个开发人员使用各自的代码风格编写接口访问代码,造成工程目录及编码风格混乱,维护相对困难。

2. 每一个开发人员编写自己的mock数据方式,开发完毕之后,需要手工修改代码移除mock。

3. 每一个开发人员为了实现接口的不同环境切换(日常,预发,线上),可能各自维护了一些配置文件。

4. 数据接口调用方式无法被各个业务model非常方便地复用。

5. 对于数据接口的描述约定散落在代码的各个角落,有可能跟后端人员约定的接口文档不一致。

6. 整个项目分离开发之后,对于接口的联调或者测试回归成本依然很高,需要涉及到每一个接口提供者和使用者。

于是我们希望有这样一个框架,通过该框架提供的机制去描述工程项目中依赖的所有外部接口,对他们进行统一管理,同时提供灵活的接口建模及调用方式,并且提供便捷的线上环境和生产环境切换方法,使前后端开发无缝结合。ModelProxy就是满足这样要求的轻量级框架,它是Midway Framework 核心构件之一,也可以单独使用。使用ModelProxy可以带来如下优点:

1. 不同的开发者对于接口访问代码编写方式统一,含义清晰,降低维护难度。

2. 框架内部采用工厂+单例模式,实现接口一次配置多次复用。并且开发者可以随意定制组装自己的业务Model(依赖注入)。

3. 可以非常方便地实现线上,日常,预发环境的切换。

4. 内置river-mockmockjs等mock引擎,提供mock数据非常方便。

5. 使用接口配置文件,对接口的依赖描述做统一的管理,避免散落在各个代码之中。

6. 支持浏览器端共享Model,浏览器端可以使用它做前端数据渲染。整个代理过程对浏览器透明。

7. 接口配置文件本身是结构化的描述文档,可以使用river工具集合,自动生成文档。也可使用它做相关自动化接口测试,使整个开发过程形成一个闭环。

ModelProxy工作原理图及相关开发过程图览

在上图中,开发者首先需要将工程项目中所有依赖的后端接口描述,按照指定的json格式,写入interface.json配置文件。必要时,需要对每个接口编写一个规则文件,也即图中interface rules部分。该规则文件用于在开发阶段mock数据或者在联调阶段使用River工具集去验证接口。规则文件的内容取决于采用哪一种mock引擎(比如 mockjs, river-mock 等等)。配置完成之后,即可在代码中按照自己的需求创建自己的业务model。

下面是一个简单的例子:

【例一】

  • 第一步 在工程目录中创建接口配置文件interface.json, 并在其中添加主搜接口json定义
  1. {
  2. "title": "pad淘宝项目数据接口集合定义",
  3. "version": "1.0.0",
  4. "engine": "mockjs",
  5. "rulebase": "./interfaceRules/",
  6. "status": "online",
  7. "interfaces": [ {
  8. "name": "主搜索接口",
  9. "id": "Search.getItems",
  10. "urls": {
  11. "online": "http://s.m.taobao.com/client/search.do"
  12. }
  13. } ]
  14. }
  • 第二步 在代码中创建并使用model
  1. // 引入模块
  2. var ModelProxy = require( 'modelproxy' );
  3. // 全局初始化引入接口配置文件  (注意:初始化工作有且只有一次)
  4. ModelProxy.init( './interface.json' );
  5. // 创建model 更多创建模式请参后文
  6. var searchModel = new ModelProxy( {
  7. searchItems: 'Search.getItems'  // 自定义方法名: 配置文件中的定义的接口ID
  8. } );
  9. // 使用model, 注意: 调用方法所需要的参数即为实际接口所需要的参数。
  10. searchModel.searchItems( { q: 'iphone6' } )
  11. // !注意 必须调用 done 方法指定回调函数,来取得上面异步调用searchItems获得的数据!
  12. .done( function( data ) {
  13. console.log( data );
  14. } )
  15. .error( function( err ) {
  16. console.log( err );
  17. } );

ModelProxy的功能丰富性在于它支持各种形式的profile以创建需要业务model:

  • 使用接口ID创建>生成的对象会取ID最后’.'号后面的单词作为方法名
  1. ModelProxy.create( 'Search.getItem' );

使用键值JSON对象>自定义方法名: 接口ID

  1. ModelProxy.create( {
  2. getName: 'Session.getUserName',
  3. getMyCarts: 'Cart.getCarts'
  4. } );
  • 使用数组形式>取最后 . 号后面的单词作为方法名

下例中生成的方法调用名依次为: Cart_getItem, getItem, suggest, getName

  1. ModelProxy.create( [ 'Cart.getItem', 'Search.getItem', 'Search.suggest', 'Session.User.getName' ] );
  • 前缀形式>所有满足前缀的接口ID会被引入对象,并取其后半部分作为方法名
  1. ModelProxy.create( 'Search.*' );

同时,使用这些Model,你可以很轻易地实现合并请求或者依赖请求,并做相关模板渲染

【例二】 合并请求

  1. var model = new ModelProxy( 'Search.*' );
  2. // 合并请求 (下面调用的model方法除done之外,皆为配置接口id时指定)
  3. model.suggest( { q: '女' } )
  4. .list( { keyword: 'iphone6' } )
  5. .getNav( { key: '流行服装' } )
  6. .done( function( data1, data2, data3 ) {
  7. // 参数顺序与方法调用顺序一致
  8. console.log( data1, data2, data3 );
  9. } );

【例三】 依赖请求

  1. var model = new ModelProxy( {
  2. getUser: 'Session.getUser',
  3. getMyOrderList: 'Order.getOrder'
  4. } );
  5. // 先获得用户id,然后再根据id号获得订单列表
  6. model.getUser( { sid: 'fdkaldjfgsakls0322yf8' } )
  7. .done( function( data ) {
  8. var uid = data.uid;
  9. // 二次数据请求依赖第一次取得的id号
  10. this.getMyOrderList( { id: uid } )
  11. .done( function( data ) {
  12. console.log( data );
  13. } );
  14. } );

此外ModelProxy不仅在Node端可以使用,也可以在浏览器端使用。只需要在页面中引入官方包提供的modelproxy-client.js即可。

【例四】浏览器端使用ModelProxy

  1. <!-- 引入modelproxy模块,该模块本身是由KISSY封装的标准模块-->
  2. <script src="modelproxy-client.js" ></script>
  1. <script type="text/javascript">
  2. KISSY.use( "modelproxy", function( S, ModelProxy ) {
  3. // !配置基础路径,该路径与第二步中配置的拦截路径一致!
  4. // 且全局配置有且只有一次!
  5. ModelProxy.configBase( '/model/' );
  6. // 创建model
  7. var searchModel = ModelProxy.create( 'Search.*' );
  8. searchModel
  9. .list( { q: 'ihpone6' } )
  10. .list( { q: '冲锋衣' } )
  11. .suggest( { q: 'i' } )
  12. .getNav( { q: '滑板' } )
  13. .done( function( data1, data2, data3, data4 ) {
  14. console.log( {
  15. "list_ihpone6": data1,
  16. "list_冲锋衣": data2,
  17. "suggest_i": data3,
  18. "getNav_滑板": data4
  19. } );
  20. } );
  21. } );
  22. </script>

同时,ModelProxy可以配合Midway另一核心组件Midway-XTPL一起使用,实现数据和模板以及相关渲染过程在浏览器端和服务器端的全共享。关于ModelProxy的详细教程及文档请移步https://github.com/purejs/modelproxy

总结

ModelProxy以一种配置化的轻量级框架存在,提供友好的接口model组装及使用方式,同时很好的解决前后端开发模式分离中的接口使用规范问题。在整个项目开发过程中,接口始终只需要定义描述一次,前端开发人员即可引用,同时使用River工具自动生成文档,形成与后端开发人员的契约,并做相关自动化测试,极大地优化了整个软件工程开发过程。

【注】River 是阿里集团研发的前后端统一接口规范及相关工具集合的统称

原文链接:http://ued.taobao.org/blog/2014/04/modelproxy/

【编辑推荐】

Midway-ModelProxy — 轻量级的接口配置建模框架的更多相关文章

  1. ModelProxy 前端接口配置建模框架

    ModelProxy    轻量级的接口配置建模框架(1) 先看一下这个博客说明为什么需要用ModelProxy的前端轻量级的框架吧:  http://developer.51cto.com/art/ ...

  2. 通过策略接口,Spring 框架是高度可配置的,而且包含多种视图技术

    通过策略接口,Spring 框架是高度可配置的,而且包含多种视图技术,例如 JavaServer Pages( JSP)技术.Velocity.Tiles.iText 和 POI.Spring MVC ...

  3. Asp.net 面向接口可扩展框架之业务规则引擎扩展组件

    随着面向接口可扩展框架的继续开发,有些功能开发出现了"瓶颈",有太多的东西要写死才好做.但写死的代码扩展性是非常的不好,迷茫中寻找出入... 进而想到我以前开发的好几个项目,都已有 ...

  4. Asp.net 面向接口可扩展框架之核心容器(含测试代码下载)

    新框架的容器部分终于调通了!容器实在太重要了,所以有用了一个名词叫“核心容器”. 容器为什么那么重要呢?这个有必要好好说道说道. 1.首先我们从框架名称面向接口编程说起,什么是面向接口编程?(这个度娘 ...

  5. Jmeter笔记(Ⅱ)使用Jmeter实现轻量级的接口自动化测试

    接口测试虽然作为版本的一环,但是也是有一套完整的体系,有接口的功能测试.性能测试.安全测试:同时,由于接口的特性,接口的自动化低成本高收益的,使用一些开源工具或一些轻量级的方法,在测试用例开发的成本不 ...

  6. Asp.net 面向接口可扩展框架之消息队列组件

    消息队列对大多数人应该比较陌生.但是要提到MQ听说过的人会多很多.MQ就是英文单词"Message queue"的缩写,翻译成中文就是消息队列(我英语差,翻译错了请告知). PS: ...

  7. Asp.net 面向接口可扩展框架之使用“类型转化基础服务”测试四种Mapper(AutoMapper、EmitMapper、NLiteMapper及TinyMapper)

    Asp.net 面向接口可扩展框架的“类型转化基础服务”是我认为除了“核心容器”之外最为重要的组成部分 但是前面博文一出,争议很多,为此我再写一篇类型转化基础服务和各种Mapper结合的例子,顺便对各 ...

  8. 面向接口可扩展框架之“Mvc扩展框架及DI”

    面向接口可扩展框架之“Mvc扩展框架及DI” 标题“Mvc扩展框架及DI”有点绕口,我也想不出好的命名,因为这个内容很杂,涉及多个模块,但在日常开发又密不可分 首先说Mvc扩展框架,该Mvc扩展就是把 ...

  9. struts2+hibernate+spring配置版框架搭建以及简单测试(方便脑补)

    为了之后学习的日子里加深对框架的理解和使用,这里将搭建步奏简单写一下,目的主要是方便以后自己回来脑补: 1:File--->New--->Other--->Maven--->M ...

随机推荐

  1. 【Framework】深入研究Asp.net页面的生命周期

    介绍 Asp.net是微软.Net战略的一个组成部分.它相对以前的Asp有了很大的发展,引入了许多的新机制.本文就Asp.net页面的生命周期向大家做一个初步的介绍,以期能起到指导大家更好.更灵活地操 ...

  2. solr5.5教程-tomcat布署(2)

    tomcat 布署成功后,接下来就是使用了. 首先要创建一个core. 1.选择右侧菜单, Core Admin -> Add Core. 注意:name自己定义,instanceDir要填写上 ...

  3. Backup App's data without rooting the phone

    First I'd like to let you know that my phone is Android 6.0 Marshmallow. So it works on the latest A ...

  4. 二十一、contextMap中放的常用数据

    二十一.contextMap中放的常用数据 request:请求范围的数据.即ServletRequest中的那个Map parameters:请求参数的数据.即request.getParamete ...

  5. Ajax清除浏览器js、css、图片缓存的方法

    做东东时都是把图片在服务器的地址存放在数据库里面,然后到浏览器中显示,但是后来发现了两个问题. 第一:为了安全起见,js是无法读取本地的图片的,不然你写一个js,岂不是可以获取任何人电脑里面的文件了. ...

  6. JavaScript中this详解

    这里的主题是 this ,不扯远了.this 本身原本很简单,总是指向类的当前实例,this 不能赋值.这前提是说 this 不能脱离 类/对象 来说,也就是说 this 是面向对象语言里常见的一个关 ...

  7. GridView 鼠标经过时变色两种方法

    第一种: 新建一个js文件 并引用 <script src="jquery.js" type="text/javascript"></scri ...

  8. Eclipse中Maven的安装

    注:初次尝试安装,配置maven,有错误望指正! 1.说明 maven.rar 是maven文件,解压即可,无需安装,但需要配置环境变量MAVEN_HOME,并放在PATH中,

  9. DXperience重编译汉化的方法

    1. 必须有DXperience相应版本的全部源代码SourceCode.把全部源代码复制到\Program Files\Developer Express .NET vX.X\Sources目录.目 ...

  10. List GetEnumerator

    static void Main() { List<int> list = new List<int>(); list.Add(); list.Add(); list.Add( ...