使用 Cloud Application Programming 模型开发 OData 的一个实际例子

刚刚过去的 SAP TechEd 上,SAP CTO Juergen Mueller 向外界传递了一个重要的信息:身处云时代大环境下的 SAP 从业者,在 SAP 云平台上该如何选择适合自己的开发方式?
Juergen Mueller 用了一棵决策树来向大家介绍,对于拥有不同开发技能水平的 SAP 从业者,可以按照这棵树,根据自身情况和项目需要来选择不同层次和组合的开发工具以及编程模型。

上图右边的分支表明,如果不想抛弃已经习得的 ABAP 开发技能,可以选择 SAP 云平台上的 ABAP 编程环境;反之,如果青睐 nodejs,Java 这些技术栈,那么 SAP 云平台也不会让你失望:SAP Cloud Application Programming Model(简称为 CAP),是 SAP 推荐的在 SAP Cloud Platform 上进行开发的最佳实践。

究竟什么是 SAP Cloud Application Programming Model?SAP 官网上给出了定义:一套由开发语言,开发工具和库有机集成的框架,提供了一种高效,快捷,全栈式的企业级服务和应用开发手段。CAP 包含一套开发最佳实践,让开发者能够专注于应用内具体业务逻辑的开发,而无需分心将精力花在重复的底层基础设施功能的实现上去。

看一个具体的例子,通过 Cloud Application Programming Model 实现一个简单的在线书店应用。书店里出售很多书(Books),每本书包含 ID,名称,作者(Author)和库存这四个字段。用户通过创建订单(Orders)进行购买。
如果是用 ABAP 技术栈实现这个需求,一种比较容易的方式是使用事务码 SEGW,通过 OData 协议来实现。在 SEGW 里创建 Books,Author 和 Orders 模型,以及对应的增删改查。Jerry 在去年的文章 SAP OData 编程指南 里曾详细介绍。再后来有了 CDS view,可以通过在 CDS view 上加注解 @OData.publish 的方式快速创建 OData 服务。
到了 SAP Cloud Platform ABAP 编程环境上,我们有了更加好用的工具:Restful ABAP Programming Model,
30 分钟用 Restful ABAP Programming 模型开发一个支持增删改查的 Fiori 应用 Jerry 带您了解 Restful ABAP Programming 模型系列之二:Action 和 Validation 的实现

从以上短短的描述,我们能够感受到,近些年来 ABAP 技术栈随着 SAP 向云端转型而不断快速向前演进的趋势。
下面我们就来看看如何用 SAP CAP 实现这个在线书店的需求。
命令行执行下面的命令:
npm set @sap:registry=https://npm.sap.comnpm i -g @sap/cds
从 SAP 的 npm 仓库里下载 cds 库并进行全局安装:

接下来直接敲 cds 命令,如果看到下面的帮助信息,说明安装成功了。此后所有的 CAP 开发,都围绕着这个 cds 命令进行。

CAP 开发的 IDE 可以使用 Visual Studio Code,当然也可以用其他文本编辑工具。推荐 Visual Studio Code 的原因是 SAP 发布了一款针对 CAP 开发的 Visual Studio Code 扩展,支持语法高亮和静态检查,可以从 SAP 官网下载:https://tools.hana.ondemand.com/#cloud

和我们开发一个 nodejs 应用类似,基于 CAP 的编程,第一步就是 cds init,这个命令会自动帮我们创建 CAP 应用的骨架和从 npm.sap.com 下载 CAP 应用必需的库文件。

cds init 执行完毕后,打开 Visual Studio Code,界面如下,这些全是 cds init 自动生成的:

新建 srv 文件夹,下面创建文件 cat-service.cds,完成 Books,Authors 和 Orders 的建模,即定义每个模型的字段,以及模型间的跳转关系:

定义完之后,执行命令 cds run,就可以本地预览我们刚刚创建的模型了。这个命令启动了一个本地服务器,通过 http://localhost:4004 访问:

到目前为止,因为我们没有实现这个模型的持久层,所以还观察不到任何数据。

在实现持久层之前,我们可以先 mock 一些数据。新建 cat-service.js, 在里面硬编码一些测试数据:

这样,再次请求 Books 和 Authors,就能在浏览器里看到 mock 的数据了:


下面我们进行持久层的相关开发。新建一个文件夹 db,下面新建一个文件 data-model.cds,把之前实现在 cat-service.cds 里的模型定义拷贝过来。第 17 行的 managed 意思是把 Orders 模型的增删改查操作托管给框架完成。

此时 cat-service.cds 里的实现就干净多了,直接重用上一步 data-model.cds 里定义好的模型。注意此处的 @readonly 和 @insertonly 注解。

这个例子里我们选用 SQLite 这个轻型数据库来存储数据。用命令行 npm i sqlite3 -D 安装 SQLite,然后进行数据库部署:
cds deploy --to sqlite:db/my-bookshop.db

根据 cds deploy 命令的输出提示,package.json 也相应被更新了:

前面提过 Books 和 Authors 这两个模型具有 @readonly 注解,因此我们新建两个 csv 文件,维护一些数据在文件内:

然后将这两个 csv 文件通过命令 cds deploy 导入到数据库里。

登录 sqlite 控制台,使用 select 语句查看成功从 csv 文件导入的数据:

前面提到 Orders 的注解是 @insertonly, 现在我们想实现一个新功能,每次针对一本书下单后,该图书的库存减一。
《生化危机》目前只有 12 本了:

打开之前存放 mock 数据的 cat-service.js, 在下单之前的 hook 里实现库存减一的操作:

然后进行测试:在 postman 里执行 post 请求,下单再买一本:

此时再次执行 get 请求,发现《生化危机》的库存已经和期望的一样扣掉了一本了:

这种频繁下单的顾客,估计是和 Jerry 一样的生化系列爱好者。


希望这个例子能够帮助大家对如何使用 Cloud Application Programming Model 进行开发有一些基本的认识。感谢阅读。
版权声明: 本文为 InfoQ 作者【Jerry Wang】的原创文章。
原文链接:【http://xie.infoq.cn/article/ef77ebf211b46522b808be26d】。文章转载请联系作者。
评论