快速上手:探索 Apex Recipes 示例应用

Apex Recipes 是 Salesforce 官方维护的示例应用,用一组精心设计的范例演示编写 Apex 的正确姿势。本项目用 Salesforce DX 工具(VS Code + CLI + Git)把应用部署到 Playground,再深入探索两个智能抽象:简化 HTTP Callout 的 RestClient 与分离业务逻辑的 Trigger Handler 框架,为可持续、可测试的 Apex 开发树立标杆。...

📅 2026/10/11 ✍️ ponybai 🏷️ salesforce, headless

部署 Apex Recipes 示例应用(01 Deploy the Apex Recipes Sample App)

slide_2

在探索代码之前,你需要先把它部署到组织里。本单元你将了解 Apex Recipes 示例应用包含什么、创建一个带凭据的全新 Trailhead Playground、安装 Git,并用 Visual Studio Code 加 Salesforce CLI 完成部署。这一单元涵盖 DevOps 侧的工作——把真实、生产级质量的 Apex 代码放进你的组织,供你研究。

完成本项目后,你将能够:

  • 部署 Apex Recipes 示例应用;
  • 了解该应用的用例;
  • 探索 Apex Recipes 示例应用的实现。

介绍 Apex Recipes 示例应用(一):它是什么(Introducing (1): What It Is)

slide_3

Apex Recipes 是一组"有立场"的示例,用来演示在 Apex 中正确地完成某件事的方式。你会在里面找到从安全地查询数据到编写可持续的触发器等各种范例。这些示例被设计得尽可能简洁,同时又能反映真实场景——希望开发者能把这些 recipe 当作自己解决方案的起点。

Apex Recipes 被拆分成多个文件夹,每个文件夹包含与某个特定解决方案(或一组方案)相关的代码,包括:

  • Async Apex Recipes——Queueable、Batch、Scheduled、Future 方法;
  • Data Recipes——SOQL、DML 模式;
  • Integration Recipes——HTTP callout、REST/SOAP 模式;
  • Security Recipes——FLS、CRUD、共享规则;
  • Trigger Recipes——handler 框架模式;
  • Platform Event Recipes——事件驱动架构;
  • Invocable Recipes——可被 Flow 调用的 Apex;
  • Shared Code——可复用的抽象。

此外,在 force-app/tests 文件夹里还有与源码结构一一对应的单元测试。这是一个你可以多年引用的代码库——需要写 Queueable、触发器 handler 或 HTTP callout 时,打开对应的 recipe 就能看到推荐做法。

介绍 Apex Recipes 示例应用(二):关于与前置条件(Introducing (2): About & Prerequisites)

slide_4

这个示例应用来自 Trailhead Sample Gallery——一组由 Salesforce Developer Relations 团队维护、托管在 GitHub 上的参考应用合集。它的代码能说明可持续 Apex 代码的写法,还展示了帮助你写出可复用代码的智能抽象。

开始之前——前置条件:你必须先完成 Quick Start: Salesforce DX 项目。那个徽章会带你搭好并熟悉 Salesforce DX 开发环境:

  • Salesforce CLI——用于组织管理和部署的命令行工具;
  • Visual Studio Code + Salesforce Extension Pack——Salesforce 开发的推荐 IDE。

此外还需要 Git——用来克隆代码仓库的版本控制系统。这些就是 Salesforce DX 工具集。如果还没完成那个徽章,请先停下来完成它——本项目的命令离开这些工具根本无法运行。

介绍 Apex Recipes 示例应用(三):抽象(Introducing (3): Abstractions)

slide_5

Apex Recipes 真正特别的地方在于智能抽象(intelligent abstraction)——即"具体到足以做有意义的工作、又通用到足以到处复用"的代码。Unit 2 中你将探索两个这样的抽象:

  • RestClient——一个用于 HTTP callout 的虚父类。你不再需要为每次 callout 写 5 行以上的样板代码,而是直接得到 get()、post()、put()、del() 方法。继承 RestClient,callout 一行搞定;
  • Trigger Handler Framework——编写触发器的可复用模式。触发器本身不再包含逻辑,而由一个 handler 类把执行分派到与上下文对应的方法:beforeInsert()、afterUpdate() 等。同一个框架同时适用于标准对象和平台事件。

这些抽象节省代码、减少 bug,并让测试变得异常简单——这正是区分资深开发者和初学者的那种抽象。

创建新的 Trailhead Playground(Create a New Trailhead Playground)

slide_6

从一个干净的环境开始:

  1. 滚动到本页底部;
  2. 点击 Launch 旁的下箭头;
  3. 选择 Create a Trailhead Playground;
  4. 等待 3–4 分钟完成创建。

务必使用全新的 Playground!Apex Recipes 应用包含触发器、类、自定义对象和平台事件——把它们部署到已有自定义的组织里可能产生冲突,尤其是针对 Account 这类标准对象的触发器。一个干净的 Playground 能确保部署顺利、所有测试通过。创建好后,下一步是拿到凭据。

获取 Playground 用户名与密码(一):查找凭据(Get Credentials (1): Find Credentials)

slide_7

获取你的 Playground 登录凭据——后续 Salesforce CLI 认证时会用到:

  1. 滚动到本页底部,点击 Launch 打开你的 Playground;
  2. 如果看到 Get Your Login Credentials 标签——点击它、记下用户名,然后点击 Reset My Password;
  3. 如果没有,从 App Launcher 中找到并打开 Playground Starter,按步骤操作;
  4. 查收邮件中的重置链接;
  5. 设置新密码并确认。

为什么需要重置密码?CLI 通过浏览器登录流程认证,会自动打开 Salesforce 登录页,你在那里输入用户名和密码。而自动生成的 Playground 密码不会显示给你,所以必须重置成自己知道的密码,才能完成 CLI 的认证步骤。

获取 Playground 用户名与密码(二):保存与使用(Get Credentials (2): Save & Use)

slide_8

重置密码后,把用户名和密码都保存在一个安全的地方——部署时 Salesforce CLI 会打开浏览器登录页,届时需要输入它们。

Salesforce CLI 使用基于 OAuth 的认证:你会直接在浏览器里登录 Salesforce,而不是在终端里输入凭据。你的密码只在你和 Salesforce 之间,从不进入终端——这与 Postman 的 OAuth 流程一致。如果弄丢了密码,重复重置流程即可。

把凭据放在随手可及的地方,下一节部署应用时就要用到。

获取 Git 命令行(Get Git Command Line)

slide_9

安装 Git——用于克隆 Apex Recipes 仓库的版本控制系统:

  1. 从 https://git-scm.com/downloads 下载并安装,全部接受默认设置;
  2. 验证安装——在 Terminal(macOS)或 Command Prompt(Windows)中输入 git,输出应显示一串 git 命令列表。如果报错,重启终端再试。

Git 是一次性安装。它在本项目里只用一次:把 Apex Recipes 仓库从 GitHub 克隆到本地。之后 Salesforce CLI 会接手,从本地副本部署到你的 Playground。链路是:GitHub → git clone → 本地文件 → CLI → org。

部署应用(一):VS Code 与终端设置(Deploy the App (1): VS Code & Terminal Setup)

slide_10

用 Visual Studio Code 和 Salesforce CLI 把 Apex Recipes 部署到组织:

  1. 打开 Visual Studio Code;
  2. 打开 Command Palette:点击 View → Command Palette(或按 Ctrl+Shift+P / Cmd+Shift+P);
  3. 打开终端:点击 Terminal → New Terminal。

为什么用 VS Code?Salesforce Extension Pack 为 Apex 开发提供了语法高亮、自动补全和组织集成;集成终端让你无需切换窗口就能运行 CLI 命令;你可以在同一个工具里既浏览代码又部署代码。接下来,按 GitHub 上项目 readme 的说明克隆并部署。

部署应用(二):克隆与部署步骤(Deploy the App (2): Clone & Deploy Steps)

slide_11

按 github.com/trailheadapps/apex-recipes 上项目 readme 的 "Installing the App using a Developer Edition Org or a Trailhead Playground via the Salesforce CLI" 一节操作。流程大致是:

  1. git clone <仓库地址>——把代码下载到本地;
  2. cd apex-recipes——进入项目文件夹;
  3. 用你的 Playground 组织认证——CLI 打开浏览器,你登录;
  4. 把源码部署到组织——sf project deploy start(或类似命令);
  5. 分配权限——授予对 Apex Recipes 应用的访问。

部署成功后,Apex Recipes 应用就会出现在组织的 App Launcher 中。所有 Apex 类、触发器、自定义对象、平台事件和测试现在都在你的组织里了。具体的 CLI 命令可能因 CLI 版本和当前 readme 略有差异——始终以 GitHub 说明为准。Unit 2 里,你将探索刚部署的这些代码。

了解 Apex Recipes 示例应用(02 Get to Know the Apex Recipes Sample App)

slide_12

应用已部署,现在探索代码。你将用组织里的 Apex Recipes Lightning 应用浏览两个关键抽象的源码:把 HTTP callout 简化为单行操作的 RestClient 虚类,以及把触发器上下文管理与业务逻辑分离的 Trigger Handler 框架。学完本单元,你会理解智能抽象如何让 Apex 代码更易维护、更易测试、更易复用。

发起 HTTP Callout(一):样板代码问题(Making Http Callouts (1): The Boilerplate Problem)

slide_13

向外部服务发起 HTTP callout 是 Apex 最常见的任务之一——获取货币汇率、更新公司 ERP 系统、集成第三方 API,开发者经常要做。标准的 Apex callout 代码直接了当,却充满样板代码,每次都要重复同样的设置:

HttpRequest req = new HttpRequest();
req.setEndpoint('https://api.example.com');
req.setMethod('GET');
Http http = new Http();
HttpResponse res = http.send(req);
// 最后才处理响应...

在真正处理响应之前,就已经有 5 行以上的重复代码了。一个项目里有 10 个 callout 方法,那就是 50 多行复制粘贴的样板——重复、易错、难维护。Apex Recipes 展示了一种更好的做法。

发起 HTTP Callout(二):RestClient 抽象(Making Http Callouts (2): The RestClient Abstraction)

slide_14

打开应用来探索:

  1. App Launcher → Apex Recipes;
  2. 展开 Integration Recipes → 选择 Callout Recipes;
  3. 在代码查看器中找到 rawCallout() 方法——这是带全部样板的传统写法(5 行以上);
  4. 再找 httpGetCalloutToSecondOrg()——同样的工作,一行搞定。

怎么做到的?靠 RestClient 虚类:

  • 它提供了预置的 get()、del()、put()、post() 方法;
  • 继承 RestClient 的类自动获得所有这些方法;
  • 你只需覆盖真正需要定制的部分(端点 URL、认证请求头)。

点开一个 recipe,右侧不仅显示代码,顶部还有对应 Test Class、类文档和相关类的标签——Callout Recipes 就有一个相关的 RestClient 类。比较 rawCallout()(5 行设置 + 业务逻辑)与 httpGetCalloutToSecondOrg()(1 行),就能直观看到这个抽象如何减少代码量。通用的 HTTP 管道在 RestClient 里处理一次,处处复用。

发起 HTTP Callout(三):为什么抽象重要(Making Http Callouts (3): Why Abstractions Matter)

slide_15

RestClient 模式带来的价值:

  • 代码更少——每次 callout 1 行 vs 5 行以上,行数越少,出 bug 的地方越少;
  • 一致性——每个 callout 都用同一个基础,新成员看任何一个 callout 方法都能立刻看懂模式;
  • 可测试性——mock 一次 RestClient,就能测试所有 callout 类;没有抽象时,每个测试都要单独 mock HttpRequest;
  • 可维护性——如果 Salesforce 将来调整 HTTP 类 API(不太可能但有可能),你只需改 RestClient 一次,而不是改动整个代码库里的每个 callout 方法。

这就是"智能抽象"的含义:解决通用问题的代码,让你能专注于解决自己的具体问题。这也是"能用的代码"与"写得好的代码"之间的区别。

编写可持续的触发器(一):触发器问题(Writing Sustainable Triggers (1): The Trigger Problem)

slide_16

触发器是 Apex 开发者世界里的"瑞士军刀电锯"——你几乎能用它做任何事,但一不小心就会砍错树。常见的触发器反模式包括:

  • 业务逻辑直接塞进触发器主体;
  • 没有关注点分离——触发器自己包办一切;
  • 难以测试——逻辑埋在触发器里,单元测试无法直接访问;
  • 脆弱——改一处就可能全盘崩溃。

Apex Recipes 遵循最佳实践,使用 Trigger Handler Framework。应用里有两个触发器:一个在 Account(标准对象)上,另一个在自定义平台事件上——同一个框架同时处理这两种场景。统一的模式、可复用的设计。

编写可持续的触发器(二):框架实战(Writing Sustainable Triggers (2): The Framework in Action)

slide_17

在应用里探索 Trigger Handler:

  1. 展开 Trigger Recipes → 选择 AccountTriggerHandler;
  2. 注意右侧两个相关代码标签:TriggerHandler(父框架类)和 AccountServiceLayer(业务逻辑);
  3. 点击 TriggerHandler 标签,找到 run() 方法——它的 switch 语句负责把执行分派到与上下文对应的方法:beforeInsert()、afterUpdate() 等;
  4. 回到 AccountTriggerHandler 标签,找到 beforeInsert()——它调用 AccountServiceLayer;
  5. 点击 AccountServiceLayer,找到 incrementCounterInDescription() 方法——这才是真正要执行的业务逻辑。

架构链路是:Trigger → TriggerHandler.run() 分派 → AccountTriggerHandler.beforeInsert() → AccountServiceLayer.incrementCounterInDescription()。每一层都做了关注点分离!触发器本身极简——只负责实例化 handler 并调用 run()。

编写可持续的触发器(三):为什么这种架构胜出(Writing Sustainable Triggers (3): Why This Architecture Wins)

slide_18

这种三层架构(触发器分派器 → 上下文 handler → 服务层)带来三个实打实的好处:

  • 可测试性——业务逻辑在服务层而非触发器里,你可以直接调用服务方法写单元测试,无需插入记录来触发触发器。测试更快、更简洁、更聚焦;
  • 可复用性——incrementCounterInDescription() 既能被触发器调用,也能被暴露给 Flow 的 Invocable Method、自定义 REST 端点或 Batch 类调用。写一次,处处使用;
  • 执行顺序可控——框架的 switch 语句让你显式控制"哪个方法在哪个触发器上下文中以何种顺序运行"。不再猜测,没有意外。

同一个框架同时处理标准对象触发器(Account)和平台事件触发器。一个模式,多种用例——这就是智能抽象的力量。

还有更多(一):超越 Callout 与触发器(There's So Much More (1): Beyond Callouts & Triggers)

slide_19

你只探索了两个抽象,但 Apex Recipes 里还有更多:

SOQL 与安全:

  • 尊重字段级安全(FLS)和 CRUD 权限的查询;
  • 防止数据泄露的安全 SOQL 模式。

控制流:真实 Apex 场景中 if/else 和 switch 语句的示例。

异步 Apex:

  • Queueable 类——可链式调用的异步任务;
  • Batch 类——处理数百万条记录;
  • Scheduled 类——基于时间的自动化;
  • Future 方法——简单的"发完即忘"异步执行。

每个 recipe 都是"正确实现某个特定模式"的聚焦示例——不是理论,而是真实、可运行、经过测试的代码。

还有更多(二):你的参考代码库(There's So Much More (2): Your Reference Codebase)

slide_20

Apex Recipes 是你长期使用的 Apex 参考库:

  • 需要写 Queueable?打开 Async Apex Recipes,复制模式;
  • 需要触发器 handler?打开 Trigger Recipes,适配框架;
  • 需要 HTTP callout?打开 Integration Recipes,继承 RestClient;
  • 需要保护 SOQL?打开 Security Recipes,应用 FLS/CRUD 检查。

这个示例应用还在持续演进——新的 recipe 会随时间不断加入。你可以把它用作:

  • Apex 最佳实践的学习工具;
  • 实现模式的参考;
  • 以可持续架构启动新项目的模板。

把 GitHub 仓库收藏、加星、克隆到本地。下次要写触发器、Batch 类或 HTTP callout 时,先查查 Apex Recipes——很可能已经有一个 recipe 展示了正确做法。这就是你从"写出能跑的 Apex"升级到"写出安全、可持续、可维护的 Apex"的路径。


文章来源:Trailhead - Quick Start: Explore the Apex Recipes Sample App