Salesforce與網絡服務的通信
在Salesforce中可以利用Apex類與遠程站點的網絡服務進行通信。當遠程網絡服務支持REST方法時,開發者可以利用Apex代碼進行數據的操作。
設置遠程站點
在設置界面下,搜索“遠程站點”,點擊“安全性控制”菜單項下的“遠程站點設置”鏈接,即可進入遠程站點的一覽表。在此處可以新建、編輯、刪除遠程站點。這些遠程站點可以作為網絡服務接口。
Apex REST請求
Apex中可以以HttpRequest類為核心和網絡服務接口進行REST通信。HttpRequest類包括了“setEndpoint()”、“setMethod()”、“setHeader()”、“setBody()”等函數。
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類型變量
Map<String, Object> results = (Map<String, Object>) JSON.deserializeUntyped(response.getBody());
// 對結果進行處理,得到language對象
List<Object> languages = (List<Object>) results.get('languages');
}
return response;
}
}
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"]}
在單元測試函數中,寫入如下代碼:
@isTest
static 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'));
Map<String, Object> results = (Map<String, Object>) JSON.deserializedUntyped(result.getBody());
List<Object> languages = (List<Object>) results.get('languages');
System.assertEquals(3, languages.size());
}
HttpCalloutMock接口
HttpCalloutMock接口的使用方法與StaticResourceCalloutMock()函數類似,不過不需要先建立靜態資源,而需要預先建立一個全局Apex類,該類實現了HttpCalloutMock接口,並預設了網絡服務請求的模擬數據。
比如要測試上面示例代碼中的“makePostCallout()”函數,則首先在系統中建立一個“LanguagesHttpCalloutMock”類,在其中設置:
@isTest
global 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;
}
}
在單元測試函數中,寫入如下代碼:
@isTest
static 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請求。