添加自定义逻辑

Objective

After completing this lesson, you will be able to 借助 .before 事件处理程序实施编程验证

自定义服务实施

由于通用服务提供者涵盖大多数标准任务和用例,因此大大减少和缩小了添加服务实施代码的需求。

其余情况将减少到特定于域和应用程序的实际自定义逻辑,例如域特定的编程验证。

例如,让我们编写一个验证,以确保通过 AdminService 创建新作者时,出生日期早于经过的死亡日期。

添加自定义服务实现的最简单方法是将同名的 .js 文件放在包含相应服务定义的 .cds 文件旁。例如,在我们的案例中,我们将名为 admin-service.js 的文件放入项目的 srv 文件夹中,因为此文件夹还包含文件 admin-service.cds,用于定义管理服务(请参阅下图)。

注意

或者,您还可以使用 @impl 注释对 .cds 文件中的服务定义进行注释。使用此注释来显式引用应包含服务实施的其他 .js 文件。

有多种方法可以在 .js 文件中实施所需的自定义逻辑。最常见的方法是使用 cds.ApplicationService 的子类从通用的开箱即用实施中受益。这是因为 cds.ApplicationService 类是缺省服务提供者实施,它将已讨论的通用提供者添加到服务定义中。

要创建 cds.ApplicationService 的子类,我们首先将 @sap/cds 模块分配到代码中的常量 cds(第 1 行)。@sap/cds 模块是 cds 外观对象,提供对所有 CAP Node.js API 的访问。

然后,我们在行 4 到 6 中创建 cds.ApplicationService 的子类,稍后我们将在其中实施自定义逻辑。子类的名称是任意的。我们在这里将其称为服务接口,即管理服务

在第 9 行中,我们使 AdminService 类可用于导入到其他模块。这是 Node.js 中用于构建代码的常见做法。

注意

如果现在通过在终端中输入 cds watch 来启动应用程序,则添加的服务实施文件将通过类似于以下内容的输出显示在日志中:

Code Snippet
1
[cds] - serving AdminService { path: '/admin', impl: 'srv/admin-service.js' }

事件处理器

自定义服务实施在自定义事件处理器的帮助下执行,从而区分不同类型的处理器。

观看视频以获取不同事件处理器的概览。

正在注册 .before 事件处理程序

对于要实施的验证,我们需要一个在作者实体上注册 CREATE 和 UPDATE 操作的 before 处理程序

要注册自定义事件处理器,请在创建的实施类中覆盖继承的 init() 方法(请参阅下图)。不要忘记在实现中调用 super.init() 以允许子类注册其处理器。

要在 init() 方法中注册 before 处理程序,请通过 this.before() 调用继承的 before() 方法。 为此,您必须提供以下接口。可在 CAP 文档中找到各个参数的详细描述:

Code Snippet
12345
function before ( event : string | string[] | '*', entity? : CSN definition | CSN definition[] | string | string[] | '*', handler : function )

在所示示例中,命名函数 this.validateLifeData 注册用于 Authors 实体上的 CREATE 和 UPDATE 操作。我们稍后将讨论此功能的实施。

要进行注册的一个或多个实体可以字符串形式传递到 before() 方法。但是,建议在此处传递 CSN 定义。通过 服务公开的实体的 CSN 定义通过 this.entities 属性方便使用。

在所示示例中,作者实体的所需 CSN 定义通过重组分配分配给作者常量。

注意

解构分配语法是 JavaScript 标准。它是一个 JavaScript 表达式,能够将数组中的值或对象的属性解压缩到不同的变量中。

验证内向数据

最后,让我们看看如何在 AdminService 类上实现已注册为 before 处理程序的验证 LifeData 函数。

在处理程序通常接收单个参数(cds.Request 的实例)之前。此实例提供可用于实施处理器的属性和方法。在示例中,我们命名了参数 req(请参阅下图)。

对于我们在此处关注的 CREATE 和 UPDATE 请求,接口参数的数据属性包含请求的 HTTP 正文。我们使用重组分配将传递的值从 HTTP 正文分配到常量 dateOfBirthdateOfDeath

如果死亡日期早于出生日期,则通过 req.error() 方法发出相应的错误消息。

注意

req.error() 方法收集属性 req.errors 中的所有故障,允许一次在 UI 上显示所有故障。如果在之前阶段之后存在 req.errors,则会中止请求处理,并将相应的错误响应返回到客户端。

提示

传递到 req.error() 方法的文字使用反勾号 (`) 字符分隔。此类模板文字允许使用语法 ${name_of_the_variable} 将变量值嵌入到字符串中。

演示和练习:在事件处理器之前提供 .before

注意

在练习中,在 SAP Business Application Studio 中自行执行以下演示中的分步说明。

作为练习的起点,如果已成功完成,请使用上一练习基于非规范化视图定义服务的结果。或者,您还可以使用以下 GitHub 资源库中的分支 10_denormalized_views 作为起点:

https://github.com/SAP-samples/cap-development-learning-journey

可在 GitHub 资源库的 11_.before_event_handler 分支中找到模拟的完整实施。

有关资源库内容及其使用方法的详细信息,可在此处找到。

观看视频,了解如何提供 .before 事件处理程序。