学习目标
完成这个单位后,你会知道:
- 何时使用预定的Apex。
- 如何监控计划的工作。
- 计划的Apex语法。
- 计划的方法最佳实践。
计划的Apex
Apex Scheduler让您延迟执行,以便您可以在指定的时间运行Apex类。对于使用Batch Apex的每日或每周维护任务来说,这是理想之选。要利用调度程序,编写一个实现Schedulable接口的Apex类,然后按照特定的调度安排它执行。
计划的Apex 语法
为了调用Apex类在特定时间运行,首先实现类的Schedulable接口。然后,使用System.schedule方法安排类的实例在特定时间运行。
global class SomeClass implements Schedulable {
global void execute(SchedulableContext ctx) {
// 真棒代码在这里
}
}
示例代码
这个类查询当前应该关闭的开放机会,并创建一个任务来提醒所有者更新机会。
global class RemindOpptyOwners implements Schedulable {
global void execute(SchedulableContext ctx) {
List<Opportunity> opptys = [SELECT Id, Name, OwnerId, CloseDate
FROM Opportunity
WHERE IsClosed = False AND
CloseDate < TODAY];
// 为列表中的每个机会创建一个任务
TaskUtils.remindOwners(opptys);
}
}
使用System.Schedule方法
在使用Schedulable接口实现类之后,使用System.Schedule方法执行它。 System.Schedule方法使用用户的时区作为所有调度的基础,但是以系统模式运行 – 所有类都被执行,无论用户是否有执行类的权限。
RemindOpptyOwners reminder = new RemindOpptyOwners();
// 秒分钟小时数Day_of_month Month Day_of_week optional_year
String sch = '20 30 8 10 2 ?';
String jobID = System.schedule('Remind Opp Owners', sch, reminder);
从UI调度作业
您也可以使用用户界面安排课程。
- 从安装程序中,在快速查找框中输入Apex,然后选择 Apex Classes.
- 点击 Schedule Apex.
- 对于工作名称,请输入类似Daily Oppty Reminder的内容。
- 单击Apex类旁边的查找按钮,然后为搜索项输入*以获取所有可以调度的类的列表。在搜索结果中,单击您的计划课程的名称。
- 为频率选择每周或每月,并设置所需的频率。
- 选择开始和结束日期,以及首选开始时间。
- 点击 Save.
测试计划的 Apex
就像我们到目前为止所介绍的其他异步方法一样,对于Scheduled Apex,您还必须确保计划的作业在测试结果之前完成。为此,请在System.schedule方法周围再次使用startTest和stopTest,以确保在继续测试之前完成处理。
@isTest
private class RemindOppyOwnersTest {
// CRON表情:3月15日午夜。
// 因为这是一个测试,所以在Test.stopTest()之后立即执行作业。
public static String CRON_EXP = '0 0 0 15 3 ? 2022';
static testmethod void testScheduledJob() {
// 创建一些过时的机会记录
List<Opportunity> opptys = new List<Opportunity>();
Date closeDate = Date.today().addDays(-7);
for (Integer i=0; i<10; i++) {
Opportunity o = new Opportunity(
Name = 'Opportunity ' + i,
CloseDate = closeDate,
StageName = 'Prospecting'
);
opptys.add(o);
}
insert opptys;
// 获取我们刚刚插入的机会的ID
Map<Id, Opportunity> opptyMap = new Map<Id, Opportunity>(opptys);
List<Id> opptyIds = new List<Id>(opptyMap.keySet());
Test.startTest();
// 安排测试工作
String jobId = System.schedule('ScheduledApexTest',
CRON_EXP,
new RemindOpptyOwners());
// 验证计划作业尚未运行。
List<Task> lt = [SELECT Id
FROM Task
WHERE WhatId IN :opptyIds];
System.assertEquals(0, lt.size(), 'Tasks exist before job has run');
// 停止测试将同步运行作业
Test.stopTest();
// 现在计划的作业已经执行,
// 检查我们的任务是否被创建
lt = [SELECT Id
FROM Task
WHERE WhatId IN :opptyIds];
System.assertEquals(opptyIds.size(),
lt.size(),
'Tasks were not created');
}
}
- 一次只能有100个预定的Apex作业,每24小时有最多的预定Apex执行次数。有关详细信息,请参阅参考资料部分中的执行调控器和限制。
- 如果您计划通过触发器安排课程,请特别小心。您必须能够保证触发器不会添加比限制更多的计划作业。
- 计划的Apex不支持同步Web服务标注。为了能够进行标注,通过将标注放在用@future(callout = true)注释的方法中进行异步标注,并从预定的Apex中调用此方法。但是,如果预定的Apex执行批处理作业,则批处理类将支持标注。