Apex API 请求

Salesforce与网络服务的通信

在Salesforce中可以利用Apex类与远程站点的网络服务进行通信。当远程网络服务支持REST方法时,开发者可以利用Apex代码进行数据的操作。

设置远程站点

在设置界面下,搜索“远程站点”,点击“安全性控制”菜单项下的“远程站点设置”链接,即可进入远程站点的一览表。在此处可以新建、编辑、删除远程站点。这些远程站点可以作为网络服务接口。

Apex API 请求

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类型变量
            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服务类只需要以下步骤:

  1. 将类定义为全局类
  2. 将特定注解添加到类和函数的定义
    比如:
@RestResource(urlMapping='/Account/*)
global with sharing class ExampleRestClass {
    @HttpGet
    global static Account getAccount() {
        // ...
    }
}

代码讲解:

  1. 在类的定义上方,添加了@RestResource注解,并定义了“urlMapping”属性。这样,该Salesforce中的特定URL便可以作为REST服务的端点。在此示例中,外部请求通过URL “https://xxx.salesforce.com/services/apexrest/Account/” 就可以调用此类。需要注意的是,“urlMapping”属性是区分大小写的。
  2. 在函数的上方,添加了@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请求。

Apex API 请求

上一篇:Android SDK下载和更新失败的解决方法


下一篇:[技术干货] Zabbix 实现Server和windows的Agent通信加密