Salesforce与网络服务的通信
在Salesforce中可以利用Apex类与远程站点的网络服务进行通信。当远程网络服务支持REST方法时,开发者可以利用Apex代码进行数据的操作。
设置远程站点
在设置界面下,搜索“远程站点”,点击“安全性控制”菜单项下的“远程站点设置”链接,即可进入远程站点的一览表。在此处可以新建、编辑、删除远程站点。这些远程站点可以作为网络服务接口。
Apex REST请求
Apex中可以以HttpRequest类为核心和网络服务接口进行REST通信。HttpRequest类包括了“setEndpoint()”、“setMethod()”、“setHeader()”、“setBody()”等函数。
假设有一个网络服务接口“https://example.service.com/laguages”,可以对编程语言的名字进行操作。当执行GET请求时,会给出一个json的结果,包含了一个“languages”数组,里面是若干“language”对象。
GET请求
用以下代码可以实现GET请求:
public class LanguageCallouts { public static HttpResponse makeGetCallout() { Http http = new Http(); HttpRequest request = new HttpRequest(); // 设置网络服务接口的地址 request.setEndpoint('https://example.service.com/laguages'); // 设置REST方法 request.setMethod('GET'); // 发送HTTP请求 HttpResponse response = http.send(request); // 检查HTTP通信结果状态代码 if (response.getStatusCode() == 200) { // 将通信结果转化为Map类型变量 Mapresults = (Map ) JSON.deserializeUntyped(response.getBody()); // 对结果进行处理,得到language对象 List
POST请求
用以下代码可以实现POST请求:
public class LanguageCallouts { public static HttpResponse makePostCallout() { Http http = new Http(); HttpRequest request = new HttpRequest(); // 设置网络服务接口的地址 request.setEndpoint('https://example.service.com/laguages'); // 设置REST方法 request.setMethod('POST'); // 设置请求的Header,类型为JSON request.setHeader('Content-Type', 'application/json;charset=UTF-8'); // 将一个JSON对象传入请求的Body,设置编程语言的名字 request.setBody('{"name":"Apex"}'); // 发送HTTP请求 HttpResponse response = http.send(request); // 检查HTTP通信结果状态代码 if (response.getStatusCode() == 201) { // 在控制台输出通信结果 System.debug(response.getBody()); } return response; }}
对API请求进行单元测试
在Apex的单元测试中,如果被测试的函数涉及到对网络服务的请求,则单元测试函数无法真正的连接到网络服务接口进行数据传输。开发者必须建立模拟数据。
Apex中提供了“StaticResourceCalloutMock()”函数和“HttpCalloutMock”接口来对网络服务接口的请求结果进行模拟
StaticResourceCalloutMock()函数
在使用StaticResourceCalloutMock()函数前需要在系统中建立一个静态资源,其中预设了网络服务请求的结果。
比如要测试上面示例代码中的“makeGetCallout()”函数,则首先在系统中建立一个静态资源“mockRequestResult”,其中包含一个JSON格式的字符串:
{"languages": ["C", "PHP", "Java"]}
在单元测试函数中,写入如下代码:
@isTeststatic void testGetCallout() { StaticResourceCalloutMock mock = new StaticResourceCalloutMock(); // 设置静态资源 mock.setStaticResource('mockRequestResult'); // 设置模拟网络服务请求的返回结果 mock.setStatusCode(200); // 设置模拟网络服务请求的Header部分 mock.setHeader('Content-Type', 'application/json;charset=UTF-8'); // 设置模拟的网络服务请求 Test.setMock(HttpCalloutMock.class, mock); // 运行要测试的函数 HttpResponse result = LanguageCallouts.makeGetCallout(); // 检查返回的结果。该结果应该与mock中设置的内容相同,也包含了静态资源里的内容 System.assertNotEquals(null, result); System.assertEquals(200, result.getStatusCode()); System.assertEquals('application/json;charset=UTF-8', result.getHeader('Content-Type')); Mapresults = (Map ) JSON.deserializedUntyped(result.getBody()); List languages = (List ) results.get('languages'); System.assertEquals(3, languages.size());}
HttpCalloutMock接口
HttpCalloutMock接口的使用方法与StaticResourceCalloutMock()函数类似,不过不需要先建立静态资源,而需要预先建立一个全局Apex类,该类实现了HttpCalloutMock接口,并预设了网络服务请求的模拟数据。
比如要测试上面示例代码中的“makePostCallout()”函数,则首先在系统中建立一个“LanguagesHttpCalloutMock”类,在其中设置:@isTestglobal class LanguagesHttpCalloutMock implements HttpCalloutMOck { global HttpResponse response(HttpRequest request) { HttpResponse response = new HttpResponse(); response.setHeader('Content-Type', 'application/json'); response.setBody('{"languages": ["C", "PHP", "Java", "Apex"]}'); response.setStatusCode(200); return response; }}
在单元测试函数中,写入如下代码:
@isTeststatic void testPostCallout() { // 设置模拟的网络服务请求 Test.setMock(HttpCalloutMock.class, new LanguagesHttpCalloutMock()); // 运行要测试的函数 HttpResponse result = LanguageCallouts.makePostCallout(); // 检查返回的结果 System.assertEquals(200, result.getStatusCode()); System.assertEquals('application/json;charset=UTF-8', result.getHeader('Content-Type')); String expectedResult = '{"languages": ["C", "PHP", "Java", "Apex"]}'; System.assertEquals(response.getBody(), expectedResult);}
Apex类作为网络服务
Apex类可以被扩展为网络服务,外部的请求可以通过此类来与Salesforce中的数据进行通信。
将Apex类定义为REST服务类
将Apex类定义为REST服务类只需要以下步骤:
- 将类定义为全局类
- 将特定注解添加到类和函数的定义 比如:
@RestResource(urlMapping='/Account/*)global with sharing class ExampleRestClass { @HttpGet global static Account getAccount() { // ... }}
代码讲解:
- 在类的定义上方,添加了@RestResource注解,并定义了“urlMapping”属性。这样,该Salesforce中的特定URL便可以作为REST服务的端点。在此示例中,外部请求通过URL “https://xxx.salesforce.com/services/apexrest/Account/” 就可以调用此类。需要注意的是,“urlMapping”属性是区分大小写的。
- 在函数的上方,添加了@HttpGet注解,说明此类相应“GET”方法。同样,基于标准的REST方法,还有其他注解:@HttpPost, @HttpDelete, @HttpPut, @HttpPatch等。
将Apex类定义为SOAP服务类
将Apex类定义为SOAP服务类和定义为REST服务类的步骤类似,只不过不需要注解,而是直接用“webservice”关键字定义函数。比如:
global with sharing class ExampleSoapClass { webservice static Account getAccount(String Id) { // ... }}
从设置界面的“Apex 类”链接进入Apex类一览表,再进入该类的详细信息页面,即可下载该类对应的WSDL文件,用于SOAP请求。