DEX455

Apex 集成与工具完全指南:Callouts、命名凭据、WSDL2Apex、Mock 测试

课程介绍

Apex集成完全指南:Callout基础(SOAP+HTTP+REST三种/Remote Site Settings未注册失败/命名凭据免远程站点)、命名凭据(Per User vs Named Principal/Merge Fields动态引用sObject字段/最多100个/不编码请求体)、WSDL2Apex(Generate from WSDL/请求响应封装+SOAP端口类/Document+Literal+RPC支持/SOAP1.2+MTOM+WSDL2.0不支持)、WebServiceMock+HttpCalloutMock(StaticResourceCalloutMock/MultiStaticResourceCalloutMock/Mock前后可DML)、证书(clientCertName_x+setClientCertificateName)、Callout限制(100个+120s+10s超时+6/12MB)、Continuation(最多3并行+60s超时+state传上下文+仅Visualforce+Test.setContinuationResponse)。

课程章节

本课程共有 63 个章节

  • 1

    Integration and Apex Utilities

    第 353 页

    嗨,同学,欢迎来到这一章。这章的内容呢,其实是一个,完整的语言参考,,专门讲怎么用Apex跟外部的服务做集成。 简单来说,Apex允许你通过一种叫做,callout,的机制,去调用外部的SOAP或者REST这种Web服务。不管外面是用什么技术搭的接口,只要它支持这些标准,你的Salesforce就能跟它对话。 另外,我们还准备了一些实用的小工具,帮助你在集成时处理JSON格式的数据、HTML内容,或者做数据安全和编码转换。甚至还有一个专门用来处理,文本正则表达式,的工具,方便你做字符串匹配和替换。 接下来,我们会把callout的方方面面都过一遍,很全面哦。我们会讲: - 怎么配置,远程站点设置,,让Salesforce允许访问外部地址; - 如何使用,命名凭据,来安全地管理认证信息; - 怎么从一个,WSDL文档,自动生成Apex类,省去手写代码的麻烦; - 怎么创建,HTTP调用,,直接发请求拿数据; - 还会涉及,双向SSL证书,的配置,保证通信安全; - 当然也得了解,调用限制,,避免踩坑; - 最后,如果你在Visualforce页面或Lightning组件里需要做长时间运行的同步调用,我们还会用到,Continuations,这个特性,让请求乖乖等着不超时。 总之,这一章就是个集成大礼包,学完之后,你就能让Salesforce跟外面的世界畅通无阻地聊天啦。准备好了吗?我们这就开始吧。

    查看详情
  • 2

    Integration Capabilities Overview

    第 354 页

    今天我们来看看Apex里一些特别好用的内置工具,这些工具能帮我们轻松地和外部服务打交道,还能处理各种数据格式,让开发更省力。 首先,Apex可以直接跟外部的SOAP和REST网络服务对话,也就是我们常说的“Callout”。通过它,你的Salesforce就能调用外部的接口,获取或者发送数据了。 接着,说到数据格式,现在最流行的就是JSON。Apex对JSON的支持很到位,你可以直接把一个Apex对象转成JSON字符串,这叫序列化;反过来,也能把JSON字符串重新变回Apex对象,也就是反序列化。这样数据传输就非常方便。 如果你需要处理网页内容,Apex也提供了工具类,可以创建和解析HTML。甚至还可以用流和DOM的方式来操作,就跟前端开发一样灵活。 再来看文件压缩,Apex自带了一个原生Zip库。你只要用Compression命名空间里的类,就可以很方便地创建ZIP压缩文件,或者把压缩包解开。比如你想把多个文件打成一个zip包发给用户,这个功能就派上用场了。 数据安全方面,Apex提供了Crypto类,你可以用它来加密、解密、生成消息摘要,保护敏感数据。 还有编码工具类EncodingUtil,它能帮你对URL进行编码和解码,防止特殊字符乱码;还能把字符串转成十六进制格式,常用于数据校验和加密场景。 最后,如果你要做复杂的文本搜索,Apex的模式和匹配器类能让你用正则表达式来匹配和提取文本。比如验证邮箱格式、提取日志中的特定信息,这都是利器。 简单来说,Apex不仅是一门语言,它还内建了很多实用的“瑞士军刀”,让我们处理外部集成、数据格式、压缩、加密、编码和文本搜索时,不用再从零造轮子了。好,这部分内容就到这里,大家先消化一下。

    查看详情
  • 3

    Invoking Callouts Using Apex

    第 355 页

    好,咱们现在来聊聊本章的核心知识点:调用号召,也就是Apex里常说的 Callout。 你可以把 Callout 想象成 Apex 代码主动给外面的系统打电话,或者发个请求过去,然后对方回个话——也就是接收响应。这样一来,Salesforce 就能跟外部的服务紧紧集成在一起了。 Apex 能对接两种常见的外部服务:一种是基于 SOAP 和 WSDL 的传统 Web 服务,另一种就是现在流行的 RESTful 风格的 HTTP 服务。 不过有个很重要的安全点要记住:每次从 Salesforce 往外发 Callout 的时候,都得先在我们后台的“远程站点设置”里,把那个目标网站的地址加进去。 如果没加,Salesforce 会默认拦住这个请求,Callout 就直接失败了,因为它不允许调用未经授权的网络地址。 那有没有例外呢?有的,如果你在 Callout 中用了,命名凭据,来指定端点,那就不用再去配远程站点设置了,因为凭据本身就包含了端点的信息,还能帮你管理好身份验证,更安全也更省事。 好,关于 Callout 的基本概念先说到这儿,后面我们看具体怎么用。

    查看详情
  • 4

    Callout Fundamentals

    第 356 页

    同学们,今天我们来聊聊Apex里怎么跟外面的系统打交道,也就是Callout的基本概念。 首先你要记住一个很重要的安全规则:,任何时候,你想在Apex里调用一个外部网站,必须先在Salesforce的“远程站点设置”里把这个网站的地址加进去,否则调用一定会失败。, 因为Salesforce会默认把所有没登记过的网络地址都当成是未经授权的访问,直接帮你挡掉。 不过,有一种情况可以省略这一步——,如果你用的是“命名凭据”来指定端点,就不用再去配置远程站点设置了。, 命名凭据的好处在于,它在一个地方就帮你同时定义好了目标URL和所需的认证信息,用起来更省事,也更安全。 后面我们讲到长时间运行的请求时,还会详细介绍几种不同的调用类型,比如,SOAP服务、普通的HTTP调用,还有异步Callout,等等。简单来讲,,Callout就是让Apex主动去调用外部的Web服务或HTTP服务,。而反过来,,Apex Web服务,则是让外部的应用通过Web服务来调用我们写好的Apex方法。 好,这一页的重点就是这些,我们继续往下看。

    查看详情
  • 5

    Adding Remote Site Settings

    第 357 页

    同学,我们来看一下怎么让我们的Apex程序安全地跟外部的网站打交道。在Salesforce里,所有从Apex发出的对外部网站的调用,都得先在一个叫“远程站点设置”的地方把这个网站“登记”一下。你想象成就像你要去别人家串门,得先跟主人打个招呼、拿到门禁许可,不然就会被挡在门外,调用就会直接失败。 不过呢,有一种情况可以省掉这一步。如果你在Apex里调用时,使用的是“命名凭据”来指定这个外部服务的地址,那就不需要再单独去远程站点设置了。因为命名凭据相当于一个打包好的信封,它里面已经写清楚了目标网址,以及访问时所需要的身份验证信息,比如用户名密码或者令牌。Salesforce一看,哦,这个凭据已经包含了该有的安全设置,那就直接放行。 所以,简单总结一下:直接用网址调用外部服务,一定要先去远程站点设置里注册;如果用了命名凭据作为端点,那就可以跳过这一步。如果你还没设置过命名凭据,可以去Salesforce的帮助文档里搜索“定义命名凭据”,里面有详细的步骤。好,这个小知识点就到这里,我们继续下一部分。

    查看详情
  • 6

    Adding Remote Site Settings — Steps

    第 358 页

    今天我们来快速聊一聊在Salesforce里怎么添加一个远程站点设置。这个操作非常基础,但很重要,尤其是当你的Apex代码需要调用外部的Web服务时,你必须提前在这里“打卡”,不然Salesforce为了安全会直接拦住你的请求。 那我们一步步来。首先,你进入设置,就是右上角那个齿轮图标。在左边的快速查找框里,直接输入“远程站点设置”,中文环境可能也叫“远程站点设定”。输入完后,系统会把它搜出来,你点进去。 进入这个页面后,你会看到一个列表,上面列着所有已经授权的外部站点。我们现在要新增一个,所以点击“新建远程站点”按钮。 接下来弹出的编辑页面,有几个框要填。第一个是“远程站点名称”,这个你可以随便起,但最好用个有意义的词,一看就知道是连到哪个系统的,比如“订单系统API”或者“邮件服务”。注意,这个名称只是给自己看的,不会影响实际连接。 第二个框是“远程站点URL”,这个就要写真实要连接的外部网址了。比如外部系统提供给你的接口地址是 `https://api.example.com`,那开头必须是https,然后完整的域名,注意不要在后面加路径。像 `https://api.example.com/v1` 这种就错了,只需要到根域名的部分。 下面还有一个“描述”框,可填可不填,写点备注方便以后维护。然后点击“保存”。 这里有个提性能的小点,如果你的远程站点用的是HTTPS加密,最好确认一下对方服务器是否开启了OCSP装订,也就是在线证书状态协议装订。这东西可以加快证书校验的速度,提升连接效率。不过这一步是外部网站自己的配置,我们只需要知道有这么回事就行。 保存成功后,这个远程站点就会被加入授权列表,接下来你写的Apex代码在调Http请求时,只要目标URL匹配这里设置的站点,就能顺利发出去了。 记住,URL必须精确匹配,大小写也得一致。如果不匹配,运行时会报“未授权的端点”错误,那就要回来检查是不是没配,或者URL写错了。 好,这节课关于远程站点设置的步骤就这些,很简单,你动手试一下就熟了。

    查看详情
  • 7

    Named Credentials as Callout Endpoints

    第 359 页

    同学们,咱们接着聊一个非常实用的功能,叫做“命名的凭据”(Named Credentials)。你可能在想,这名字听起来有点抽象,别急,我打个比方你就明白了。 想象一下,你要给很多餐馆打电话订餐。每次都得先翻通讯录找电话号码,然后报自己的会员卡号、密码之类的身份信息,对吧?这很麻烦,而且万一你记错了密码,或者拨错号码,订餐就失败了。 在Salesforce里,当我们的Apex代码需要调用外部系统时(比如发个请求给支付网关或天气API),也是一样。你得在代码里写清楚那个外部服务的网址,还得自己处理用户名、密码、密钥这些认证信息。这不仅让代码变得冗长,而且如果密码改了,你还得去代码里更新,很不安全。 而“命名的凭据”就像是Salesforce专门给你准备的一个通讯录和安全管家。你只需要,一次性,地在设置里创建一个命名的凭据,填好这些信息: - 那个外部服务的网址(URL),比如`https://api.example.com`。 - 以及访问它需要的认证方式,比如用户名密码,或者OAuth令牌。 然后,给它取个好记的名字,比如“我的支付网关”。 之后,当你在Apex代码里要发起调用(Callout)时,你根本不用再写那一长串URL,也不用操心怎么传密码。你只需要在代码里引用这个,名字,,就像说:“Salesforce,帮我联系一下‘我的支付网关’,发送这个请求”。剩下的所有认证、加密这些脏活累活,Salesforce全自动替你处理了。你的代码变得干净又安全。 还有一个很方便的小细节:通常,如果你直接在代码里写了个外部网址,还得去“远程站点设置”里把它加白名单,不然Salesforce会拦住请求。但如果你用的是,命名的凭据,,这个步骤也可以跳过了,因为Salesforce已经信任了这个你定义好的凭据,不需要你再额外去配置远程站点。 所以总结一下,命名凭据的好处是:,集中管理,,,简化代码,,,增强安全性,,还省去了配置远程站点的麻烦。当你以后需要和外部系统集成时,记住这个小管家,它会让你省心很多。 好了,关于命名凭据的概念,我们就先了解到这里。有什么问题随时问我!

    查看详情
  • 8

    Named Credentials — Benefits & Usage

    第 360 页

    同学们,今天我们来看一下Salesforce里一个特别实用的功能,叫,命名凭据,。 你可以把命名凭据理解成:我们给一个外部服务的地址和登录信息,起一个固定的名字。以后在代码里要做接口调用的时候,就直接喊这个名字,而不用再一遍遍去写又长又容易错的URL和认证信息了。 这样做最大的好处就是维护起来非常省心。比如说,最近公司有个第三方系统的接口地址换了,从原来的测试环境迁移到了正式环境。在以前,你要是直接在Apex代码里写死了URL,那所有相关的调用位置你都得改。但现在有了命名凭据,你只需要进到设置里,把那个命名凭据对应的端点URL改一次,,所有引用它的地方就都跟着生效了,,你不用碰一行代码。 再举个例子,假设你做了一个功能要部署给多个客户,或者你们公司有沙盒、生产等好几个环境。这些环境里,同一个外部服务可能地址不同。这时候,你可以在每个环境创建一个,叫法一模一样,的命名凭据,但把各自正确的URL填进去。然后你的代码里只引用这个共同的名字,打包部署到任何环境都能直接跑,完全不用为环境差异改代码,非常方便。 那在代码里具体怎么引用命名凭据呢?格式其实很简单。它是以 `callout:` 开头,后面跟上你给命名凭据起的名字,还可以在后面加一段具体的路径。 比如你有一个命名凭据叫 `MyPaymentGateway`,你想调用它的下单接口 `/api/orders`,那完整的地址写法就是:`callout:MyPaymentGateway/api/orders`。 如果还想在后面带上问号跟查询参数,比如 `?page=1`,你直接拼上去就行,就像普通网址一样:`callout:MyPaymentGateway/api/orders?page=1`。 这样一来,你既不用在代码里暴露真实的服务器地址,也把认证信息集中管理了,又安全又好维护。 好,关于命名凭据的基本概念我们就先讲到这儿。大家可以先消化一下,下一节我们会看看怎么在设置里具体创建一个命名凭据。

    查看详情
  • 9

    Named Credentials — Code Comparison

    第 361 页

    同学们,咱们这节课来聊聊命名凭据(Named Credential)最让人省心的一点——身份验证这块儿。 你想啊,平时要跟外部系统集成,绕不开的一件事就是认证。但要是没有命名凭据,哪怕只是最基本、最简单的用户名密码认证,你都得在Apex代码里自己去写逻辑:怎么传用户名密码、怎么拼Header,一堆繁琐的细节,代码马上变得臃肿又难维护。要是换成OAuth2.0这种更复杂的协议,那简直要写一大堆回调、刷新令牌的逻辑,既容易出错,又不好调试。 而一旦用上了命名凭据,情况就完全不同了。关键在于:不管后台实际用的是什么认证方式,你写的Apex代码都可以,一模一样,,完全不用动。为什么?因为所有跟身份验证相关的脏活累活,都转移到了“外部凭据”(External Credential)身上。这个外部凭据,会去引用咱们在Salesforce里已经定义好的身份验证提供者,比如Auth. Provider。换句话说,认证细节全在配置里,代码只负责说“我要调这个服务”,Salesforce平台自己就知道该怎么安全地去验证身份。 说得再直白一点:命名凭据这个东西,一头帮你指定好远程服务的端点URL,另一头呢,就关联上那个配置好认证方式的外部凭据。所以你Apex里只需要直接引用这个命名凭据,平台就会自动帮你搞定所有认证步骤。譬如你调用OAuth端点,不需要写一句OAuth的代码,就能自动获取令牌、自动刷新,是不是很优雅? 所以说,处理复杂的OAuth认证,正是命名凭据最理想的应用场景。记住这个结论:认证逻辑再变,代码岿然不动,轻松可靠全靠命名凭据。这一页Slide的核心,就是让大家体会到这种“分离关注点”的巨大好处。有什么疑问咱们可以随时交流。

    查看详情
  • 10

    Custom Headers and Bodies with Named Credentials

    第 362 页

    同学们,咱们来看这页讲的是命名凭据的一个小窍门。 平时Salesforce很贴心,会帮你自动往请求里加上一个标准的授权标头,就是那个 Authorization ,这样你省得自己写了。但有时候,这个自动加上的东西反而会帮倒忙。 比如,你调用的那个外系统,它不认这种标准格式,它就非得让你在请求头里塞一个安全令牌,或者要求你把用户名密码直接写在请求正文里。这时候你怎么办?很简单,咱们可以把自动生成标头这个选项给它关掉,就禁用它。 同时,在写Apex代码的时候,你还可以用合并字段来手动拼出你想要的HTTP头和正文内容。这样一来,灵活性一下就上来了。不管对方系统有多奇怪的要求,比如非要把加密凭据放在某个自定义的头里,或者非得在请求体里传用户名密码,咱们用命名凭据配上合并字段,都能轻松搞定。 明白了吧,就是让本来只能走直道的命名凭据,通过这几招,学会了拐弯儿,什么特殊路况都能应付。

    查看详情
  • 11

    Custom Headers — Generate Authorization Header Options

    第 363 页

    同学们,咱们今天来看一下命名凭据配置页面上两个很实用的选项。很多同学可能经常看到它们,但不确定什么情况下该勾选,什么情况下该关掉。我帮你用大白话理一理。 首先,第一个选项叫“生成授权标头”,默认是打勾的。它的意思是,每次你通过这个命名凭据去调用外部系统,Salesforce 都会非常贴心地自动帮你生成一个身份认证的请求头,带着它去敲门。这就好比你去酒店,前台直接帮你刷好了房卡,你不用自己操心怎么开门。 那什么时候需要把这个勾去掉呢?主要有两种情况: 第一种,对方系统比较特别,根本不认可 Salesforce 自动生成的这种授权头格式,那你就别硬塞给人家了,关掉它自己想办法。 第二种,你想完全靠自己写 Apex 代码来定制授权逻辑,比如有些接口需要多重签名、动态令牌,这时候也得取消勾选,不要让 Salesforce 自动插手。 另外要记住一点,如果你的命名凭据是专门给外部数据源用的,那这个“生成授权标头”一定要保持开启,否则外部数据源就没办法正常连接了。 接下来,咱们看另一个选项:“允许合并字段”。这个选项一旦开启,你的 Apex 代码就能在发起调用的时候,用合并字段直接把组织里的数据填到请求头和请求体里。举个例子,假设你要在请求头里加上当前登录用户的邮箱,或者在请求体里塞进去一个动态的账户ID,只要打开这个选项,代码里写个简单的合并表达式就行了,非常灵活,不用每次都去拼字符串。这就好比你写邮件模板,把收件人姓名自动填进去一样方便。 所以总结一下,授权标头选项控制是否让平台代劳认证,按需开关;允许合并字段则是给 Apex 调用加了一把动态数据填充的钥匙。把这两个设置理解透,以后调用外部接口就能少踩很多坑。

    查看详情
  • 12

    Merge Fields for Apex Callouts

    第 364 页

    大家好,我是你们的Salesforce老师。今天我们来聊聊一个非常实用的小知识点,就是在Apex代码中,怎么利用,命名凭证,(Named Credential)提供的合并字段,帮我们自动拼出HTTP请求的授权头,从而安全、方便地调用外部接口。 你可能已经知道,命名凭证可以在后台配置好连接外部服务的地址、身份验证方式,让我们在代码里不用硬编码用户名密码或令牌。那具体怎么在Apex里拿到那些验证信息呢?Salesforce给了我们一组,合并字段,,就像占位符一样,写请求体或者请求头的时候,直接引用它们,运行时会自动替换成正确的值。 这些字段中,有几个的可用性和我们选的身份验证方法直接相关: - 如果你用的是,密码验证,(Password Authentication),那么 ,`{!Credential.Username}`, 和 ,`{!Credential.Password}`, 这两个字段就可以用。注意哈,幻灯片翻译里的“收件箱”其实是错的,是“用户名”才对。这样你可以单独拿到用户名和密码。 - 要是你用的是,OAuth 2.0 验证,,那你会拿到 ,`{!Credential.OAuthToken}`, 这个字段,里面装着OAuth的访问令牌。 除此之外,还有两个非常好用的通用字段,无论什么验证方式都能用,它们会帮你直接把整个`Authorization`头部的值准备好: 一个是 ,`{!Credential.AuthenticationMethod}`,,它会告诉你当前是什么认证方式:密码验证时就返回字符串 ,Basic,,OAuth 2.0 就返回 ,Bearer,,如果根本没配验证,这个值就是空的。 另一个是 ,`{!Credential.AuthenticationHeaderValue}`,,它就更直接了,返回的就是你可以直接放到HTTP头`Authorization`后面的那个值。比如密码验证时,它帮你把用户名密码按“用户名:密码”格式做完Base64编码;OAuth时,它直接给你令牌本身;没验证就是空。 所以你在代码里写HTTP请求的时候,可以这样用: ```apex HttpRequest req = new HttpRequest(); req.setHeader('Authorization', '{!Credential.AuthenticationMethod} {!Credential.AuthenticationHeaderValue}'); ``` 或者像有些例子,直接写成 `'Authorization', '{!Credential.AuthorizationHeaderValue}'`,因为那个 `AuthenticationHeaderValue` 有时候已经带了前缀,具体看文档配置。 用这些合并字段,你的代码就完全不用硬编码敏感信息,而且换一个命名凭证,相同的代码换个环境也能直接用,非常灵活。 简单总结一下: - 密码验证:你能拿到`Username`和`Password`,`AuthenticationMethod`返回`Basic`,值被编码好。 - OAuth 2.0:你能拿到`OAuthToken`,`AuthenticationMethod`返回`Bearer`,值就是令牌。 - 无验证:这些字段基本都空,`AuthenticationMethod`也是空。 好了,这一页的内容就这么多。理解了这几个合并字段,你就能安全高效地在Apex里构建对外请求了。有什么问题随时问我。我们下节课见!

    查看详情
  • 13

    Merge Fields — Important Considerations

    第 365 页

    好,咱们来看一下在 Salesforce 里用“合并字段”构建 HTTP 请求的 Header 和正文时,必须留意的几个要点。这些点虽小,但很容易踩坑,你听我慢慢说。 首先,要想让你写的 Apex 代码顺利用上合并字段,光写代码可不够。你的 Salesforce 管理员得先在对应的命名凭据里,把两个开关都打开:一个是“允许在 HTTP 头部使用合并字段”,另一个是“允许在请求正文中使用合并字段”。这两个权限缺一不可,否则合并字段根本不会生效。 接着,如果你需要读写那些自定义的 HTTP 头,注意可不是直接在合并字段里乱写,而是得通过 Connect REST API 去操作。这是官方指定的方式,别走错路了。 再说正文里的合并字段。如果你想对里面的特殊字符做转义,可以用一个公式函数叫 `HTMLENCODE`。但这里规矩很严:公式必须以 `HTMLENCODE` 打头,而且不能再嵌套别的公式函数,就它一个,干干净净。反过来,这个 `HTMLENCODE` 可不许用在 HTTP 头部的合并字段里。头部的特殊字符要另外想办法,比如凭据里自带的处理机制,千万别硬套。 最后,还跟 SOAP API 调用有个相关点:一旦在 SOAP 调用里用了合并字段,那个 OAuth 访问令牌是不会自己刷新的。也就是说,如果令牌过期了,你的调用就会失败,需要你额外去处理令牌的刷新逻辑。 把这几点记牢,你在用合并字段构造 HTTP 请求时,就会顺手很多,不容易被小问题卡住。

    查看详情
  • 14

    SOAP Services: Defining a Class from a WSDL Document

    第 366 页

    同学们,今天我们来看看怎么用Apex和外部Web服务集成,特别是SOAP类型的服务。先说一下,在Salesforce里,如果我们想把外部系统提供的一个SOAP Web服务变成可以在Apex里直接调用的方法,那就可以借助WSDL文档来帮我们自动生成对应的Apex类,这个过程就叫WSDL2Apex。 那什么是WSDL呢?WSDL全称是Web服务描述语言,你可以把它看成是Web服务的“说明书”。它用XML格式写清楚了服务有哪些操作、要传什么参数、返回什么结果,还定义了数据类型。我们只要拿到这份用XML写的WSDL文件,把它保存在本地硬盘上,或者从网络地址直接引入,Salesforce就可以帮我们生成一组Apex类。这些类里封装好了请求和响应的结构,也提供了可直接调用的方法,这样开发人员完全不用手写复杂的SOAP报文发送逻辑,直接像调用本地方法一样去调用远程服务就可以了。 具体操作很简单,在开发者控制台或者Setup里,进入Apex类,选择“从WSDL生成”,然后上传WSDL文件,系统就会自动解析并生成对应的Apex代码。生成出来的代码里会有一些代表复杂类型的内部类,还有调用服务的主方法。之后在你的业务逻辑里,只要new一个请求对象,填好参数,再调用生成的invoke方法,就能拿到返回结果。 不过这里有个很重要的实践建议,大家一定要记住:在考虑集成方案时,尽量优先使用Salesforce原生的消息传递机制,比如平台事件、Change Data Capture等异步消息通道来实现系统间的联动。为什么这样推荐呢?因为这些方式能更好地利用平台的高可用性,避免因为外部服务不稳定而拖慢我们整个事务。只有当你确实需要从Salesforce主动去调用一个外部第三方提供的SOAP服务,并且没有其他更合适的替代方案时,才去使用这种基于WSDL的标注调用。简单说就是,能用内部事件解耦的就不要轻易去碰实时同步标注,能用平,立的消息机制处理的,就不要轻易依赖外部调用。这样能让你整体的集成架构更可靠,也更易于维护。 好,这个部分的核心就两点:一是会用WSDL自动生成Apex代理类来调SOAP服务,二是懂得在合适的场景下选择最稳妥的集成方式。接下来我们演示一下生成过程和代码示例。

    查看详情
  • 15

    WSDL2Apex — Generation Process

    第 367 页

    好,同学们,今天我们来讲一个实用的操作,就是怎么从一个SDF文档来生成Apex类。这个功能在Salesforce里挺方便的,可以帮我们节省很多手动写代码的时间。 首先,你需要登录到你的Salesforce组织,然后在设置里找到Apex类。怎么找呢?在“设置”页面,左上角有个“快速查找”框,你直接在上面输入“Apex类”,然后从结果里点进去。 进去之后,你会看到一个按钮叫“从SDF生成”,点击它。这时候系统会弹出一个窗口,让你选择文件。你点“浏览”,然后去你电脑本地硬盘或者公司网络里找到那个SDF文档,把它选中。 这个SDF文档里可能定义了某些Web服务的接口,特别是它可能会引用一个外部端点,也就是SOAP服务的位置。这里要注意一个安全限制:Salesforce对出站端口做了严格规定。允许的端口只有这些:80端口(只能用于HTTP)、443端口(只能用于HTTPS),还有从1024到65535之间的端口(HTTP或者HTTPS都可以)。如果SDF里指定的端点用了别的端口,那生成出来的Apex类在调用时可能就会失败,因为防火墙不允许。所以用的时候一定要检查一下端口号。 选好文件后,点击“解析SDF”按钮。这时候Salesforce会帮你验证文档内容是否合法。它会分析SDF里定义的每个命名空间,自动生成一些默认的类名,同时如果发现错误,会马上报告出来。有两个常见的失败原因你要记住:第一,如果SDF里包含它不支持的架构类型,解析就会失败;第二,如果生成的Apex代码总字符数超过了100万个字符,也会失败,这是一个硬限制。所以如果SDF特别大,你可能需要拆分成多个文件来操作。 解析成功之后,系统就会自动创建Apex类,你就可以在Apex类的列表里看到它们,然后根据需要进行修改和使用了。 这就是整个流程,很简单对吧?关键点就是端口限制和文件大小限制要心里有数。好了,这一节就到这里,有什么问题随时问。

    查看详情
  • 16

    WSDL2Apex — Generation Process (cont.)

    第 368 页

    好,咱们今天来看这一页,讲的是生成 Apex 类的时候一些要注意的地方。你可能会用到这个功能,比如从 WSDL 文件生成代码去调用外部的 Web 服务。 首先,页面上会让你修改类名,你可以按需要改。注意哦,如果你有多个命名空间,把它们存到同一个类里是允许的,但整个 Apex 类的字符数加起来不能超过 100 万。这是个硬限制,避免类太庞大。 然后你点击“生成 Apex”按钮,就会跳到最后一页,上面会列出生成成功的类,以及有没有错误信息。 成功生成的 Apex 类里,会包含一些 stub(桩代码)和类型类,这些是帮你调用第三方 Web 服务的基础结构。 特别要记住的是:对于每一个生成的类,系统其实会创建两个版本。第二个类的名字和第一个一样,只是前面会加上“Async”这个前缀。第一个类是用来做同步调用的,也就是代码会一直等到服务返回结果;第二个带 Async 前缀的,是用来做异步调用的,你的代码不会卡在那里等,可以继续执行其他任务。 所以简单来说,生成 Web 服务代理时,你总会得到一对类:一个同步,一个异步。异步那个名字前面多了个“Async”,方便你区分使用。 这样讲,清楚了吗?

    查看详情
  • 17

    WSDL2Apex — Generated Code Notes

    第 369 页

    同学们,咱们今天来聊聊从 WSDL 生成 Apex 类的时候,几个特别重要的小细节。平时咱们调用外部服务,经常要用到 WSDL 文件,但生成的代码可能会跟原始的命名不太一样,你先心里有个底,遇到就不会慌了。 第一个要注意的:如果 WSDL 里头有些词,在 Apex 里是属于保留字,比如 “limit” 这种,生成类的时候,Salesforce 会自动在那个词的末尾加上一个 “_x”。所以 “limit” 就会变成 “limit_x”。这样既能保留原意,又不跟语言的关键字冲突。 再来看一个情况:如果 WSDL 里某个操作,它的输出消息包含了好几个元素,那生成的 Apex 代码会自动把这些元素打包进一个内部类里面。这样做是为了结构清晰,你访问返回的数据时,就通过这个内部类的属性去拿,不容易乱。 还有一点要留心:Apex 类名是不允许出现句号的,但 WSDL 的命名里可能会用句点。没关系,生成代码的时候,所有的句点都会被下划线替换掉。比如原来的名字里带 “my.service”,就会变成 “my_service”。 那最终咱们怎么用这些生成的代码呢?很简单,你就在 Apex 里直接创建这个生成存根的实例,然后调用它上面定义好的方法,就像调用普通的 Apex 类方法一样,数据就发出去、接收回来了。这样就把外部服务轻松集成进来了。 记住这几个小规律,以后看生成的 Apex 类就不会觉得奇怪了。好了,今天就讲到这里,下回见。

    查看详情
  • 18

    HTTP Header Support in SOAP Callouts

    第 370 页

    同学们,今天我们来说一个很实用的技巧:在Salesforce里调用外部Web服务时,怎么设置HTTP标头。 你可能会遇到这样的场景——比如你想在请求里加一个授权信息,或者传递某个特定的Cookie。这时候,就可以利用生成的Web服务代理类,也就是我们常说的“树桩”类,里面有两个特殊的属性:`inputHttpHeaders_x` 和 `outputHttpHeaders_x`。 简单说,`inputHttpHeaders_x` 是用来设置你要发出去的请求头。如果你给它赋了值,它会完全覆盖掉原本那些标准的请求头,只按你指定的来。而 `outputHttpHeaders_x` 呢,是调用完成后用来读取对方返回的响应头,方便你检查服务端给你回了什么额外信息。 但这里我要特别提醒你一个安全问题:千万别直接把授权信息硬编码在代码里。这样做既不安全,也不好维护。正确的做法是用Salesforce的“命名凭据”,它提供了一个声明式、又安全的方式,来帮我我们管理所有外部服务的用户名、密码或者令牌这些敏感信息。你只要在设置里创建好命名凭据,然后在代码里引用它,Salesforce会自动帮你处理身份验证,把对应的HTTP头带上,根本不用你自己去拼授权字符串。 记住这个原则:用`inputHttpHeaders_x` 自定义头,但凭据管理交给命名凭据,这样你的集成既灵活又安全。

    查看详情
  • 19

    Accessing HTTP Response Headers

    第 371 页

    同学们,今天我们来看一个在使用Salesforce做HTTP请求时,经常会遇到的小细节——怎么获取响应头里的信息,以及不同API版本对响应编码的影响。 假设你写了一个Apex类,去调用外部的Web服务,服务返回了一些数据,还在响应头里附带了有用的元数据,比如分页信息、自定义追踪ID等等。你肯定想在代码里把这些头信息读出来,对吧?那就要用到`outputhttpHeaders_x`这个变量。 记住一个关键点:这个`outputhttpHeaders_x`默认是空的,什么也没有。就像你有一个空盘子,必须先把它变成一个真正的盘子,才能往里面装东西。所以,在访问响应头之前,你必须先手动把它初始化成一个新的Map。比如,你可以写`outputhttpHeaders_x = new Map<String, String>();`,然后再去做HTTP请求。否则,如果你直接尝试读取它的内容,就会遇到空指针异常。这个坑,早年不少开发者都踩过。 好,拿到了响应头,你可能会关心响应体的文字编码问题。比如返回的是中文、日文等多字节字符,编码如果搞错了,就会变成乱码。这里,Salesforce在API版本演进中有过重要变化。 在API 16.0及更早的版本里,Salesforce比较“固执”,它不管服务器在Content-Type头里声明了什么编码,一律按UTF-8来解码响应体。这在当时可能会导致一些兼容性问题。 但从API 17.0开始,Salesforce变聪明了,它会尊重服务器返回的Content-Type头里指定的字符集。比如服务器说“Content-Type: text/html; charset=Shift_JIS”,那Salesforce就会用Shift_JIS来解码,大大减少了乱码的可能。 所以,如果你在维护老代码,看到莫名其妙的乱码,不妨检查一下类或触发器的API版本。如果低于17.0,可以考虑升级一下,让编码处理更符合标准。 今天的要点就两个:一是访问响应头前一定要先给`outputhttpHeaders_x`建好Map;二是知道API版本会影响HTTP响应的解码方式,新版本更灵活。希望这能帮你少踩几个坑。我们下节课再见!

    查看详情
  • 20

    Supported WSDL Features

    第 372 页

    同学们,我们这节课来看一下 Apex 里怎么处理 XML 模式里那些数据类型。简单说呢,Apex 只支持一种叫做“文档字面量包装”的 SDF 风格,还有那些最基础的内置类型。它会把 XML 里的每一种模式类型,都自动对应到 Apex 自己的类型上,这样你处理 Web 服务的时候就方便多了。 我给大家理一理常见的对应关系,特别好记:像什么 anyURI、language、Name、NCName、NMTOKEN,还有 normalized 字符串和 token,它们本质上都是字符串,所以在 Apex 里就统一映射成 String。日期呢,就是 Date;日期时间,就是 Datetime;带浮点的小数,不管是 double 还是 float,一律变成 Apex 的 Double。再来看整数,int、integer 和 unsignedInt 一律映射成 Integer;长整数 long 和 unsignedLong 映射成 Long;短整数 short 和 unsignedShort 映射成 Integer。是不是挺整齐的? 注意了,有一个特例要记住:anyType 这个数据类型,Apex 是不支持的。也就是说,如果你的 Apex 代码是用 API 版本 15.0 或更高版本保存的,用到的 WSDL 里不能出现 anyType。不然就会报错。 所以总结一下,只要看到那些 XML 里的基本类型,脑子里自动和咱们 Apex 的类型做个连线,记住 anyType 是禁区,就不会出错了。这一页大家理解了吗?我们继续往下。

    查看详情
  • 21

    Supported WSDL Features (cont.)

    第 373 页

    好,我们来看这一页幻灯片,内容稍微有点技术,但我会把它拆得简单清楚,让你一听就明白。 首先,它说的是:当你在 Salesforce 里,用 API 版本 15.0 或者更高的版本来保存 Apex 代码的时候,Apex 能理解和处理 Web 服务描述语言(就是我们常说的 WSDL)里的某些结构模式。 这些结构模式的名字你可能看着眼熟,它们都是以 “xsd:” 开头的,比如 xsd:all、xsd:annotation、xsd:attribute、xsd:choice,还有加了特定限制的 xsd:element(特别是带有 ref 属性的那个),以及 xsd:order。简单理解,就是当外部系统通过 Web 服务跟你的 Apex 代码沟通时,如果它的定义文件里用了这些结构,Apex 是能认出来的,不会报错,能正常处理。 接下来,它特别提醒了几个关于 xsd:element 的 ref 属性的限制,这一点在日常工作中容易踩坑,得注意一下: 第一个限制:这个 ref 属性不能去引用不同命名空间里的元素。也就是说,你只能在同一个命名空间里用 ref 来指向另一个元素,不能跨空间指。 第二个限制:全局元素不能使用 ref 属性。什么叫全局元素?就是在 WSDL 里顶层直接定义的、没有父元素的那些元素,它们不能再去 ref 别的东西。 第三个限制:如果一个元素用了 ref 属性,那它就不能再同时带上 name 或者 type 属性了。因为 ref 本身就会把被引用的元素的名字和类型带过来,所以你不能再手动指定一遍。 最后一点,讲的是数据类型:blob、decimal 和 enum 这三种类型,在 Apex Web 服务里,它们只支持作为 “in” 参数,也就是只能被外部系统传进来给 Apex 方法用。当 Apex 方法内部要把这些类型的数据作为结果返回出去时——也就是作为 “out” 参数——是不支持的。换句话说,只能收,不能发。 你可以这样记:这三种类型在 Apex Web 服务里是“单向通行”的,只能进,不能出。 好,这一页的要点就这么多,你拿个小本记下关键限制,以后遇到 WSDL 解析报错,可以回头看看是不是犯了这些限制。

    查看详情
  • 22

    Unsupported WSDL Features

    第 374 页

    今天我们来聊一个Apex开发中非常实际的话题——当你用WSDL文件生成Apex代码的时候,有哪些“坑”是我们要绕开的。 首先想象一下,WSDL文件就像一份“合同”,描述了外部系统提供什么样的服务、怎么去调用它。Salesforce的Apex可以用工具把这份合同翻译成一堆Apex类,方便我们直接调用。但这个翻译工具并不万能,它有一些严格的限制,我们得提前知道,避免白费功夫。 第一个不支持的情况是,PRC/编码服务,。这听起来有点技术,简单说就是一种老式的、把数据类型编码进调用里的方式。如果你手里的WSDL里有这种服务,Apex是认不出的,直接会报错。 第二个要小心的,是,一个WSDL里有多个portTypes、多个服务或者多个绑定,。啥意思呢?PortType可以理解为“接口”,一些WSDL会在一份文件里定义好几个接口,或者有好几种不同的服务地址和协议绑定。但Salesforce的解析工具比较“专一”,它只能处理一个服务、一个绑定、一个portType的情况。如果你的WSDL里定义了多个,你只能先拆开,让每一份都只保留一个,不然解析会失败。 还有就是,导入外部架构,这件事。很多WSDL为了复用结构,会引用外部的XSD文件来定义数据类型。这个操作Apex是不接受的——它看不懂“请去那里找”这种指引。但有个小技巧:如果你真的需要那个外部的架构,你可以打开它,把里面的内容,直接复制粘贴到你的主WSDL里,,只要东西都在同一个文件里,Apex就能认。不过这要求你都放在同一个架构命名空间下,跨命名空间的引用还是不行。 ,类型映射,也是一个坑。Salesforce内部有个“翻译表”,能把WSDL里的XML数据类型(比如xsd:string)自动映射成Apex类型(比如String)。但是如果你的WSDL里用了什么怪类型,或者非常复杂的嵌套,而这个类型不在它支持的清单里,那生成代码就会失败。遇到这种情况,我们可能得考虑手动简化类型,或者用字符串去模拟。 ,WSDL文件的大小,也有限制。因为Salesforce里可以用WLSL文件(就是WSDL对应的Apex stub代码),但Apex代码本身有大小限制。如果你生成的Apex类太大了,超过了限制,毫无疑问会失败。这通常发生在非常庞大的WSDL上。 最后一个,注意WSDL的,文档字面量包装风格,,这个术语听着拗口。简单说,这是Web服务调用时消息怎么打包的一种方式。通常大家会使用“文档-字面量-被包装”这种风格,而有些系统可能生成“文档-字面量-裸”或者其他变种。如果WSDL的包装风格不是“被包装”的,那Apex解析的时候就会卡住,直接报错。所以拿到WSDL第一步,最好先确认下它的style和 use属性是不是符合要求。 总结一下,如果你想成功用WSDL生成Apex代码,就得保证:它是一个单服务、单绑定、单portType的文件,没有外部导入,类型都是Salesforce认识的,大小不会撑爆Apex限制,并且使用的是文档字面量包装风格。遇到不符合的,就按我们刚才讲的那些方法提前“修剪”一下WSDL。 这些限制听起来有点多,但提前了解了,就能避免调试时抓狂。实战中,我们通常会对WSDL做必要的清洗,然后再喂给Salesforce。现在你心里有数了吗?下次咱们就动手练一练怎么清洗WSDL。

    查看详情
  • 23

    Generated WSDL2Apex Code

    第 375 页

    同学们好呀,今天我们来讲讲怎么用Apex去调用外部的Web服务,这里有一个特别趁手的小工具,叫WSDL2Apex。你只要从外部系统拿到一个WSDL描述文件,它就能帮我们自动生成一套Apex

    查看详情
  • 24

    Test Web Service Callouts — WebServiceMock

    第 376 页

    今天我们来聊聊,在Apex里怎么测试那些调用外部Web服务的代码。想象一下,你写了一个Apex类,里面有个方法会去呼叫远方的Web服务拿数据。当你部署或打包这个类的时候,Salesforce要求至少有75%的代码被测试覆盖到,否则不让你上线。 但是测试有个麻烦:测试方法默认是不能真的去调用Web服务的,一跑就会失败。那怎么验证这些代码,又能达到覆盖率呢?这就是我们这节课要学的:WebServiceMock接口和Test.setMock方法。 简单说,WebServiceMock就像个替身演员。你可以写一个模拟类,实现WebServiceMock接口,让它假装是那个外部服务,按照你的要求返回假数据。这个模拟类可以写成public或global,最好再用@isTest注解标记一下,这样它就不计入你组织那6MB的代码大小限制,不占你宝贵的代码空间。 然后在测试方法里,你用Test.setMock方法,告诉系统:“嘿,当接下来的代码要调用这个特定的WebService时,请使用我这个模拟替身。”这样测试就不会真去外部请求,而是拿回你预设的响应,既保证了测试平稳通过,又覆盖了Web服务调用那部分代码。 举个例子,假设你有一个类叫WebServiceCallout,里面用SOAP或HTTP叫外部服务。你就创建一个实现WebServiceMock的替身类,在它的execute方法里写好要返回的假响应。然后在测试中,用Test.setMock(WebServiceMock.class, 替身实例)来绑定。之后你的测试就能顺畅跑完,代码覆盖率轻松达标。 记住这个组合:写模拟替身,用@isTest防占空间,再用Test.setMock注入。这样你的Web服务代码就能安全、可靠地通过测试了。 好,这节课就到这里,下次我们可以动手写一个例子试试看。

    查看详情
  • 25

    WebServiceMock — Implementation & Usage

    第 377 页

    同学们,我们接下来讲一个在测试里特别有用的技巧:如何模拟 Web 服务的调用,也就是“打桩”或者叫“Mock”。 大家知道,我们在写单元测试的时候,最怕的就是依赖外部系统,比如要调一个第三方的 Web 服务。如果测试的时候真的去调,不仅慢,还可能花钱,万一对方服务刚好挂了,你的测试也跟着失败,这就不合理了。所以我们希望测试的时候,能假装调了一次 Web 服务,然后直接返回一个我们预先准备好的假响应,这样测试就完全在我们自己的掌控之中。 那 Apex 里怎么做呢?很简单,就三步。 第一步,写一个类,让它实现 `WebServiceMock` 接口。这个接口只有一个方法,叫 `doInvoke`。你就在这个 `doInvoke` 方法里,把你想返回的假数据填进去。比如,不管外面传进来什么请求,你都给一个固定的成功响应。这就相当于你提前把答案写好,等着别人来问的时候直接给出去。 第二步,在你的测试方法里,调用 `Test.setMock`。这个方法需要两个参数。第一个参数是 `WebServiceMock.class`,注意这里就是把接口的类类型传进去,告诉平台“我要模拟的是 Web 服务调用这种类型”。第二个参数,就是你刚才写好的那个实现类的一个新实例,比如 `new MyWebServiceMock()`。这样一来,Apex 运行时就记住了:哦,接下来如果在这个测试里遇到调用 Web 服务的代码,不要真的去联网,而是去问这个 `MyWebServiceMock` 的实例要答案。 第三步,正常写你的测试逻辑。当你被测试的代码里,调用那些 salesforce 内置的 Web 服务方法时,因为我们现在处在测试上下文,Apex 运行时会自动拦截这个调用,转而调用你那个 Mock 类里的 `doInvoke` 方法,把假响应给回去。整个过程完全透明,你的业务代码根本不知道自己其实是在跟一个“替身”说话。 这里要特别注意一个知识点,跟托管包有关系。如果你的 Web 服务调用代码是打包在一个托管包里的,那么你的测试类和 Mock 类也必须放在同一个包里面,并且要有相同的命名空间。只有从同一个包里的测试方法去调用 `Test.setMock`,这种模拟才会生效。如果你试图在包外的测试里去模拟包内的 Web 服务调用,那是不行的。所以,如果是 ISV 在开发托管包,一定要记得在包内写好对应的测试和 Mock 类。 总结一下,今天的内容就是通过 `Test.setMock` 来模拟 Web 服务调用,让我们能写出又快、又稳、又不依赖外部的单元测试。你在 Mock 类里定好假响应,测试里用 `Test.setMock` 注册一下,测试上下文里的 Web 服务调用就全听你的指挥了。大家在实际项目中一定要把这个用起来,会极大提升你的测试质量。好了,这节课就到这儿,下回我们继续拆解更多好用的测试技巧。

    查看详情
  • 26

    Performing DML Operations and Mock Callouts

    第 378 页

    你知道吗,在写测试代码时,经常会遇到一个很烦人的限制: 如果你在一个事务里先做了数据操作,比如插入、更新记录,这些操作会让系统产生“未提交的工作”。接着如果你马上要发起一个 HTTP 调用,系统就会报错——因为它不允许在有未提交工作的情况下进行调用。 那怎么绕过这个限制呢? 答案就是,用好 Test.startTest 和 Test.stopTest 这两个老朋友,。 具体做法是: - 把你要,模拟的调用,(就是被测代码里的呼叫外部系统那部分)放在 `Test.startTest` 和 `Test.stopTest` 之间。 - 那些,会产生未提交工作的事务性操作,,必须写在 `Test.startTest` ,之前,,不能放在这个块里。 - 而且别忘了,`Test.setMock` 语句要写在 `Test.startTest` 的,前面,,顺序不能错。 为什么这样就能工作呢? 因为 `Test.startTest` 会把之前所有挂起的操作提交掉,并开启一个全新的测试上下文,这样后面的调用就没有未提交工作的阻碍了。 还有一点可以放心: 调用完成之后,如果再发生事务操作,是允许的,不需要做任何调整,系统不会管你。 简单总结就是:,先办事(DML),再开块(start/stop),模拟调用放中间,setMock 放最前。, 这样你的测试就能顺畅运行啦。

    查看详情
  • 27

    Asynchronous Apex and Mock Callouts

    第 379 页

    同学们,咱们今天来看个测试里的小陷阱,就是异步代码和接口调用混在一起的时候,容易出错。 先回忆一下,所谓异步Apex,就是那些不会马上执行完的操作,比如用@future注解的方法、批处理类、定时调度任务。这些异步操作因为不知道什么时候会跑完,所以Salesforce规定:在一个事务里,如果你已经做过DML操作,或者触发过异步调用,就不能再去做外部HTTP的调出了。形象点说,就像你出牌后必须等别人出完,才能再出下一张,不然系统会觉得不安全。 在测试类里,这个规则更严格。有时候我们需要测一个流程:先做异步调用,后面还要测某个callout。直接写的话,一定会出异常,因为测试运行是同步的,异步任务会卡住后面的callout。 那怎么破呢?Salesforce提供了一个专门用于测试的“时间控制”方法:Test.startTest() 和 Test.stopTest()。你可以把它们想象成一个测试专用的小世界。只要你把异步调用放在 startTest 和 stopTest 之间,系统就会“延迟”执行它,直到 stopTest 才真正跑起来。这样一来,在 stopTest 之前你还没真的触发异步,也就不会影响callout的准备;等stopTest执行异步的时候,你可以提前用 mock 把 callout 替换成假数据,完美避开真实调用。 所以,如果你测试代码里既有异步操作,又有外部调用,请记住两个保命方案: - 方案一:直接把异步调用那一整块,用 startTest/stopTest 包起来。这样异步在 stopTest 后才跑,不会挡路。 - 方案二:如果不得已,异步调用必须放在外面,那至少把会发起 callout 的那部分代码,用 startTest/stopTest 包起来,让mock生效的范围覆盖进去。 不这么做的话,测试一跑就会直接给你抛异常,提示“你有未提交的工作,不能做callout”。记住了吗?把异步活动关进 startTest 的小房间里,测试就乖多了。

    查看详情
  • 28

    Considerations Using WSDLs

    第 380 页

    好,我们来看这一页幻灯片。它主要提醒我们,用 WSDL 文件自动生成 Apex 代理类时,有几个重要的注意事项。 首先,在生成的类里,如果 WSDL 里定义了 SOAP 消息头,这些头部信息会自动变成类里的公共字段,也就是存根上的属性。你在代码里直接给这些字段赋值,调用时就会自动带在请求里,非常方便。 但是,有一个很容易踩的坑:假如对接的服务后续更改了 XML 命名空间,而 WSDL 里的命名空间还是旧的,那自动生成的类就不好使了。因为生成的类是把命名空间写死的。这时候,你就不能再用这个代理类去调了,必须手动构建完整的 HTTP 请求体,也就是自己拼出 SOAP 报文,然后用 Apex 的 HttpRequest 直接发一个 POST 请求到服务端点。虽然麻烦一点,但更灵活。 另外,在运行时,平台还会自动替我们做几项检查。比如,会防止因循环引用导致的无限递归,会检查远程站点

    查看详情
  • 29

    Considerations — Variable Name Rules

    第 381 页

    那我们今天来聊一个比较细节但特别实用的知识点,就是当我们要把一个 SDF 文件里的元素名称,转成 Apex 里能用的变量名时,系统是怎么自动处理的。 你看,SDF 文件里有些元素的命名,可能不太符合 Apex 变量名的规则,比如开头是数字、里面含有特殊符号。那这时候 Salesforce 会自动帮你做一些转换,让它变成一个合法的 Apex 变量名。 这个转换规则其实很贴心,我们一条一条来看。 首先,如果元素名称的第一个字符不是字母,那它会在最前面给你加一个“x”。比如你有一个元素叫 “123Data”,它开头是数字,那转换后的变量名就会变成 “x123Data”。 那如果反过来,是最后一个字符在 Apex 变量名里不允许用呢?系统就会在结尾补一个“x”。比如结尾是连字符或者其他不允许的符号,它就会给你加个“x”收尾。 接着,如果元素名称中间包含了一些 Apex 不允许的字符,那么这些字符都会被替换成下划线。这样就能保证名字的剩余部分都是合法的。 还有一个比较特殊的情况:要是元素名称里,刚好有连续两个不允许的字符挨在一起,那系统会怎么处理呢?如果是简单地把它们都变成下划线,就会变成两个下划线连在一起,这种双下划线在变量名里看起来很奇怪,而且也不是很规范。所以为了避免出现双下划线,它会把第一个不允许的字符替换成下划线,而第二个替换成 “x”。这样一来,就不会有连续的 __ 出现了。 最后还有一个要注意的点,就是如果经过自动转换之后,不同的元素得到了完全一样的变量名,那系统就没法区分了。这种情况下,就需要我们手动去修改其中一个,让它们变得不一样。 所以总结一下,就是在自动生成 Apex 变量名时,开头非字母加 “x”,结尾不允许的字符加 “x”,中间不允许的字符变下划线,连续两个不允许的字符分别变成下划线和 “x”,重名了还要手动调整。这些规则记住了,以后处理 SDF 映射就轻松多了。

    查看详情
  • 30

    Invoking HTTP Callouts

    第 382 页

    同学们,我们接着来看一个新的话题——,HTTP标注,,也就是我们常说的HTTP Callout。 那么,什么是HTTP标注呢?简单来说,就是让我们的Apex代码能够主动向外部系统发送请求,并接收响应。比如你要从Salesforce里调用一个外部的天气接口查询天气,或者调用一个支付服务,这些都要用到HTTP Callout。 Apex为我们提供了一套非常方便的内置类,专门用来处理这些HTTP服务、创建HTTP请求。常见的请求方式,比如,GET,、,POST,、,PUT,,甚至,DELETE,,这些都可以直接用这些内置类来实现。而且,这些类不仅支持现在非常流行的,REST风格的服务,,也能让你集成,基于SOAP的Web服务,。 说到SOAP,我之前讲过,我们可以通过从WSDL文件自动生成Apex代码的方式来集成SOAP服务,那样做很省事,框架都帮你搭好了。但是如果你选择直接使用HTTP类来发SOAP消息,就等于不走自动生成的捷径,而是自己手动构造请求的XML内容、解析响应的XML。这样做的话,你需要承担更多的责任,比如你得自己把那个“肥皂消息”——呃,其实是,SOAP消息,,就是那个信封格式的XML——给构建出来。当然,好处是你可以更加灵活地控制细节。 所以,记住啦:HTTP类给了我们一把通用的钥匙,既可以开REST这扇门,也可以开SOAP这扇门。当我们用它来开SOAP门的时候,就意味着我们要自己动手处理消息的构造细节,而不是依赖自动生成的代码。 好,这就是HTTP标注的基本介绍,是不是很好理解?我们休息一下,接下来再看看代码怎么写。

    查看详情
  • 31

    HTTP Classes Overview

    第 383 页

    同学们,咱们今天来看看 Apex 里用于做 HTTP 调用的几个核心类。这些类其实就是 Salesforce 用来跟外部系统“打电话”的工具,比如你调用第三方 API、发个消息或者获取数据,都会用到它们。 第一个是 ,Http 类,,它类似于一个通话发起器,你用它来发送请求、接收响应。我们平时写代码时,会先创建一个 Http 对象,然后拿一个请求交给它去执行,它就会把远端服务器的响应带回来。 那请求本身怎么构造呢?这就用到 ,HttpRequest 类,。它就像你要寄出的一封信,你可以在这封信里指定很多东西:用什么方法发送,是取数据的 GET,还是提交表单的 POST,或者做部分更新的 PATCH、整体替换的 PUT;你还可以设置请求头,告诉对方你的身份或数据格式;甚至还能设定读取超时和连接超时,避免一直傻等;另外也能控制是否跟随重定向,以及在消息正文里放上你要传过去的具体内容,比如 JSON 或 XML 格式的数据。 当 Http 对象发送完请求,返回的就是一个 ,HttpResponse 类,的实例。这个响应就像你收到的回信,你可以从它里面读到状态码,比如 200 表示成功,404 表示没找到;也能拿到响应头,里面包含服务器类型、内容长度等信息;最重要的还是响应正文,里面很可能就是你真正需要的数据,比如一段 JSON 或者 XML 字符串。 那拿到正文里的 XML 或者 JSON 怎么办呢?别担心,Salesforce 给了我们配套的解析工具——XML 解析类和 JSON 解析类。你可以用它们把那些文本嗖地一下转成 Apex 里的对象,然后轻松地把数据取出来用。 好,总结一下:Http 类负责“发”,HttpRequest 负责“装请求”,HttpResponse 负责“装回应”,而 XML 和 JSON 工具类负责“拆包解析”。这一套配合起来,就能让 Salesforce 跟外面的世界畅通无阻地交流。大家记住这三个核心角色,后面的练习就会非常顺畅了。

    查看详情
  • 32

    HTTP Callout — GET Example

    第 384 页

    同学们,我们来一起看这个关于HTTP调用的示例。这个例子演示了怎么从Apex代码里向外部服务器发出一个HTTP GET请求。代码的大意是,你有一个方法叫`getCalloutResponseContents`,它接收一个`url`参数,然后在方法里面,会做这么几步:首先,实例化一个`Http`对象,然后创建一个`HttpRequest`对象,接着设置这个请求的端点为传入的URL,并把方法指定为GET。准备好之后,就用`Http`对象的`send`方法把请求发出去,最后从响应里拿到主体内容并返回。 这里要注意,这个调用是同步执行的。什么意思呢?就是说,当`send`方法一执行,代码就会停在这里等待,直到外部服务器返回响应,才会继续往下处理。这就像你打电话问别人一个问题,你必须等他回答完才能挂电话做别的事一样。 如果你不想让用户或者当前事务一直等着,有没有别的办法呢?有的。你可以把这个调用逻辑放到一个用`@future(callout=true)`注解标记的方法里,这样它就会以异步的方式运行。那样的话,代码把请求发出去之后,就不会原地等待,而是立刻继续执行后面的语句,Salesforce会在后台单独处理这次调用,等响应回来了再处理结果。这就相当于你发了一条信息过去,然后就去忙别的了,不用一直守着等回复。 希望这样讲,大家能分清同步调用和异步调用的区别,以及在这个例子里具体的实现步骤。

    查看详情
  • 33

    HTTP Callout — POST Example & Considerations

    第 385 页

    同学,我们接着来看这个Slide,它讲的是在Apex里怎么从Salesforce向外部服务器发一个HTTPS的请求,而且使用的是JSON格式的数据。 你可以想象,Salesforce就像我们的大本营,它需要给外面的某个服务打个电话,说:“嘿,我这里有些数据,用JSON格式传给你,你帮我处理一下。”那怎么打这个电话呢?在代码里,我们就要按这几步来做: 首先,我们得创建一个专门负责打电话的“对象”,也就是实例化一个新的`Http`对象。有了这个对象,我们就可以开始构造我们的“请求”了——也就是新建一个`HttpRequest`,然后告诉它:我要打的这个电话的目标地址是什么(指定端点),以及这次通话的方式是“Post”,意思是我们要把数据主动发给对方。 接下来,很重要的一点,因为我们要发送的是JSON数据,所以我们要在请求的“信头”里写明:`Content-Type`是`application/json`,这样对方收到后就知道该怎么读我们给的内容了。然后,我们把真正的JSON内容放到请求的“躯干”里,也就是设置请求主体。 准备好了之后,就拨打这个电话——发送请求,对方收到后会给我们一个回复,我们把回复的“躯干”部分取出来,这就是响应主体,也就是外部服务器回传给我们的结果。 不过,你的代码要能顺利拨通这个电话,有一些非常重要的注意事项,Slide里也强调了: 第一,,你必须把要连接的远程站点,提前添加到Salesforce里批准的远程站点列表中。, 这是安全策略,就像公司大门的门禁,只有被你登记过的外部地址,Salesforce才允许你去调用。 第二,,你可以把端点设置为一个命名凭据的URL。, 这是什么意思呢?就是如果你经常要用到同一个外部地址,而且还需要密码之类的身份验证,你可以把地址和认证信息打包成一个“命名凭据”,在代码里直接引用它,这样更安全也更方便维护。 另外,Slide里还提到了一个有点反直觉的细节:,如果请求主体有内容,但你设置的方法却是GET,这时候Salesforce会实际执行一个Post请求。, 这算是一个隐含的规则,你要记住,别在GET请求里塞了数据还指望它按GET去工作。 最后,还有一个执行环境上的限制:,如果你当前存在未提交的那些事务——比如来自TLR操作(应该是触发器里的异步操作)、可调度的作业、批处理或者未来方法中的未决事务,这时候直接调用外部服务会被阻止。, 这是因为Salesforce为了防止对外部服务的调用被无限期挂起,要求调用必须在没有未提交工作的情况下进行。所以,你要记得检查代码逻辑,确保发出的呼叫是在干净的事务状态中进行的。 这样理解下来,整个流程和约束是不是就清晰多了?我们只要按步骤写好请求,配好远程站点,再注意好这几个坑,就能安全地让Salesforce和外部系统对话啦。

    查看详情
  • 34

    Testing HTTP Callouts — Overview

    第 386 页

    同学们,今天我们来讲一个Apex开发中很重要的知识点——测试覆盖,特别是如何处理HTTP调用测试。 大家知道,我们在部署或打包Apex代码到生产环境之前,Salesforce要求至少75%的代码被测试覆盖。这意味着,你写的方法、逻辑,几乎都要有对应的测试代码跑一遍,保证它们没问题。 但是在写测试的时候,有个常见的坑:如果你用到了HTTP请求,比如调用外部API,默认的测试方法是不允许真正发出网络请求的。因为测试环境是隔离的,不能联网。如果你直接在测试里写HTTP callout,它会失败,甚至影响你的覆盖率。 怎么办呢?Salesforce给我们提供了 “模拟调用” 的方法,专业术语叫 “Mock”。就是用一个假的响应来代替真实的网络返回,让测试能顺利跑完。 你只需要在测试方法里调用一个关键方法:`Test.setMock`,告诉系统:“嘿,遇到HTTP请求时,别真去联网,用我给你的假数据就好”。 那么,这个假数据怎么提供呢?有两种简单的方式。 第一种,是实现一个叫 `HttpCalloutMock` 的接口。你单独写一个Apex类,在里面定义当收到某个请求时,返回什么响应。这种方式很灵活,可以自定义状态码、响应体、头部信息等等,适合需要精细控制的情况。 第二种,是用静态资源配合两个现成的类:`StaticResourceCalloutMock` 或 `MultiStaticResourceCalloutMock`。你事先在静态资源里上传一个文件,比如一个JSON或XML文件,然后在测试代码里说:“遇到HTTP callout,就用这个静态资源里的内容作为响应”。很简单,不用额外写太多代码。`MultiStaticResourceCalloutMock`则是可以根据不同的请求URL返回不同静态资源内容,一个测试里模拟多个接口。 最后记住一个重要的测试技巧:如果你需要在一段测试代码中间才开始启用callout的模拟,或者想精确控制模拟生效的时机,要用到 `Test.startTest()` 和 `Test.stopTest()` 这对方法。它们把测试代码分成两个阶段,只有在这之间的代码会受到getMock设置的影响。这样做能让你更精准地测试异步流程或复杂逻辑。 总结一下,保证高测试覆盖的同时,遇到HTTP callout不要慌,用 `Test.setMock` 模拟输出,要么写个Mock类,要么用静态资源,再配合 `startTest/stopTest`,你的测试就能安全、高效地通过了。 这就是今天的内容,大家消化一下,有问题随时问。

    查看详情
  • 35

    HttpCalloutMock Interface Implementation

    第 387 页

    同学们,我们来看这一页内容。它在讲测试的时候,怎么模拟外部接口的调用,也就是 HttpCalloutMock 接口。 简单说,以后你在测试里,不能再真去连外网发请求了。那样不仅慢、不稳定,可能还会花真钱,或者不小心修改了外部数据。所以 Salesforce 提供了一个“假接口”的机制。我们只要写一个类,实现一个叫 HttpCalloutMock 的接口,在类里面写好假的响应内容,测试的时候 Apex 就会自动调用这个假响应,根本不会往外真的发请求。 具体怎么做呢? 第一步,创建一个类,这个类需要实现 HttpCalloutMock 接口,里面要重写一个 respond 方法。在这个方法里,你返回一个 HttpResponse 对象,把状态码、响应体、头信息都设好——这就是你希望外部系统“假装”返回给你的内容。 这个类可以是 public 或者 global 的,都可以。但最好加上 @isTest 注解。这样 Salesforce 就知道,这个类只用在测试里,不会被算进正式代码的 6MB 大小限制里,能帮你省下宝贵的代码空间。 写好这个假响应类之后,在测试方法里,你要在真正执行被测代码之前,先调用 Test.setMock 方法,告诉 Salesforce:“哎,等一下如果有 HTTP 请求,就用我这个假类来响应。” 其中第一个参数是 HttpCalloutMock.class,第二个参数是你刚刚写的那个假响应类的实例。 做完这一步之后,神奇的事情就发生了——接着在你的测试方法里,只要业务代码里一执行 HTTP 调用,Apex 运行时就会拦截下来,不再去连真正的网络,而是直接把你预先写好的那个 HttpResponse 还给你。你的代码就像真的接到了外部系统回复一样,但实际上完全没有网络开销,稳定又快。 所以记住三个要点: 第一,写个类实现 HttpCalloutMock 接口,在 respond 方法里返回设定好的 HttpResponse。 第二,给这个类加上 @isTest,不占正式代码空间。 第三,在测试方法里用 Test.setMock 把这个假类绑上。这样所有 HTTP 调用就都被你“骗”过去啦。 这在日常开发里特别常用,尤其是在做集成测试的时候。你可以用这个方法模拟各种成功、失败、超时等不同的场景,让测试覆盖更全面。好,这一页就讲到这里。

    查看详情
  • 36

    HttpCalloutMock — Full Test Example

    第 388 页

    同学们,我们来看这一页。这一页讲的是什么呢?就是我们在写Apex测试的时候,怎么去模拟一个外部服务的HTTP响应。因为我们不能在测试里真的去调用外部系统,对吧?这样又慢,又不稳定,还消耗调用次数。所以Salesforce提供了一个接口,叫HttpCalloutMock。 你只需要写一个类,实现这个接口,然后重写里面的respond方法。在这个respond方法里,你可以做两件事:第一,你可以检查一下,这次发出的请求是不是你期望的——比如方法是不是GET,端点地址对不对,请求头带没带正确的信息——如果不符你期望,甚至可以立马失败。第二,就是制造一个假的HttpResponse。 怎么制造呢?很简单,你new一个HttpResponse对象,然后给它设置状态码200,设置Content-Type头,再把你要返回的JSON字符串塞到body里,最后把这个响应对象返回出去。这样,一个假的外部服务响应就做好了。 接下来在测试方法里,我们怎么用这个模拟呢?在你的测试代码里,调用真正的方法之前,先写一句:Test.setMock,第一个参数是HttpCalloutMock.class,第二个参数就是你刚写的那个模拟类的实例。这样一来,后续所有对外部的HTTP调用,都会被这个模拟拦截下来,返回你设置好的假响应。这样你的代码就以为真的收到了外部系统的回复,测试就可以顺畅跑下去了。 总结一下,就三步:实现接口写模拟,设置假响应,测试方法里用Test.setMock绑定起来。是不是很简单?好,这一页就到这,我们继续下一部分。

    查看详情
  • 37

    HttpCalloutMock — Full Test Example (cont.)

    第 389 页

    同学们,我们来看这张幻灯片讲的重点,它其实是关于我们怎么测试对外部服务的调用——也就是在Apex里做HTTP Callout的测试。 假设你写了一个类叫CalloutClass,里面有个方法叫 getInfoFromExternalService,这个方法负责真正去调用外部的、比如第三方的天气接口或者支付接口。但是在测试的时候,我们不能真的去连外网发请求,因为那样测试会变慢、不稳定,而且Salesforce也不允许在测试里做真实的callout。那怎么办呢?我们就需要“模拟”这个外部服务。 这里的关键就是在测试类里使用 Test.setMock。在调用 getInfoFromExternalService 之前,我们先调用 Test.setMock,告诉Salesforce:接下来的callout不要真发出去,而是用我自己写的一个模拟响应来代替。这个模拟响应其实是一个实现了 HttpCalloutMock 接口的类,我们经常叫它“Mock类”。你可以把模拟想象成一个假的收件箱——当你的代码试图向外发请求时,Salesforce直接把这个假收件箱里的响应丢给你,让你以为真的从外部拿到了数据。 设置完模拟之后,测试类就可以放心地调用 getInfoFromExternalService 了。这个方法以为自己发了个请求,但实际上它拿到的是我们在模拟里设置好的响应。这时候,我们就需要去验证一下返回的结果,确保是模拟里塞进去的那个响应,而不是系统编造的别的什么东西。 具体验证什么呢?幻灯片上说了三个点:检查 Content-Type 头、检查响应正文、以及状态码。比如你的模拟响应里设定了状态码200,正文是 “success”,Content-Type 是 “application/json”,那你的测试类就得断言收到的响应状态码也是200,正文完全相同,头信息也匹配。这样,我们既保证了模拟本身工作正常,又能让测试覆盖到callout那部分代码,满足部署要求的代码覆盖率。 所以简单总结一下流程:一个方法专门负责真正的HTTP Callout;另一个测试类里,先设好模拟的假响应,再调那个方法,最后对拿到的响应做断言,验证头、正文、状态码。这样一圈走下来,我们就既有信心的把代码部署上去,又不会在测试时受外部服务的限制。 大家在练习的时候,可以试着给不同的外部接口写模拟,多感受一下这个模式。好了,这张幻灯片的核心就是这些,有任何疑问随时提出来。

    查看详情
  • 38

    Testing HTTP Callouts — StaticResourceCalloutMock

    第 390 页

    同学们,今天我们来看一个让HTTP调用测试变得特别简单的工具,叫做 StaticResourceCalloutMock。 以前,我们要在测试里模拟外部服务的响应,得自己写一个类去实现 HttpCalloutMock 接口,挺麻烦的。现在 Apex 内置了这个 StaticResourceCalloutMock 类,就不用再费劲写那么多代码了。它怎么用呢?其实就是提前把要返回的响应内容,放到一个静态资源文件里,然后在测试类里告诉系统:“嘿,碰到callout的时候,就拿这个静态资源里的东西当作响应。” 具体步骤很容易:第一步,你先去 Salesforce 静态资源设置里,上传一个文本文件,文件内容就是你想要的响应正文,可以是 JSON 字符串、XML,或者任意字符串,只要和你后面指定的内容类型对得上就行。比如你设了内容类型是 application/json,那这个文件里就得是合法的 JSON 数据。 第二步,在测试方法里,创建 StaticResourceCalloutMock 的一个实例。然后设置几个属性:用 setStaticResource 指定你用哪个静态资源的名字,用 setStatusCode 设定返回的状态码,像 200 成功、404 找不到之类的,再用 setHeader 或者 setContentType 来设定 Content-Type 头,保证跟静态资源的内容匹配。 最后,别忘了调用 Test.setMock 方法,把刚才建好的 mock 对象和 HttpCallout.class 关联起来。这样,当被测试的代码发起 HTTP 请求时,就不会真的去联网,而是直接收到你在静态资源里准备好的响应。 简单总结一下:准备一个静态资源文件 → 创建 StaticResourceCalloutMock 对象 → 配好资源名、状态码、内容类型 → 用 Test.setMock 挂上,齐活。这样写测试又快又干净,还不依赖外部网络,赶紧试试看吧。

    查看详情
  • 39

    Testing HTTP Callouts — MultiStaticResourceCalloutMock

    第 391 页

    我们来聊聊 Apex 测试里一个很实用的小工具——,MultiStaticResourceCalloutMock, 类。 你之前可能已经听说过,测试的时候,我们不能真的去调用外部系统,否则测试会失败。所以 Apex 提供了模拟(mock)的方式,让测试假装得到了外部系统的回应。 那这个 MultiStaticResourceCalloutMock 呢,它就是专门用来模拟这种“对外 HTTP 调用”的。它和它的“兄弟” StaticResourceCalloutMock 很像,但关键区别是:它允许你,同一个测试里,给不同的外部接口地址(也就是不同的端点),分别配上不同的假响应,。 怎么用呢?很简单,三步: 第一,,创建它的一个实例,。 第二,,通过 setStaticResource 方法,告诉它“哪个端点”该返回“哪个静态资源”里的内容,。这里的静态资源就是你在 Salesforce 里上传的文件,比如 JSON 或 XML 文件,里面写好了你想让外部系统返回的假数据。你还可以顺便设置一下状态码,比如 200 表示成功,或者 404 表示找不到,还有内容类型比如 application/json。 第三,,调用 Test.setMock,把这个模拟对象注册进去,。这样一来,当你的测试方法里对之前指定的那个端点发起 HTTP 请求时,Salesforce 就不会真的去访问外网,而是直接返回你配置好的那个静态资源里的内容。 就这么简单。它特别适合你需要模拟好几个不同的外部服务,或者同一个外部服务的不同接口,每个接口返回不一样的数据的情况。这样你的代码逻辑就可以在测试里完整跑通,又不会真的去调外部接口,测试既快又稳定。 记住,核心是:,用静态资源文件存放响应内容,然后按端点绑定模拟响应,。这样,你就可以灵活地控制不同 URL 的返回结果了。

    查看详情
  • 40

    HTTP Callouts — DML Before Mock Callouts

    第 392 页

    我们今天讲一个在 Apex 测试中很容易踩到的坑,就是“模拟调用”和“未提交工作”之间的小矛盾。大家记住一个简单的规则就行,我把原理也顺带讲一下。 你看,我们平时写测试类的时候,都会先做一些数据准备,比如插入一条客户记录、一个订单,这些操作在测试里都是被 Test Level Rollback 保护的,也就是说这些数据其实并没有真的写到数据库里,而是处在一种“待提交”的状态。这本身是好事,测试完自动回滚,不污染数据。 但是问题来了,如果你在测试里要模拟一个 HTTP 请求,比如调用外部 API,系统就特别严格:它不允许在还有未提交工作的情况下进行这个调用。因为模拟调用本质上是模拟一次出去的网络请求,如果这时候还有一堆没真正存进去的数据,系统怕出问题,就直接报错了。 所以解决办法很简单,就是让我们把数据准备和模拟调用分到不同的“执行区段”里去。具体怎么做呢? ,第一步,,所有需要插入数据的操作,都写在 `Test.startTest()` 之前。 比如你插入客户、插入业务记录,这些全都放前面。 ,第二步,,然后写 `Test.startTest();`。 ,第三步,,在 `startTest` 和 `stopTest` 之间,先通过 `Test.setMock(...)` 设置你要模拟的接口响应,然后写那段会触发调用的代码。注意,`Test.startTest()` 必须写在 `Test.setMock` 之前。 ,第四步,,最后 `Test.stopTest();`。 这样一来,`Test.startTest()` 就像一条分界线,它会让之前做的数据准备工作绑定成一个独立的已提交上下文,不再有未提交工作的尾巴。然后你在这个干净的环境里去模拟调用,就不会报错了。 另外强调一点:,数据准备的 DML 操作本身,绝对不要放到 `Test.startTest()` 和 `Test.stopTest()` 这个块里面,,不然跟直接写在模拟调用后面一样,还是会出问题。 这句话我简单总结一下,就是: ,“准备数据放前面,模拟调用放中间,mock 声明在 start 后,stop 之前全跑完。”, 不管是哪种模拟实现——`HttpCalloutMock` 接口、`StaticResourceCalloutMock` 还是 `MultiStaticResourceCalloutMock`,这个规则都一样适用。 你就记住这个顺序,测试就不会莫名其妙报“未提交工作”的错误了。

    查看详情
  • 41

    HTTP — Asynchronous Apex and Mock Callouts

    第 393 页

    同学们,今天我们来聊一个测试中很常见的“坑”,以及怎么轻松绕过它。简单来说,当你在代码里做了异步操作,比如调用未来方法、批处理,或者定时任务,这些操作内部可能会“卡住”你后面想做的外部调用。 为什么会这样?因为异步 Apex 会把一些还没提交的数据库工作暂时挂起,在这个事务期间,Salesforce 就不让你再做新的 HTTP 调用(也就是 callout)了。这就好比你正在写一封信,还没寄出去,就不让你同时打电话,怕你搞混了。 那在测试代码里怎么办?我们有一个特别好用的工具:Test.startTest 和 Test.stopTest。只要把异步操作包在这两个方法中间,测试系统就会帮你把这些异步工作暂时“扣住”,等到 stopTest 的时候再统一执行。这样一来,你就可以在 stopTest 之后,安安心心地做模拟的 callout,完全不用担心被阻塞。 如果你没有用 startTest 和 stopTest 包住异步调用,那你就得动一下脑:要么把 callout 也放进 startTest/stopTest 里面,要么把 callout 放在外面,但也要符合测试的规则。不过最简单、最推荐的做法,还是把异步操作用 startTest 和 stopTest 包起来,然后模拟的 callout 放在 stopTest 之后去执行,因为它会等到异步处理完毕后触发。 你只需要记住一句话:异步卡呼叫,测试用 start/stop 包,呼叫放后面,模拟轻松搞。 这样,以后写测试的时候就能流畅地处理异步和 callout 混合的场景了。有什么问题,随时问我。

    查看详情
  • 42

    Using Certificates

    第 394 页

    同学们,我们来看看这个幻灯片里提到的,关于证书的使用。当我们需要做到双向 SSL 身份验证的时候,证书就非常重要了。 你可以想象一下,平时我们访问一个安全的网站,通常只是服务器出示证书,我们来验证它是不是真的。但在双向 SSL 里,服务器也要反过来验证我们的身份。这就像不仅你要看对方的工牌,对方也要看你的工牌,双方都确认没有问题。 那 Salesforce 想调用外部服务,怎么证明“我就是我”呢?就需要发送一个证书给对方。这个证书可以是在 Salesforce 里直接生成的,也可以是由权威的证书颁发机构,也就是 CA 签发的。 你把这份证书交给目标服务,对方会把它放进自己的“信任仓库”——也就是它用来验证请求的密钥库里。以后,每当 Salesforce 带着这个证书发起请求,对方就能拿出这张事先存好的“电子工牌”进行比对,确认请求真的是来自你,而不是被人冒充。 这样做就大大增强了安全性,避免未经授权的访问。简单来说,发送证书,就是在双向认证当中,让接收方能可靠地验明我们的身份。 好了,这一页的内容就讲到这里。

    查看详情
  • 43

    Certificates — Overview & Generation

    第 395 页

    同学们,今天我们来看一个既重要又容易让人头疼的概念:双向SSL身份验证。别被名字吓到,其实它就像两个人见面要先互相看身份证一样,客户端和服务器彼此都要验证对方的身份。 那在Salesforce里,怎么来启用双向SSL呢?有几个关键步骤,我慢慢说给你听。 首先,你需要一个证书。这个证书就像是你Salesforce的身份证。你可以直接在Salesforce里生成一张自签名证书,也就是自己给自己签发的,速度快,适合测试或者内部系统。但如果是正式生产环境,和外部合作伙伴对接,最好还是去正规的证书颁发机构申请一个他们签发的证书,对方更认可。 有了证书之后,第二步,就要把这个身份证跟你的代码绑在一起。如果你用的是早期的SOAP服务,调用时可以通过一个叫clientCertName_x的变量来指定证书。如果你用现在的HTTP请求去调用外部API,那就用setClientCertificateName这个方法把证书的名字传进去。这样你的代码出去敲门的时候,就会带着这张身份证了。 第三步非常关键,如果你是连接一个第三方系统,而且你用的是自己签发的自签名证书,对方可不认识你。怎么办?你得把你的证书分享给对方,让他们把这张“身份证”添加到他们的信任关系、或者叫密钥库里。反过来也一样,如果对方是自签名证书,它们也得给我们一份,我们也要把它装进来,后面会说到。 第四步,要配置远程站点设置。在Salesforce里,你要调用外部的网址,得先在“远程站点设置”里把那个地址加进去,否则网络策略会拦住你的请求。不过这里有个小技巧,如果你用命名凭据(Named Credential)的话,就可以省去这一步了,因为命名凭据已经帮你做好了认证和端点管理的整合,更加方便和安全。 最后,还有一个自动完成的好处:当你保存证书成功后,Salesforce会自动帮你生成对应的密钥。这省得你再去手工折腾密钥生成的事情,系统全给你办妥了。 这样梳理下来,是不是清晰多了?简单总结就是:先搞证书,再绑定代码,需要的话交换证书,配上远程站点或者用命名凭据,然后钥匙自动配好。靠着这几步,就能实现安全可靠的双向SSL啦。下节课我们会实际操作一下,今天先理解这个流程。

    查看详情
  • 44

    Certificates with SOAP Services

    第 396 页

    嘿,同学,咱们今天聊一个特别实用的功能,叫“双向身份验证”。你看,平时我们调用外部系统的接口,对方可能要验明我们的身份,对吧?但有些时候,对方不光要验我们,我们也得反过来验它——这就是双向验证,互相出示“身份证”。 那么在 Salesforce 里,怎么让咱们的代码能支持这种双向身份验证呢?其实步骤不难,我一步步说给你听。 首先,咱们得准备一张“数字身份证”,也就是证书。你可以在 Salesforce 的设置里直接生成一张,或者如果你在其他地方已经有现成的密钥对,也可以导入进来。这张证书就存放在“证书和密钥管理”那个页面里,你给它起个唯一的名字,后面会用到。 接下来,咱们要跟第三方的 Web 服务打交道,通常对方会给你一个描述文件,叫 WSDL(其实就是告诉你它的服务长什么样、该怎么调用)。你把这个 WSDL 文件下载下来,然后在 Salesforce 里用“从 WSDL 生成 Apex 类”这个功能,点几下,系统就会自动帮你生成一套 Apex 代码。这套代码里呢,会有一个叫“stub”(桩)的类,它就像一个代理,帮你封装了所有跟对方通信的细节。 最关键的一步来了:在你生成的这个 stub 类里,会有一个变量,名字差不多是 `clientCertName_x`(可能稍微有点变体,但核心就是它)。你需要给这个变量赋一个字符串值,这个值必须跟你之前在“证书和密钥管理”页面上给证书起的唯一名称一模一样。这样,Salesforce 就知道,哦,当要通过这个 stub 去跟外部系统握手时,要用这张指定的证书来证明自己的身份。 总结一下就是:准备证书 → 拿 WSDL 生成代码 → 在代码里把证书名字填上 —— 双向认证就搞定了。是不是比想象中简单?以后遇到需要双向认证的场景,你就按这个套路来,准没问题。

    查看详情
  • 45

    Certificates with HTTP Requests

    第 397 页

    我们来看一下在 Salesforce 中如何使用证书来进行双向身份验证。 简单来说,当你需要调用一个外部系统,而这个外部系统要求双向 SSL,也就是不仅它要验证你的身份,还要你出示一个数字证书时,就需要用到这里讲的方法。 首先,你需要在 Salesforce 里生成或上传一个证书,并且一定要记住这个证书的“唯一名称”(Unique Name),这个名称在后续写代码时会用到。 接下来,在 Apex 代码中,创建 HTTP 请求时,你会用到 HttpRequest 这个类。它提供了一个方法叫作 setClientCertificateName。你只需要把刚才记下来的证书唯一名称作为参数传入这个方法。 这样一来,当这个 HTTP 请求发出时,Salesforce 就会自动把对应的客户端证书一同发送出去,对方系统就可以用这个证书来验证你的身份了。 这个流程很简单,关键就是两步:先在设置里准备好证书,再在代码里用 setClientCertificateName 把它绑定到请求上。

    查看详情
  • 46

    Callout Limits and Limitations

    第 398 页

    我们接着往下看。现在要聊的是一个很实际的场景——当我们写的 Apex 代码需要向外面发送 HTTP 请求,或者去调用一个外部的 Web 服务时,代码会受到哪些限制。 大家可以把这些调用想象成“出站”操作,无论是去调 Salesforce 自家的 SOAP API,还是去调你们公司自己搭建的任何一个外部接口,这些都属于我们这里要讨论的范畴。 因为 Apex 要保障整个平台的安全和稳定,所以对这些外面的调用做了一些约束。提前了解清楚这些限制,能帮你在做集成的时候,少走很多弯路,代码也写得更稳。 那具体都有哪些限制呢?下面我们就一个一个来看。

    查看详情
  • 47

    Callout Limits

    第 399 页

    同学们,今天我们来聊聊Apex里对外部系统做HTTP调出的一些限制。这些限制虽然听起来挺多,但理解起来并不难,我一项一项给你说清楚。 首先,在一个Apex事务里,你最多可以做100次对外部的调用。也就是说,假设你写了一个触发器或者一个批处理作业,它一次运行中向不同的网址发了请求,总共不能超过100次。记住,这是整个事务的合计数。 第二点,如果你的组织是Developer Edition,就是那种免费开发者版本,那么有一个特殊限制:你最多只能创建20个并发的对外调用。什么叫并发?就是同时发起的请求。比如你一次发起30个请求,在Developer Edition里就会报错,最多只能20个同时出去。但如果你用的是正式的生产环境或沙盒,这个限制就不适用了,你想发几个并发都可以,只要不超其他限制。 接下来是超时时间。Apex默认每个调出等待时间是10秒,也就是服务器不响应就停止了。但你可以自定义这个时间,最短可以设成1毫秒,最长可以设成120,000毫秒,也就是120秒。你可以用这个方法灵活控制:比如某个服务特别慢,你给它设长一些;如果要求快速失败,就设短一些。 还有一点要注意,一个事务中所有调出的超时时间累加起来,不能超过120秒。举个例子,你发了3个请求,每个请求设了50秒的超时,那么加起来就是150秒,超过了120秒的限制,这就不行。所以在设计时,你要考虑所有调用的总等待时间。 最后还有一个比较体贴的设计:在计算长时间运行的请求限制时,HTTP超时等待的时间是不算在内的。也就是说,当你那些调用都在等服务器应答时,这个等待时间是会被“暂停计时的”。等超时一结束,计时器才会继续跑。这样就不会因为等外部服务而让事务被误判为慢事务了。 简单回顾一下: - 总共调用次数不超过100次; - 并发调用限制只在Developer Edition有,20个; - 每个调用可以自定义超时,默认10秒,最长120秒; - 所有调用的超时加起来不能超过120秒; - 而且等待超时的时间,不占慢事务的配额。 理解了这些,你在写集成外部系统的代码时就能心里有数了。有什么问题随时问,我们继续。

    查看详情
  • 48

    Callout Limits (cont.)

    第 400 页

    同学们,咱们今天来看一个在实际开发中很容易踩到的坑,就是在同一个事务里,什么时候不能进行HTTP调用,以及一些相关的注意点。 你可能在代码里先做了一些数据库操作、发邮件或者调用了异步方法,然后又想马上发一个HTTP请求出去,这时候Salesforce就会报错。规则其实很清楚:,当你的事务中还存在“挂起的操作”时,是不允许再发起外部调用的。, 那什么是挂起的操作呢?简单说,就是还没真正提交到数据库、或者还没结束的异步工作。比如: - 执行了DML语句(插入、更新、删除记录),但事务还没结束; - 调用了未来的方法(@future)、批处理作业; - 安排了计划Apex; - 或者发送了电子邮件。 这些都属于挂起的操作。如果你在它们之后紧接着写了一个HTTP callout,系统就会阻止你。 那如果想先做一些数据库改动,又能调用外部服务,怎么办呢?一个办法是在执行这些操作,之前,,先创建一个保存点(savepoint)。保存点能让你在后续出错时把数据回滚到这个地方,很多业务场景里会这么用。但注意哦,保存点本身并不能解除调用的限制,它只是帮你更好地控制事务——要解决限制,通常的做法是先做callout,拿到结果后再做DML。其实你可以反过来安排顺序:先完成HTTP调用,再去操作数据库。 另外还有一个测试时的小特例:在单元测试里,如果你用的是“模拟调用”,挂起的操作是可以在模拟调用之前发生的。因为模拟调用并不会真的去连外部服务器,所以系统就放宽了这个限制。这一点对咱们写测试类很有用。 最后再说一个跟HTTP调用超时有关的情况。当你的HTTP请求里添加了 `Expect: 100-Continue` 这个请求头,意思是告诉服务器:“先别急着发请求体,你确认能接收我再发。” 这种情况下,如果外部服务器没有及时返回 `HTTP/1.1 100 Continue` 这个确认响应,那请求就会超时。所以使用时一定要确保对方服务器支持这个机制,否则反而会让你的调用卡住。 好了,这页就是强调调用顺序的约束和几个容易疏忽的点。实际项目中只要记住:,事务里有DML或异步操作时,别在它们后面放callout,,早一点把调用完成就好。继续加油!

    查看详情
  • 49

    Apex Callouts in Read-Only Mode

    第 401 页

    同学们,今天咱们来聊聊 Salesforce 里一个非常容易踩坑的细节: ,在只读模式下调用外部服务,。 你看啊,当 Salesforce 组织进入只读模式的时候,系统其实并不会阻止 Apex 向外部服务发请求。这个 callout 会正常执行,你也能正常收到响应,比如接收到一个第三方系统的状态更新。 问题就出在得到响应之后——咱们通常会在同一个事务里,紧接着执行一些写操作,像更新记录、创建日志等等。但因为这时候 Salesforce 正处于,只读模式,,所有的 DML 写操作都会被系统直接拦下来,报错回滚。 这就造成了典型的不一致:,外部调用做完了,响应也拿到了,但后续保存结果的步骤却失败了,——程序流程一下就断了,轻则数据对不上,重则业务流程整个卡住。 那怎么避免这种不正确的程序行为呢? 很简单,咱们在对外部服务发起调用之前,可以先检查一下当前是否处于只读模式。用到一个系统方法: `System.getApplicationReadWriteMode()` 它会返回一个枚举值,告诉我们当前是读写模式还是只读模式。 如果返回值等于 `ApplicationReadWriteMode.READ_ONLY`,那说明当前环境不允许写操作,咱们就应该,直接跳过这次 callout,,等维护结束之后再说。这样就不会出现“调成功了却存不上”的尴尬局面,整个程序流程就安全了。 你可能会问,好端端的怎么突然就只读模式了? 其实 Salesforce 在计划内的维护活动期间就会自动切到只读模式,比如,计划的站点切换,、,实例刷新,这类操作。这些维护通常发生在凌晨或者提前通知的窗口,咱们应用里加上这个检查,就能在这些时段自动保护业务逻辑,避免莫名其妙的错误。 所以记住啦: 在 Apex 里做外部 callout 时,花一行代码调用 `System.getApplicationReadWriteMode()`,如果读到的状态是只读,就礼貌地绕过这次调用,不要硬来。这样写出来的程序才足够健壮,不会因为维护窗口而“翻车”。 好,这点就讲完了,大家在实际开发的时候可以对照着试一下,有问题随时讨论。

    查看详情
  • 50

    Setting Callout Timeouts

    第 402 页

    那我们现在来看一下,在 Apex 里如何控制对外调用的超时时间,这个在集成里非常实用。 想象一下,我们的代码要去调用一个外部的 Web 服务或者 HTTP 接口,如果对方响应很慢,我们总不能一直等下去对吧?所以 Salesforce 允许我们自定义这个等待的最长时间,也就是超时。 对于 ,Web 服务调用,,也就是那种用 WSDL 生成代理类的方式,你可以在代码里给 `timeout_x` 这个特殊变量赋一个值。注意哈,变量名后面要带一个下划线 x,叫 `timeout_x`,单位是毫秒。 比如你想让它最多等 5 秒,那就设成 5000。如果不设,默认就是 10 秒。 那对于 ,HTTP 调用,,也就是我们用 `HttpRequest` 对象去发请求的情况,要设置的就不是变量了,而是调用对象的 `setTimeout` 方法,传进去的也是毫秒数。 这两种方式都遵循一样的限制:最小值不能小于 1 毫秒,最大值不能超过 120,000 毫秒,也就是 120 秒。 还有一点非常重要,一个 Apex 事务里,可能会调用好几次外部服务,对吧?所有调用的超时时间会,累加,起来。总的累积超时上限也是 120 秒。也就是说,如果你的代码在同一个事务里调了三次外部服务,每次设的超时加起来不能超过 120 秒,否则会报错。 所以我们在设计时就要心里有数,合理分配每个调用的超时,别让累积超时爆掉。 简单总结一下: - Web 服务调用:设 `timeout_x` 变量 - HTTP 调用:用 `setTimeout` 方法 - 单位都是毫秒,默认 10 秒,最小 1 毫秒,最大 120 秒 - 同一个事务里所有调用的超时时间累加,总上限也是 120 秒 好,这一小段就讲到这里,有什么不清楚的可以随时问我。

    查看详情
  • 51

    Make Long-Running Callouts with Continuations

    第 403 页

    好,同学们,咱们接下来看一个很实用的功能,叫 ,Continuations,,中文呢,可以理解成“续延”或者“回调延续”。用它来处理那些耗时比较长的对外部服务的调用,特别合适。 想象一下,你在一个 Visualforce 页面或者 Lightning 组件里,需要去调用外部的 Web 服务,比如查一个第三方的物流信息,或者做个信用检查。这种请求有时候网络延迟大,可能要好几秒甚至更久才能返回结果。如果咱们按普通的同步方式去调用,那用户的界面就会卡死在那里,体验非常糟糕。 所以 Apex 提供了 Continuations 这个机制。它本质上就是一种,异步回调,。你从页面上发起一个长时间运行的请求,这个请求会先被挂起,去后台慢慢执行,但,不会阻塞当前的线程,。等服务器那边的响应回来了,Apex 会自动调用你准备好的一个回调方法,把结果传进去。 你可以把这个回调方法看作是“延续”了原始请求的处理逻辑——所以叫 Continuation。响应回来了,咱们就在这个回调方法里接着处理,然后把结果展示到页面上。 这样用户在使用的时候,界面可以继续响应,比如显示一个加载动画,而不会“假死”。而且整个过程代码写起来很清晰:你发起请求,指定一个回调函数,然后该干嘛干嘛,响应到了自然会触发那个回调。 总结一下重点: - Continuations 用于,长时间运行的外部服务调用,。 - 它是从 ,Visualforce 页面,或 ,Lightning 组件, 发起的。 - 采用,异步回调,模式,响应通过你指定的回调方法返回。 - 这样就不会阻塞用户界面,体验流畅。 好,关于这个 Continuations 的引入和基本概念,咱们就聊到这里。接下来咱们会看具体的代码怎么实现,以及有哪些注意事项。

    查看详情
  • 52

    Continuations — Overview & Execution Flow

    第 404 页

    同学们,咱们今天来看一个非常实用的执行路径,它用到了Salesforce里的Continuation机制。你先在脑子里想象一个场景:一个呼叫中心里,有成千上万个坐席都在用同一个带按钮的Visualforce页面。按钮的名字可能就叫“同步收件箱”,一点它,页面就要去外部的Web服务拿数据。 在没有特殊处理的情况下,如果每个请求都老老实实等着外部服务返回,那并发请求数很快就爆了,用户也会觉得又慢又卡。而Continuation就是来漂亮地解决这个问题的。 咱们顺着执行路径走一遍。首先,用户在Visualforce页面上点击“同步收件箱”按钮,页面就把这个请求发给了应用服务器。应用服务器接到请求后,并不会自己傻傻地等着外部Web服务响应,而是把这个活儿转交给一个专门的“Continuation服务器”。交出去之后,应用服务器就解脱了,它可以马上把页面控制权还给浏览器,让请求线程迅速释放掉,不占着茅坑。 接着,Continuation服务器就替我们去调用外部的Web服务,等外部服务处理完,把数据返回来,Continuation服务器再把结果回传给应用服务器。应用服务器拿到数据后,重新刷新Visualforce页面,把最新的信息呈现给用户。 你看,这个过程对用户来说几乎是无感的,但背后巧妙地绕开了长时间占用线程的问题。正因为请求线程被快速释放,即使几千个坐席同时点“同步收件箱”,也完全不会超过Salesforce的并发请求限制。这就是Continuation带来的核心好处,让高并发的企业应用又稳又快。

    查看详情
  • 53

    Continuations — Visualforce Example

    第 405 页

    同学们,我们来看看这个示例里按钮的动作是怎么在后台实现的。想象一下,你正在用Visualforce页面点一个外卖,你按下“下单”按钮,其实不是直接让页面卡在那里干等,而是用一种更聪明的方式——叫做Continuation,来调度这个远程调用。 在Apex控制器的方法里,我们会先创建一个Continuation对象。你可以把它理解成一张“任务单”,上面写着两件重要的事:第一个是超时时间,比如最多等30秒,防止外部服务一直没反应;第二个是回调方法的名称,就是等数据回来之后,我们要让系统自动调用的那个方法名。 接着,我们把真正的HTTP请求,比如去查询外部订单系统的接口,挂到这张任务单上,然后把Continuation对象直接返回出去。这时候,Visualforce的请求就会暂时挂起,但用户界面不会完全冻住——页面会显示一个加载状态,让用户知道正在处理中。 当外部服务终于把响应数据送回来时,之前暂停的Visualforce请求就会自动恢复,并且触发我们指定的那个回调方法。页面就能拿到响应结果,然后刷新相应的部分,比如显示“下单成功”或者更新状态。 要注意啊,在做这一切之前,必须让Salesforce信任你要访问的外部站点。要么去设置里把远程站点的URL加到“授权的远程站点”列表中,要么更规范一点,使用命名凭据来定义这个安全的连接。这样Salesforce才允许发出请求。 整个过程就是这么个异步协作的模式,避免了请求超时,也让用户体验更流畅。好,这段先讲到这儿,有什么问题吗?

    查看详情
  • 54

    Continuations — Callback Method

    第 406 页

    同学们,我们接着来看这一页幻灯片的内容,它讲的是在异步调用中,外部服务完成后,回调方法是怎么处理响应的。 当我们发起的外部服务请求全部完成以后,咱们之前写好的回调方法就会被调用。在这个回调方法里,最重要的一步,就是用 `Continuation.getResponse` 这个方法来拿到服务的返回结果。拿的时候,需要用到咱们在发起请求时存下来的那个唯一标签,通过这个标签来识别到底是哪个请求的结果,这样就不会搞混了。 然后,我们把拿到的数据,赋值给一个在 Visualforce 页面上已经定义好的变量,这个变量是用来在页面上显示结果的。设置完之后,方法最后要返回一个 `null`。这里返回 `null` 并不是没意义,它的作用是告诉系统:数据已经准备好了,请把原来的 Visualforce 页面重新渲染一遍。这样,用户就能在页面上看到最新的外部数据了。 这里还有一个非常重要的知识点:在一次延续调用里,我们最多可以创建三个同步请求。注意,这里说的“同步”是指这三个请求会并行发出,同时执行。但是,后续的 Visualforce 处理流程会暂时挂起,直到这三个外部服务全都返回结果了,才会恢复执行。这样就能大大提升整体的响应速度。 不过,大家一定要记住,这种一次发多个并行请求的功能,只能在 Visualforce 页面的上下文中使用。如果你是在 Visualforce 页面以外的地方,比如直接在开发者控制台里用匿名窗口去调用这些动作方法,那是没办法创建这种延续回调的。换句话说,整个异步并行机制,是专门为 Visualforce 页面设计的。 好了,关于回调方法和并行调用这部分,就讲到这里。大家有问题可以随时提出来。

    查看详情
  • 55

    Continuations — Process: Action Method & Callback

    第 407 页

    同学们好,咱们这节课呢,来说说一个很实用的功能——在Visualforce页面里,怎么去调用外部系统,也就是有时候文档里提到的“收件箱调用”。我们要实现这种异步、不卡页面的操作,就必须用到Salesforce里的一个专门的对象,叫作 ,Continuation,。 好,我们先理清一下思路:你想要在页面上点一个按钮,然后它在后台静悄悄地给外部系统发个请求,拿到结果再刷新页面,而不让用户干等着。这整个过程就得靠 Continuation 来帮忙。 具体做法是这样的: 第一步,你要在自己的 action 方法里,创建一个 Continuation 实例,。创建的时候,必须指定两样东西:一个是,超时值,,就是等多少秒还没回应就算超时;另一个是,回调方法的名字,,就是当外部系统把数据返回后,系统要调用的那个方法,你用一个字符串告诉它就行。 第二步,我们要把具体的 HTTP 请求跟这个 Continuation 关联起来。你得先 new 一个 `HttpRequest` 对象,把接口地址、请求方式、参数什么的都配置好,然后调用 Continuation 对象上的 `addHttpRequest` 方法,把这请求添加进去。这样,Continuation 才知道它要去调哪个服务。 第三步,也是特别要记住的一点:,action 方法必须返回这个 Continuation 对象,。你一返回,Visualforce 就明白现在要发一个异步请求了,页面会进入等待状态,不会卡死。 当外部系统终于把结果送回来,系统就会自动触发前面指定的回调方法。这个回调方法,不接受任何参数,,即使你的页面用了标准控制器也一样。在回调方法里,你就可以处理返回的数据了。 那处理完了之后呢,回调

    查看详情
  • 56

    Testing Asynchronous Callouts

    第 408 页

    好,我们来说说怎么测试那些用了“延续”(Continuation)的控制器。 在Apex里,延续是用来做长时间异步调用的,比如对外部服务的HTTP请求。但在测试里,你不能真的去调用外部服务,因为Apex测试不支持真正的网络调用。 所以,我们就需要模拟这个过程。你可以用两个关键的方法: 第一个是 `Test.setContinuationResponse`,用它来为某个延续对象设置一个假的响应,相当于你提前告诉系统:“等一下如果这个延续被执行,就返回我准备好的这个假数据。” 第二个是 `Test.invokeContinuationMethod`,它的作用是,在测试里手动触发那个延续的回调方法,就像真的收到了响应一样,让回调逻辑跑起来。 具体步骤很简单: 1. 在测试里,先调用你的控制器方法,拿到它返回的延续对象。 2. 验证这个延续的请求内容是不是你期望的,比如端点、方法、参数对不对。 3. 然后用 `Test.setContinuationResponse` 设置一个模拟的响应体。 4. 再用 `Test.invokeContinuationMethod` 执行回调。 5. 最后,验证控制器里的结果变量是不是和模拟的响应一致。 这样一来,你既满足了代码覆盖率的要求,又确保了异步回调逻辑是正确的,而且完全不用真的去访问外部系统。

    查看详情
  • 57

    Asynchronous Callout Limits

    第 409 页

    同学们,今天咱们来聊聊Salesforce Apex里一个挺重要的概念——,延续,,也就是Continuation。你可以把它想象成:当你的代码需要等一个外部服务慢慢响应的时候,不用在那儿傻等,而是先挂起,等响应回来了再接着跑。这种异步处理模式就叫“延续”。 但是呢,执行延续的时候,有一些专门的限制要记住,和我们平时写Apex的限制不太一样。咱们一条条来看。 --- ,第一,并行调用的数量最多3个。, 啥意思呢?就是在同一个延续里,你同时发起的异步请求不能超过3个。比如你要同时调三个外部API,可以;调第四个就不行了。这是为了控制并发,避免资源被占满。 ,第二,链接调用最多3个。, 链接调用就是,你收到第一次响应后,又在回调里马上发起第二个延续,第二个完了又发第三个……这种串起来的链,深度最多只能有3层。超过3个链接,平台就不干了。 ,第三,超时时间强制为120秒。, 你要注意,就算你在代码里给HttpRequest设了超时时间,或者用自动生成的“桩”(stub),Salesforce都会直接忽略你设的时间,统一用120秒作为上限。要是外部服务120秒还没响应,延续就会被终止,超时啦。所以别指望能等太久。 ,第四,队列状态大小最大80KB。, 延续在“暂停”等待时,需要保存一些状态数据,比如说你传进来的参数呀、一些变量的值呀。这些数据序列化后不能超过80KB,不然就存不下。 ,第五,HTTP响应大小最大1MB。, 哪怕外部服务返回给你一个很大的报文,只要超过1MB,延续就会报错。所以对接的外部服务最好能返回精简的数据。 ,第六,Post表单大小最大1MB。, 如果你用POST方式发送表单数据,body部分不能超过1MB。 ,第七,Post表单里的键(key)最多500个。, 表单里字段名太多也不行,键的数量限制在500个以内。这基本是防止提交的表单过于庞大。 --- 另外还有个小技巧:,如果你有一些变量不想被序列化到延续的状态里,可以用 `transient` 这个修饰符。, 加了 `transient`,这个变量就不会被保存在80KB的状态里,等延续恢复执行时,它的值会是null,需要重新获取或计算。这样能帮你节省那宝贵的80KB配额。 那等延续返回,请求恢复执行时,发生了什么变化呢? 这时候Salesforce会开启一个全新的Apex事务,之前的所有Apex和Visualforce限制都会被,重置,,就像全新的执行上下文一样。所以你在回调里写代码时,又有一整套新的限制额度可以用,但同时也要遵守这些新限制,不能“超支”。 咱们简单总结一下要点: - 并行不超过3个,链式调用不超过3层。 - 强制120秒超时,外部响应别超1MB。 - 状态保存最多80KB,考虑用`transient`瘦身。 - 表单POST大小和键的数量也都有限制。 - 回调里一切限制重新开始。 记住这些,写延续的时候心里就有数啦,能避免不少莫名其妙的错误。好了,这节课的内容就是这些,有什么问题咱们可以再讨论。

    查看详情
  • 58

    Controller State vs Visualforce View State

    第 410 页

    同学们,今天我们来看看一个很关键、但又经常被忽视的概念,那就是控制器状态和视图状态的区别。尤其是在异步操作里,比如用 Continuation 做长时间调用的时候,这个区别就更明显了。 咱们先打个比方:你可以把控制器状态想像成“操作台”上所有决策者的记忆,而视图状态则是整个“控制室”里所有设备的状态和它们的连线图。 具体来说,第一点,当你在一个页面流程中发起一个 Continuation 异步请求时,请求里面携带的控制器状态,并不是只有发起调用的那个控制器。它会序列化整个请求里涉及的所有控制器——包括控制器扩展,还有那些自定义组件、内部组件里绑定过的控制器。哪怕这个 Continuation 不是你亲手在那个扩展里写的,只要这个请求链路里出现了这些控制器,它们的关键状态都会被一起打包带走。所以,控制器状态是一个“团队记忆”,而不是个人的记忆。 第二点,视图状态比控制器状态要重得多。它不仅保存了每一个组件、每一个控制器属性的状态,还保存了整个页面的组件树结构——也就是哪个组件是父、哪个是子,它们是怎么嵌套在一起的。你可以理解成,控制器状态只是保存了大家脑子里记得的东西,而视图状态不但要记住这些,还画出了整个工位的分布图。 因为视图状态要存的东西多,所以它的体积上限也大一些,最大能到 170 KB。控制器状态相比之下就小得多,但也要特别注意,哪怕是在异步场景里,如果你在请求链路里无意中引用了很多笨重的控制器,它们的状态也会跟着序列化,拖慢性能。 简单总结一下,做 Continuation 的时候,控制器状态是“所有相关控制器的记忆合辑”,而视图状态是“完整的状态加结构全家桶”,上限能到 170 KB。理解这个区别,能帮你更好地优化页面性能,避免那些莫名其妙的状态丢失或者体积超限的问题。 好了,这节课就讲到这儿,大家结合手头的异步场景再体会一下,有什么疑问我们下节继续聊。

    查看详情
  • 59

    Making Multiple Asynchronous Callouts

    第 411 页

    同学你好呀,咱们接着看这个Slide,聊一聊在Visualforce页面里,怎么同时发起好几个长时间运行的服务调用。 你可能会遇到这种情况:页面上需要去查两个不同产品的库存,或者不同系统的数据。以前,你可能一次发出一个请求,等它回来了再发下一个,那页面就卡着,用户得干等,体验不好。 这时候,Salesforce给我们提供了一个叫,Continuation,的机制。用这个Continuation,你可以一次把多个独立的请求打包,让它们同时跑起来。但有个小限制——,同一个Continuation实例里,最多只能加三个请求,。就像一个小推车,一次最多装三件货,装多了它不干。 比如,你要查产品A和产品B的库存,完全可以在一个Continuation里添加这两个请求。它们会,并行运行,,各跑各的,谁也不用等谁。这时候,当前的Visualforce请求就会被,挂起,,页面不会僵死,只是暂时在后台等着。只有等所有请求的响应都回来了,这个Visualforce进程才会,恢复,,继续往下走,把拿到的数据渲染给用户看。 那问题来了,请求多了,我怎么知道哪个响应对应哪个请求呢?别担心,你每加一个请求的时候,都得给它绑一个,唯一的标签,,就像给每个包裹上贴个条码。然后在回调方法里,你就用这个标签,把对应的响应数据取出来。比如,你可以设标签叫`'productA'`、`'productB'`,回调里一调`.getResponse('productA')`就拿到了,很清楚。 简单总结一下这个Slide的重点: - 一个Continuation最多并行,3个,callout。 - 它们同时发出,,挂起,页面,等全回来了再,恢复,。 - 每个请求用,唯一标签,区分,方便在回调里取响应。 这样就能让页面更高效,用户也不用傻等啦。咱们休息一下,有问题随时提。

    查看详情
  • 60

    Chaining Asynchronous Callouts

    第 412 页

    同学们,今天我们聊一个关于异步调用的小技巧——怎样把多个对外部的服务请求串起来,让它们按顺序执行。 有时候,后面的请求必须用前面返回的结果才能继续。比如,你查一个产品的保修状态,系统说已经过期了,那你可能马上想接着去查能不能续保。这时,你就需要把这两个调用连成一串:必须等第一个保修查询返回了,拿到结果后,再发起第二个续保查询。这个过程就叫“链接调用”,在Apex里,我们用的是 Continuation 类来管理这种链。 一个关键的规则是:你最多只能把三个callout这样链起来。流程是这样的:你发起第一个调用,当它完成时,Apex会回调你指定的方法。在这个回调方法里,如果你还需要做下一个调用,就返回一个新的 Continuation 对象;如果任务结束了,不需要再调用,就直接返回 null。返回 null 就代表这条链结束了。 举个简单的例子,想象一下:先查保修,拿到一个过期的标记,然后决定是否去查续保。代码逻辑里,第一个回调方法内,判断如果过期,就用响应里的信息构造下一个 Continuation 返回给系统;如果还没过期,就返回 null 结束。这样就能把一套有顺序依赖的工作干净利落地串起来。 记住要点:顺序依赖就用链接调用,链接上限是三个callout,回调方法返回新的 Continuation 就是继续,返回 null 就是收工。这样讲是不是就好理解啦?

    查看详情
  • 61

    Chaining Async Callouts (cont.)

    第 413 页

    同学们,我们来看这一页的内容:第二个回调处理的是链接响应,也就是多个连续 Callout 串联起来的场景。这里有几个非常重要的规则,咱们一条一条理清楚。 首先,最核心的限制:你最多只能链接 3 个 Callout。就像接力赛,一个人传一个人,最多只能跑三棒。你不能依葫芦画瓢,一个接一个无限制地链下去。 其次,在创建新的延续之前,以及要再次把 Visualforce 请求挂起之前,你必须先拿到当前这个延续的响应。换句话说,不能一下子把三个请求都甩出去,然后等着收结果。你得先等第一个响应回来,在它的回调方法里处理完数据,再决定要不要、以及如何去发起第二个 Callout。 再一个,你必须注意:一旦你沿着链往下走了,就再也拿不到前面旧的响应了。比如第一个 Callout 返回了用户信息,你用它来发起第二个查订单;第二个回来后,你又发起第三个查物流。这时如果你突然想回过头去看看第一个 Callout 带回来的用户信息,对不起,那已经是过去式,访问不到了。所以每一步需要的所有数据,你都要及时保存下来,不能依赖“回头再取”。 最后,每次延续都会暂停当前的 Visualforce 请求,等响应回来后,再恢复这个请求。用户在页面上能感受到这个过程:每完成一个阶段,页面才会更新一次,然后用户看着新加载的数据,再等待下一步处理。整个过程是分步走的,而不是一下子全部跳完。这样用户虽然要等一小会儿,但每一步的状态都是清晰的。 简单总结:链式调用最多三段,必须按顺序取响应,不能回头找旧结果,每一步都会让页面暂停然后更新。这样设计是为了保证数据和交互的顺序可控,也让用户能跟得上系统的节奏。 好,关于链接响应的规则我们就讲到这里,大家对照这个思路去写代码,心里就有数了。

    查看详情
  • 62

    Async Callouts from Imported WSDL

    第 414 页

    好,同学们,我们来看这一页的内容。前面我们讲了用 HttpRequest 直接发送异步调出,但这次要说的是另一种方式——从 WSDL 生成的类也能支持异步调用,用起来更简单。 大家记住,导入一个 WSDL 文件到 Salesforce 后,系统会自动帮我们生成两个类。一个是咱们平常用的同步服务类,方法调用后会一直等着结果回来。另一个就是加了个 ,Async, 前缀的异步类,名字里会多出 Async 字样。 这个异步类最明显的变化是什么呢?——它的每个对外方法,第一个参数都

    查看详情
  • 63

    Async WSDL Callouts — Callback & Testing

    第 415 页

    同学们,我们一起来看这一页幻灯片。这里讲的是,当我们通过WSDL生成的Apex类去调用外部服务,并且在控制器里用异步延续的方式来处理响应的时候,该怎么测试。 首先,在回调方法里,我们拿到响应后,通常会调用响应对象上的 `getValue` 方法,这样才能提取到服务端返回的真实数据。那在编写测试的时候,这种基于WSDL的异步调用,其实和测试HTTP响应的延续非常相似,套路是接近的。 我们分步来看。第一步,你需要创建一个实现 `WebServiceMock` 接口的类,这个类可以非常小,只是提供一个模拟的响应就够了。然后在测试方法里,先调用控制器的动作方法,这时候会得到一个延续对象。接着,我们可以验证一下发出的请求参数是否正确。然后,创建一个模拟的 `HttpResponse`,把你想让服务端返回的数据填进去。再调用 `Test.setContinuationResponse` 方法,把这个模拟响应绑定到延续上。紧接着,用 `Test.invokeContinuationMethod` 来手动触发回调方法,让控制器处理这个模拟响应。

    查看详情