这是Jerry在2021年的第63篇文章,也是王子熙一共第340篇原创文章公众号。蜀丞相杜甫丞相祠在哪里?阶上绿草映春色,黄莺每叶空灵好声。三访频扰世间计谋,两朝开老臣心。师未离而死,令男主泪流满面。Jerry之前的文章《基于OData模型和JSON模型实现SAPUI5表格控件的增删改行》对比了SAPUI5表格控件使用OData模型和JSON模型的实现差异。SAPUI5初学者在学习使用ODataAPI时,面临的一个问题是:如何在公网上找到一些可以免费使用的OData服务。Northwind无疑是不错的选择之一,但该服务不支持编辑。虽然理论上,我们可以利用Jerry的这篇文章《SAPCloudApplicationProgrammingIntroduction(2021Update)》,采用SAPCloudApplicationProgramming模型(CAP),在本地构建一个支持增删改查的OData服务。但是对于学习SAPUI5的初学者来说,就有点大材小用了。事实上,SAPUI5自带了一个简单易用的MockServer,可以用来在本地模拟OData服务提供者,响应SAPUI5应用发起的OData请求,并回复预先配置的测试数据。登录SAPUI5官网,输入关键字MockServer,可以找到它的文档:https://sapui5.hana.ondemand....MockServer的运行对SAPUI5应用程序是完全透明的,SAPUI5应用不知道自己发送的请求是真实远程服务器响应还是MockServer返回。https://sapui5.hana.ondemand....下面以实际例子来介绍MockServer的使用步骤。这个例子的所有代码都在我的Github上:https://github.com/wangzixi-d...(1)在Tablecontroller中,新建一个OData模型实例,传入OData服务url:/here/goes/your/serviceUrl/这个url就是我们需要在MockServer中模拟的OData服务地址。(2)在本地工程文件中新建test文件夹,里面包含以下三个文件:metadata.xml:OData服务的元数据文件,定义了名为Products的EntitySet,类型为Product,包含三个Field:ProductIdNameSizeProducts.json包含与上面metadata.xml文件中定义的名为Products的EntitySet对应的数据。运行时,MockServer会自动在其工作目录下寻找一个同名的.json文件,读取其内容,返回给OData服务的消费者。server.js从sap/ui/core/util/MockServer导入MockServer的实现,将步骤1中SAPUI5需要消费的OData服务url导入到MockServer的rootUri属性中。下图中的autoRespondAfter属性定义了使用MockServer响应OData请求的延时,即1秒后返回响应。三个文件的总行数不到60行,但是提供了一个功能齐全的MockServer。(3)在SAPUI5应用的index.html中,使用sap.ui.require加载本地项目实例中的MockServer,调用其init方法启动服务器。将Jerry的代码克隆到本地,npminstall后执行nodelocal.js:https://github.com/wangzixi-d...可以在Chrome开发者工具中观察MockServer的运行状态:http://localhost:3002/tablede...(1)SAPUI5表控件向OData服务请求元数据。MockServer接收到请求,将工作目录下的metadata.xml的内容返回给调用者。(2)Jerry之前的文章《基于OData模型和JSON模型实现SAPUI5表格控件增删行项》中曾经提到OData模型是服务端模型,也就是说表格控件不知道如何实现目前有很多数据。需要展示。因此,SAPUI5表控件将发送另一个包含$count操作的OData请求来查询Products的总数。表格控件最终显示的条目数是$count操作的结果与20中较小的一个。20是OData分页的默认大小,在Jerry的文章SAPUISearchPaginationTechnology中有详细介绍。因为我在MockServer的Products.json中只维护了两条数据,所以$count的结果是2。(3)现在表格控件已经明确了需要显示两条数据,于是发起第三条OData数据请求,$skip=0&$top=2,向服务器请求第一页的前两条数据。MockServer收到请求,将Products.json中的两条数据全部返回给表单控件。(4)使用AddRow按钮添加一条新数据后,SAPUI5表控件依次发送如下三个OData请求:删除操作的执行逻辑类似,这里不再赘述。SAPUI5MockServer的一些高级用法可以通过查阅MockServer的帮助文档获得。例如,假设我们想对模拟服务器返回给调用者的数据进行一些自定义处理。此时,可以在MockServer提供的attachAfter钩子函数中编写自定义逻辑:应用开发者Trigger编写的attachAfter回调函数,在每个产品的Name字段值末尾添加一个句号。SAPUI5MockServer实际上是基于著名的开源Mock框架Sinon.js:https://github.com/sinonjs/sinonSinon该框架的名称是为了纪念希腊联盟之间出现的十年战争部队和特洛伊木马。向英勇的战士西农(Sinong)致敬,就是下图中的这位:希腊联军中的奥德修斯为了攻破坚固的特洛伊城,想出了“特洛伊木马绝招”:将士兵隐藏在木马的肚子,等着木马把木马拖进城里后,夜深人静的时候,木马里面的士兵齐齐冲了出来,内外联手,拿下了木马特洛伊城。诗乃勇敢地承担了说服特洛伊人将特洛伊木马拖入城市的艰巨任务。他成功饰演了间谍(Spy)一角,凭借出色的演技,特洛伊国王坚信特洛伊木马是特洛伊城的“吉祥物”。当通过init方法启动基于Sinon的SAPUI5MockServer时,会调用Sinon.useFakeXMLHttpRequest实现Sinon伪造的FakeXMLHttpRequest,替换Window全局的XMLHttpRequest,完成隐身。这个替换,一般的SAPUI5开发者不通过Sinon源代码是不会知道的。这种情况有点像希腊联军的士兵们躲在木马里,不知不觉潜入特洛伊城内的场景。值得一提的是,Sinon的工作原理不同于Java和Angular中的HTTPIntercept(拦截器)。在HTTP拦截器的工作场景中,HTTP请求可以在两个时间点被框架或者应用开发者编写的拦截器处理:程序代码调用API发送HTTP请求之后,HTTP请求真正被处理之前从浏览器发送过来,由拦截器预处理应用程序得到远程服务器的响应后,会先由拦截器进行预处理,然后交给它的回调函数处理。拦截器对HTTP请求进行预处理,其类型包括但不限于:全局错误处理,统一认证机制,或者增加额外的业务逻辑等。在Sinon的工作场景中,由于真正的XMLHttpRequest已经被FakeXMLHttpRequest替代,所以根本不是真正的HTTP请求,所以在Chrome开发者工具的网络选项卡中观察不到网络请求。SAPUI5应用与MockServer的交互,纯粹是基于内存中FakeXMLHttpRequest的问答。希望本文能帮助大家了解SAPUI5MockServer的使用步骤和工作原理,以及MockServer背后的Sinon框架的命名由来。谢谢阅读。更多Jerry原创文章在这里:《王子熙》:
