Metadata、Platform Cache、Knowledge 与 Files 完全指南

Metadata/Platform Cache/Knowledge/Files完整指南:Metadata.Operations.retrieve同步检索+enqueueDeployment异步部署(仅创建更新/组件全名格式/自定义元数据类型+布局/API40.0+/安装脚本可检索部署+卸载仅检索)、安全(安装类可访问公开元数据/受保护仅同命名空间/非认证包需组织首选项/包描述必须声明通知)、测试(DeployCallbackContext子类重写getCallbackJobId/构造DeployResults测试handleResults)、Permission Set Groups(Test.calculatePermissionSetGroup/CPU限制/复杂PSG+大量用户→失败)、Platform Cache(Session最长8h+Org最长48h/Enterprise10MB+Unlimited30MB+3MB Provider Free/不持久化+类修改失效+不加密+事务回滚+Flow限制)、Session/Org类(键格式+local前缀+put重载+Visibility枚举)、Org并发(per-key而非per-transaction选择)、分区(一个默认+分配≥5整数+不能打包默认分区+运行时验证)、Visualforce全局变量($Cache.Session/$Cache.Org+点符号+CacheBuilder_B_后缀)、CacheBuilder接口(doLoad String/非static/null不缓存/自动处理缺失)、内部机制(本地缓存+LRU淘汰+请求成功提交可变操作)、最佳实践(大项优于小项/分组请求/避免contains+get+getKeys+clear)、Knowledge(KbManagement.PublishingService+SearchPromotionRule+Search.suggest+KnowledgeSuggestionFilter+hasMoreResults分页)、Files(Sfc.ContentDownloadHandlerFactory+ContentDownloadHandler+isDownloadAllowed+redirectUrl+多文件ContentPack+SOAP API异常替代重定向)。...

📅 2026/7/16 ✍️ ponybai 🏷️ apex, salesforce

Metadata、Platform Cache、Knowledge 与 Files

综合指南

本章涵盖四大平台特性:Metadata 命名空间(检索/部署元数据——自定安装升级和安装后配置)、Platform Cache(会话/组织缓存提升性能——分布式缓存空间防占用)、Salesforce Knowledge(文章全生命周期管理——发布/归档/翻译/审阅)和 Salesforce Files(下载前定制——杀毒扫描/IRM 控制/设备限制)。

Metadata 操作:检索与部署

Metadata

Metadata.Operations.retrieve() 同步检索当前组织元数据——提供组件名称列表,返回 Metadata.Metadata 派生类匹配组件数据。Metadata.Operations.enqueueDeployment() 异步部署到当前组织——可创建和更新组件但不能删除。需使用组件全名——格式:namespace__TypeName__mdt.namespace__ComponentName。更新命名空间中的组件时必须限定命名空间。

支持:自定义元数据类型记录布局(Layout)。适用于 API 40.0+。安装后脚本中可检索和部署——卸载脚本中仅可检索。异步部署作业有服务保护限制——限制 Apex 发起的 Metadata API 部署同时入队数量。

典型用例:

  • 应用安装/升级时自定义:安装或升级期间创建或更新元数据让用户配置你的应用
  • 安装后自定义:通过自有 UI 让管理员配置应用(而非手动使用标准 Salesforce Setup UI)
  • 安全访问受保护元数据:更新应用内部使用的元数据而不暴露这些类型和组件给用户

Metadata:安全与测试

安全测试

安全注意事项:

  • 安装的 Apex 类可访问订阅者组织中任何公开支持的元数据类型或组件
  • 受保护元数据(如标记为 protected 的自定义元数据类型)仅同命名空间的 Apex 类可访问
  • 非认证托管包访问公开或受保护元数据需启用 Deploy Metadata from Non-Certified Package Versions via Apex 组织首选项(Setup → Apex Settings)——用于安全审查前测试或试验目的
  • 应用必须在包描述中通知用户可检索或部署元数据——Salesforce 安全审查期间验证此通知。示例声明:"This package can access and change metadata outside its namespace in the Salesforce org where it's installed."

部署限制:

  • enqueueDeployment() 使用异步 Apex——部署作业和回调计入当前组织的异步作业限制
  • 所有标准 Apex Governor Limit 适用
  • 限制 Apex 发起的 Metadata API 部署同时入队数量——保持服务功能
  • 回调在异步上下文中运行——异步限制适用

测试 Metadata 部署:

  • 部署请求代码测试:验证 DeployContainer 包含正确的元数据组件和组件值——断言需要部署的准确内容
  • 部署结果代码测试:验证 DeployCallback 处理预期和非预期结果。创建 Metadata.DeployCallbackContext 子类——重写 getCallbackJobId() 返回测试 ID。直接实例化你的回调类并构造测试 DeployResults 测试 handleResults() 方法

Permission Set Groups 与 Platform Cache 简介

PSG与Cache

Permission Set Groups:Test.calculatePermissionSetGroup(psgId) 强制立即计算聚合权限——计入 Apex CPU 限制。PSG 状态必须为 'Updated' 后才能分配。复杂的 PSG(大量包含权限集或总体启用权限多)+ 大量用户分配 → CPU 限制超出导致测试失败。最佳实践:在 @testSetup 方法中运行一次并在后续测试中复用数据。

Platform Cache 两种类型:

  • Session Cache:存储单用户会话数据——例如浏览不同地图位置时重用计算结果。最长存活 8 小时或 ttlsecs 到期(以先到者为准)。Session cache 随会话生命存在
  • Org Cache:数据跨会话/请求/用户可访问——例如基于用户配置文件动态显示菜单项的内容。仅 ttlsecs 到期——最长 48 小时

容量:Enterprise 10MB、Unlimited+Performance 30MB、其他 0MB。安全审查托管包额外 3MB Provider Free 容量(可分配给 session/org cache)。

核心缓存特性:

  • 不持久化——无数据丢失保证(不用于关键数据存储)
  • 修改 Apex 类使缓存失效——全部或部分缓存数据可能丢失
  • 数据不加密——不存储敏感信息
  • 事务失败时缓存操作回滚——每个缓存操作依赖运行中的 Apex 事务
  • 最佳缓存候选:会话中重用 + 静态(不快速变化)+ 否则获取昂贵
  • Flow 限制:包含 Pause 元素或 Scheduled Action 的 Flow 中——后续步骤不能访问 Session Cache

Platform Cache:特性与注意事项

Cache特性

存储/检索类:

  • Cache.Session / Cache.Org:管理任意分区值——键格式 namespace.partition.key
  • Cache.SessionPartition / Cache.OrgPartition:管理单个分区值——更简洁(仅需键名)

命名空间可见性:Cache.Visibility 枚举——ALL(任何命名空间可见)或限制特定命名空间。local 前缀代表当前代码运行组织命名空间——托管包中指向订阅者组织(不是包命名空间)。

重要并发行为:Org cache 支持跨多事务并发读写——同 key 同时更新任选其一作为赢家。选择是 per-key 而非 per-transaction——例如同时一个事务写 PetType="Cat"+PetName="Felix",另一事务写 PetType="Dog"+PetName="Fido"——结果可能是 PetType="Cat" 且 PetName="Fido"。

缓存缺失处理:必须处理缓存返回 null 的情况——或使用 CacheBuilder 接口自动处理。

关键限制:

  • Key 最大 50 字符
  • 单缓存项最大 100KB——超出抛 Cache.ItemSizeLimitExceededException
  • Session local cache 500KB/request | Org local cache 1,000KB/request
  • Session ttl 300s(5min) ~ 28,800s(8h) | Org ttl 300s ~ 172,800s(48h,默认 86,400s/24h)
  • 统计方法(getAvgGetSize/getMaxGetSize/getMissRate 等)从缓存服务器重启后开始计——不包含重启前数据

Platform Cache:分区

分区

Setup → Platform Cache → 使用 Partition 工具:创建/编辑/删除分区——分配 session 和 org 容量平衡应用性能。每个分区有一个 session cache 和一个 org cache 段——分别分配容量。

分区规则:

  • 可定义一个默认分区——默认分区中操作省略分区名
  • Session/org 分配可为 0 或 ≥5(整数)
  • 所有分区分配总和 = Platform Cache 总分配 ≤ 组织总容量
  • 打包:分区自动包含在包中——需显式添加。运行时验证而非编译时——缺失分区不报编译错误
  • 默认分区不能打包部署——使用显式非默认分区替代
  • 查看当前容量/分配/分区详情快照

Session Cache:存储与检索

Session Cache

Cache.Session 方法——跨分区操作:

// 键格式:namespace.partition.key
Cache.Session.put('ns1.partition1.orderDate', dt);
if (Cache.Session.contains('ns1.partition1.orderDate')) {
    DateTime cachedDt = (DateTime) Cache.Session.get('ns1.partition1.orderDate');
}

// 默认分区+调用类命名空间——省略前缀
Cache.Session.put('orderDate', dt);

// local 前缀 = 当前组织命名空间(托管包=订阅者组织)
Cache.Session.put('local.myPartition.orderDate', dt);  // = ns1.myPartition.orderDate

// put 重载——设置 ttl + 可见性 + 不可覆盖
Cache.Session.put('ns1.partition1.totalSum', '500', 3600, Cache.Visibility.ALL, true);

Cache.SessionPartition——单分区操作:

Cache.SessionPartition part = Cache.Session.getPartition('myNs.myPartition');
part.put('OrderDate', Date.today());
String title = (String) part.get('BookTitle');
// 点符号一行调用
String author = (String) Cache.Session.getPartition('myNs.myPartition').get('BookAuthor');

Org Cache:存储与检索

Org Cache

与 Session Cache 完全相同的 API 模式——Cache.Org.put/get/contains/remove。键格式命名规则、local 前缀、put 重载方法一致。OrgPartition 等效于 SessionPartition。

Visualforce 全局变量:{!$Cache.Session.ns.part.key} | {!$Cache.Org.ns.part.key}——支持点符号访问属性和方法(List.size/自定义类属性)。不同于 Apex 方法——不可省略 namespace.partition 前缀。无命名空间组织用 local。CacheBuilder 类:键名加 _B_ 后缀和实现类名——如 {!$Cache.Session.ns.part.CacheBuilderImpl_B_key}

CacheBuilder 接口:安全缓存

CacheBuilder

最佳实践——创建实现 Cache.CacheBuilder内部类(非 static——Salesforce 实例化新实例执行 doLoad),重写 doLoad(String var) 构建缓存值。Salesforce 自动:检查缓存→命中返回→未命中执行 doLoad→缓存结果→返回。唯一键 = 类名 + doLoad String 参数。

要求:doLoad 必须接受 String 参数(即使不使用——Salesforce 用于构建唯一键)。返回 null 时不缓存值——消费者需处理 null(建议用作临时重建失败信号)。不需写 put() 或 null 检查代码。

class UserInfoCache implements Cache.CacheBuilder {
    public Object doLoad(String userid) {
        return [SELECT Id, IsActive, username FROM User WHERE Id = :userid];
    }
}
User batman = (User) Cache.Org.get(UserInfoCache.class, '00541000000ek4c');

Platform Cache:最佳实践与内部机制

最佳实践

性能评估:使用 System.currentTimeMillis() 而非 debug log 时间戳——计算实际耗时对比有无缓存。

最佳实践清单:

  • 优雅处理缺失:CacheBuilder 或手动 null 检查。添加 debug 日志用于缓存操作追踪
  • 分组请求:批量 get(keys) 而非逐个 get——在初始化方法中一次获取所有需要的键
  • 缓存大项:缓存少量大项(如 Apex 类封装数据实例)比许多单独小项更高效——减少序列化大小/时间/提交时间/容量使用
  • 避免昂贵操作:Cache.Org.getKeys()/getCapacity() 遍历所有分区信息——少用。不要 contains(key) + get(key) 连用——直接 get 并检查 null。非必要不清空缓存——清空遍历所有分区空间 + 应用重新生成缓存(数据库查询+计算)
  • 注意限制:100KB 单缓存项 → ItemSizeLimitExceededException 需捕获缩小。超出 partition limit → LRU 淘汰。超出 local cache limit → 请求内淘汰(导致意外缺失+浪费资源)

内部机制:Platform Cache 使用本地缓存(应用服务器内存容器)——首次请求加载 session cache 所有项;org cache get 操作从缓存层检索值存储到本地缓存。可变操作(put/remove)先对本地缓存执行——请求成功后提交。LRU 淘汰算法:达到限制时淘汰键至 100% 容量。Session cache 被淘汰时从所有现有 session cache 实例中均匀移除。

Salesforce Knowledge:文章管理

Knowledge

使用 KbManagement.PublishingService 类管理文章及翻译全生命周期:发布/更新/检索/删除/提交翻译/设置翻译完成或未完成状态/归档/分配草稿或翻译审阅任务。日期值基于 GMT。需启用 Salesforce Knowledge。

推广搜索词(Promoted Search Terms):SearchPromotionRule sObject——关联关键词到已发布文章(PublishStatus=Online)提升搜索排名。需启用 Knowledge 才能对 SearchPromotionRule 执行 DML。

文章建议:Search.suggest(searchText, objectType, options)——返回标题匹配搜索字符串的文章列表。通过 Search.KnowledgeSuggestionFilter 设置语言(language)和发布状态(Online/Draft)。支持分页交互(首次 5 条 + 更多结果按钮)。Search.SuggestionResultshasMoreResults()getSuggestionResults()

Salesforce Files:下载定制

Files

Sfc 命名空间(API 39.0+)定制文件下载行为——定制代码在下载运行决定是否允许。实现 Sfc.ContentDownloadHandlerFactory 接口——工厂类返回 ContentDownloadHandler 处理器。

ContentDownloadHandler 属性:isDownloadAllowed(是否允许下载)、redirectUrl(不允许时重定向 URL——传递问题文件 ID 列表)。

支持场景:

  • 基于用户配置文件/设备/文件类型和大小阻止下载
  • 应用 IRM 控制——追踪文件下载次数、在 IRM 系统处理后提供下载端点
  • 标记可疑文件——重定向到杀毒扫描
  • 多文件下载和 Content Pack 下载——设置 isDownloadAllowed=false 导致整个下载失败。通过 redirectUrl 传递问题文件列表

执行流程:UI/Connect API/sObject 调用触发下载 → 查找 Sfc.ContentDownloadHandlerFactory 实现 → 如未找到则直接下载 → 如找到多个实现按名称排序级联处理——第一个不允许下载的实现被使用。SOAP API 下载:通过 Apex 类检查但不支持重定向——返回错误消息异常替代。

Metadata API 检索部署、Platform Cache 双层性能优化、Knowledge 文章全生命周期和 Files 下载安全定制——共同构成 Salesforce 平台深度定制和性能优化的核心工具集。