zoukankan      html  css  js  c++  java
  • Salesforce REST 接口集成服务(二)

    在 Salesforce REST 接口集成服务 一文中,主要讲述了如何调用外部服务器的接口,那么该如何开放Salesforce内部接口给外部系统呢?
    将Apex类作为Rest Web服务可用非常简单
    • 定义Class 为Global
    • 定义Method为global static
    • 在类和方法上添加注解,比如@HttpGet
    类似这样:
    @RestResource(urlMapping='/Account/*')
    global with sharing class MyRestResource {
        @HttpGet
        global static Account getRecord() {
            // 写入代码
            return null; 
        }
    }
    在MyRestResource上,我们使用了@RestResource(urlMapping='/Account/*') 进行标注,那么访问该Class的URL路径即
    https://yourInstance.salesforce.com/service/apexrest/Account/*
    Tips: URL区分大小写,并且可以包含通配符(*)
    其中https://yourInstance.salesforce.com为Salesforce组织域名,/service/apexrest是固定关键字,/Account/*是每个开放的接口映射的路径
    Tips: 如果是托管包中包含Apex REST方法时,需要加上托管包命名空间,比如MyRestResource类在名为packageNamespace的托管程序包命名空间中,那么通过REST调用这些方法使用的URL格式为 https://instance.salesforce.com/services/apexrest/packageNamespace/Account/*
    在每一个Salesforce类中,方法上的注解共有五种,且每种仅能出现一次
    简单说,@HttpGet 用于读取检索Salesforce系统中的数据,@HttpPost用于创建记录到Salesforce中,@HttpDelete 用于删除Salesforce中的记录,@HttpPut用于更新Salesforce中的记录,特殊的是,如果有的字段没有传值,会将原本记录上的值置空,类似于Upsert,@HttpPatch 同样用于更新Salesforce中的值,不同于HttpPut的一点是,你传什么字段就更新什么字段,不会说覆盖没有传递的字段值
    @RestResource(urlMapping='/Cases/*')
    global with sharing class CaseManager {
        @HttpGet
        global static Case getCaseById() {
            RestRequest request = RestContext.request;
            // 从URL末尾获取case Id
            String caseId = request.requestURI.substring(
              request.requestURI.lastIndexOf('/')+1);
            Case result =  [SELECT CaseNumber,Subject,Status,Origin,Priority
                            FROM Case
                            WHERE Id = :caseId];
            return result;
        }
        @HttpPost
        global static ID createCase(String subject, String status,
            String origin, String priority) {
            Case thisCase = new Case(
                Subject=subject,
                Status=status,
                Origin=origin,
                Priority=priority);
            insert thisCase;
            return thisCase.Id;
        }  
        @HttpDelete
        global static void deleteCase() {
            RestRequest request = RestContext.request;
            String caseId = request.requestURI.substring(
                request.requestURI.lastIndexOf('/')+1);
            Case thisCase = [SELECT Id FROM Case WHERE Id = :caseId];
            delete thisCase;
        }    
        @HttpPut
        global static ID upsertCase(String subject, String status,
            String origin, String priority, String id) {
            Case thisCase = new Case(
                    Id=id,
                    Subject=subject,
                    Status=status,
                    Origin=origin,
                    Priority=priority);
            // ID区分大小写
            upsert thisCase;
            // 返回case Id
            return thisCase.Id;
        }
        @HttpPatch
        global static ID updateCaseFields() {
            RestRequest request = RestContext.request;
            String caseId = request.requestURI.substring(
                request.requestURI.lastIndexOf('/')+1);
            Case thisCase = [SELECT Id FROM Case WHERE Id = :caseId];
            // 将JSON字符串反序列化
            Map<String, Object> params = (Map<String, Object>)JSON.deserializeUntyped(request.requestbody.tostring());
            // 遍历
            for(String fieldName : params.keySet()) {
                // 赋值
                thisCase.put(fieldName, params.get(fieldName));
            }
            update thisCase;
            return thisCase.Id;
        }   
    }
    Apex REST支持OAuth2.0 和会话身份验证两种机制,不过在进行接口测试时,Salesforce提供了WorkBench来简化测试流程
     使用Salesforce账号登录WorkBench,然后选择 utilities | REST Explorer,选择 POST方式,如下图:
     

    点击Execute后,即可查看接口执行结果如下,点击Show Raw Response可以查看接口返回的原始信息 

    其他的GET等标准方式测试方式同POST.

    Tips: Workbench是一套功能强大的基于Web的工具套件,供管理员和开发人员通过Lightning Platform API与组织进行交互。通过Workbench,可以使用会话身份验证,并使用用户名和密码登录到Salesforce,从而使用REST资源管理器调用REST服务
    如果考虑对API端点进行版本控制,以便可以在不破坏现有代码的情况下提供功能升级,我们可以创建两个类来指定/ Cases / v1 / *和/ Cases / v2 / *的URL映射,实现接口版本的平滑切换
    最后,测试Apex REST类与测试任何其他Apex类相似,只需通过传入参数值来调用类方法,然后验证结果。 对于不带参数或依赖REST请求中信息的方法,可以通过模拟REST请求类覆盖测试
    // 模拟一个Rest请求
    RestRequest request = new RestRequest();
    // 模拟REST请求参数
    request.requestUri = 'https://yourInstance.salesforce.com/services/apexrest/Cases/' + recordId;
    request.httpMethod = 'GET';
    request.params.put('status', 'Working');
    // 最后分配这个REST请求给RestContext
    RestContext.request = request;
    所以CaseManager的测试类如下
    @IsTest
    private class CaseManagerTest {
        @isTest static void testGetCaseById() {
            Id recordId = createTestRecord();
            //  模拟Request 请求
            RestRequest request = new RestRequest();
            request.requestUri = 'https://yourInstance.salesforce.com/services/apexrest/Cases/‘  + recordId;
            request.httpMethod = 'GET';
            RestContext.request = request;
            // 调用测试方法
            Case thisCase = CaseManager.getCaseById();
            //  断言验证结果
            System.assert(thisCase != null);
            System.assertEquals('Test record', thisCase.Subject);
        }
        @isTest static void testCreateCase() {
            ID thisCaseId = CaseManager.createCase('Ferocious chipmunk', 'New', 'Phone', 'Low');
            System.assert(thisCaseId != null);
            Case thisCase = [SELECT Id,Subject FROM Case WHERE Id=:thisCaseId];
            System.assert(thisCase != null);
            System.assertEquals(thisCase.Subject, 'Ferocious chipmunk');
        }
        @isTest static void testDeleteCase() {
            Id recordId = createTestRecord();
            // 模拟Request 请求
            RestRequest request = new RestRequest();
            request.requestUri =  'https://yourInstance.salesforce.com/services/apexrest/Cases/‘  + recordId;
            request.httpMethod = 'GET';
            RestContext.request = request;
            // 调用测试方法
            CaseManager.deleteCase();
            // 验证结果是否删除
            List<Case> cases = [SELECT Id FROM Case WHERE Id=:recordId];
            System.assert(cases.size() == 0);
        }
        @isTest static void testUpsertCase() {
            ID case1Id = CaseManager.upsertCase( 'Ferocious chipmunk', 'New', 'Phone', 'Low', null);
            System.assert(Case1Id != null);
            Case case1 = [SELECT Id,Subject FROM Case WHERE Id=:case1Id];
            System.assert(case1 != null);
            System.assertEquals(case1.Subject, 'Ferocious chipmunk');
            // 更新状态 New → Working
            ID case2Id = CaseManager.upsertCase('Ferocious chipmunk', 'Working', 'Phone', 'Low', case1Id);
            // 验证是否更新
            System.assertEquals(case1Id, case2Id);
            Case case2 = [SELECT Id,Status FROM Case WHERE Id=:case2Id];
            System.assert(case2 != null);
            System.assertEquals(case2.Status, 'Working');
        }   
        @isTest static void testUpdateCaseFields() {
            Id recordId = createTestRecord();
            RestRequest request = new RestRequest();
            request.requestUri = 'https://yourInstance.salesforce.com/services/apexrest/Cases/' + recordId;
            request.httpMethod = 'PATCH';
            request.addHeader('Content-Type', 'application/json');
            request.requestBody = Blob.valueOf('{"status": "Working"}');
            RestContext.request = request;
            ID thisCaseId = CaseManager.updateCaseFields();
            System.assert(thisCaseId != null);
            Case thisCase = [SELECT Id,Status FROM Case WHERE Id=:thisCaseId];
            System.assert(thisCase != null);
            System.assertEquals(thisCase.Status, 'Working');
        } 
        // 测试工具类
        static Id createTestRecord() {
            Case caseTest = new Case(
                Subject='Test record',
                Status='New',
                Origin='Phone',
                Priority='Medium');
            insert caseTest;
            return caseTest.Id;
        }         
    } 
    参考数据:
     
  • 相关阅读:
    Principle of Computing (Python)学习笔记(5) BFS Searching + Zombie Apocalypse
    《Java从入门到精通》src9-25
    《Java从入门到精通》src0-8
    windows查看某个端口被谁占用
    css selector: xpath:
    awk 正则表达式
    Centos系统各种日志存详解
    mysql日志文件
    mysql主键设置成auto_increment时,进行并发性能測试出现主键反复Duplicate entry &#39;xxx&#39; for key &#39;PRIMARY&#39;
    递归函数时间复杂度分析
  • 原文地址:https://www.cnblogs.com/luqinghua/p/12632137.html
Copyright © 2011-2022 走看看