# 示例5 - 处理作业失误
说明
有时作业不会在应该执行的时候执行……参考此示例看看如何处理这些失误。
# StatefulDumbJob.java
package org.quartz.examples.example5;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.PersistJobDataAfterExecution;
import java.util.Date;
/**
* Job接口的一个笨(调侃出现了异常)实现,用于单元测试
* 作者:James House
*/
@PersistJobDataAfterExecution
@DisallowConcurrentExecution
public class StatefulDumbJob implements Job {
/*
* 常量
*/
public static final String NUM_EXECUTIONS = "NumExecutions";
public static final String EXECUTION_DELAY = "ExecutionDelay";
/*
* 构造函数
*/
public StatefulDumbJob() {
}
/*
* 接口
*/
/**
* 当与此作业相关联的触发器触发时,由调度器调用此方法
* Throws:作业执行异常(JobExecutionException)-当执行作业时产生异常
*/
public void execute(JobExecutionContext context) throws JobExecutionException {
System.err.println("---" + context.getJobDetail().getKey() + " executing.[" + new Date() + "]");
JobDataMap map = context.getJobDetail().getJobDataMap();
int executeCount = 0;
if (map.containsKey(NUM_EXECUTIONS)) {
executeCount = map.getInt(NUM_EXECUTIONS);
}
executeCount++;
map.put(NUM_EXECUTIONS, executeCount);
long delay = 5000l;
if (map.containsKey(EXECUTION_DELAY)) {
delay = map.getLong(EXECUTION_DELAY);
}
try {
Thread.sleep(delay);
} catch (Exception ignore) {
//
}
System.err.println(" -" + context.getJobDetail().getKey() + " complete (" + executeCount + ").");
}
}
# MisfireExample.java源码
package org.quartz.examples.example5;
import static org.quartz.DateBuilder.nextGivenSecondDate;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.SimpleScheduleBuilder.simpleSchedule;
import static org.quartz.TriggerBuilder.newTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.SchedulerMetaData;
import org.quartz.SimpleTrigger;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
/**
* 演示StatefulJobs的行为,以及当作业执行时间超过触发器重复频率时,失效指令如何影响StatefulJobs触发器的触发
* 在运行该示例时,您应该注意到了有两个具有相同计划的触发器,它们触发相同的作业。触发器“希望”每3秒触发1次,但作业需要10秒才能执
* 行。因此,当作业完成执行时,触发器已经“失效”(除非调度程序的“失效阈值”设置为超过7秒)。您应该看到了其中一个作业的失效指令设置
* 为简单触发器(SimpleTrigger)
* MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT,当检测到失效时,它会立即触发。另一个触发器使用默认
* 的“智能策略”失效指令,这会导致触发器提前到下一个触发时间(跳过错过的那些),这样它不会立即重新触发,而是在下一个计划时间重新触
* 发
* 作者:Chris Bonham
*/
public class MisfireExample {
public void run() throws Exception {
Logger log = LoggerFactory.getLogger(MisfireExample.class);
log.info("------- Initializing -------------------");
//首先,我们必须获得对调度器的引用
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler sched = sf.getScheduler();
log.info("------- Initialization Complete -----------");
log.info("------- Scheduling Jobs -----------");
//可以在sched.start()方法调用前安排作业
//在未来15秒后获得1次不错的轮转时间(开始执行所有作业)
Date startTime = nextGivenSecondDate(null, 15);
//statefulJob1将每3秒运行1次(但它将延迟10秒)
JobDetail job = newJob(StatefulDumbJob.class).withIdentity("statefulJob1", "group1")
.usingJobData(StatefulDumbJob.EXECUTION_DELAY, 10000L).build();
SimpleTrigger trigger = newTrigger().withIdentity("trigger1", "group1").startAt(startTime)
.withSchedule(simpleSchedule().withIntervalInSeconds(3).repeatForever()).build();
Date ft = sched.scheduleJob(job, trigger);
log.info(job.getKey() + " will run at: " + ft + " and repeat: " + trigger.getRepeatCount() + " times, every " + trigger.getRepeatInterval() / 1000 + " seconds");
//statefulJob2将每3秒运行1次(但它将延迟10秒——因此在几次迭代后故意失效)
job = newJob(StatefulDumbJob.class).withIdentity("statefulJob2", "group1")
.usingJobData(StatefulDumbJob.EXECUTION_DELAY, 10000L).build();
trigger = newTrigger()
.withIdentity("trigger2", "group1")
.startAt(startTime)
.withSchedule(simpleSchedule().withIntervalInSeconds(3).repeatForever()
.withMisfireHandlingInstructionNowWithExistingCount()) //设置失效指令
.build();
ft = sched.scheduleJob(job, trigger);
log.info(job.getKey() + " will run at: " + ft + " and repeat: " + trigger.getRepeatCount() + " times, every " + trigger.getRepeatInterval() / 1000 + " seconds");
log.info("------- Starting Scheduler ----------------");
//在调度器启动之前,所有作业都不会执行
sched.start();
log.info("------- Started Scheduler -----------------");
try {
//等待10分钟以触发作业
Thread.sleep(600L * 1000L);
} catch (Exception e) {
//
}
log.info("------- Shutting Down ---------------------");
sched.shutdown(true);
log.info("------- Shutdown Complete -----------------");
SchedulerMetaData metaData = sched.getMetaData();
log.info("Executed " + metaData.getNumberOfJobsExecuted() + " jobs.");
}
public static void main(String[] args) throws Exception {
MisfireExample example = new MisfireExample();
example.run();
}
}
# 控制台输出
[main] INFO org.quartz.examples.example5.MisfireExample - ------- Initializing -------------------
[main] INFO org.quartz.impl.StdSchedulerFactory - Using default implementation for ThreadExecutor
[main] INFO org.quartz.simpl.SimpleThreadPool - Job execution threads will use class loader of thread: main
[main] INFO org.quartz.core.SchedulerSignalerImpl - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
[main] INFO org.quartz.core.QuartzScheduler - Quartz Scheduler v.2.3.0 created.
[main] INFO org.quartz.simpl.RAMJobStore - RAMJobStore initialized.
[main] INFO org.quartz.core.QuartzScheduler - Scheduler meta-data: Quartz Scheduler (v2.3.0) 'DefaultQuartzScheduler' with instanceId 'NON_CLUSTERED'
Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
NOT STARTED.
Currently in standby mode.
Number of jobs executed: 0
Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.
Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.
[main] INFO org.quartz.impl.StdSchedulerFactory - Quartz scheduler 'DefaultQuartzScheduler' initialized from default resource file in Quartz package: 'quartz.properties'
[main] INFO org.quartz.impl.StdSchedulerFactory - Quartz scheduler version: 2.3.0
[main] INFO org.quartz.examples.example5.MisfireExample - ------- Initialization Complete -----------
[main] INFO org.quartz.examples.example5.MisfireExample - ------- Scheduling Jobs -----------
[main] INFO org.quartz.examples.example5.MisfireExample - group1.statefulJob1 will run at: Wed Nov 30 00:15:45 CST 2022 and repeat: -1 times, every 3 seconds
[main] INFO org.quartz.examples.example5.MisfireExample - group1.statefulJob2 will run at: Wed Nov 30 00:15:45 CST 2022 and repeat: -1 times, every 3 seconds
[main] INFO org.quartz.examples.example5.MisfireExample - ------- Starting Scheduler ----------------
[main] INFO org.quartz.core.QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED started.
[main] INFO org.quartz.examples.example5.MisfireExample - ------- Started Scheduler -----------------
---group1.statefulJob1 executing.[Wed Nov 30 00:15:45 CST 2022]
---group1.statefulJob2 executing.[Wed Nov 30 00:15:45 CST 2022]
-group1.statefulJob1 complete (1).
-group1.statefulJob2 complete (1).
---group1.statefulJob1 executing.[Wed Nov 30 00:15:55 CST 2022]
---group1.statefulJob2 executing.[Wed Nov 30 00:15:55 CST 2022]
-group1.statefulJob1 complete (2).
-group1.statefulJob2 complete (2).
---group1.statefulJob1 executing.[Wed Nov 30 00:16:05 CST 2022]
---group1.statefulJob2 executing.[Wed Nov 30 00:16:05 CST 2022]
-group1.statefulJob2 complete (3).
-group1.statefulJob1 complete (3).
---group1.statefulJob1 executing.[Wed Nov 30 00:16:15 CST 2022]
---group1.statefulJob2 executing.[Wed Nov 30 00:16:15 CST 2022]
-group1.statefulJob2 complete (4).
-group1.statefulJob1 complete (4).
---group1.statefulJob1 executing.[Wed Nov 30 00:16:25 CST 2022]
---group1.statefulJob2 executing.[Wed Nov 30 00:16:25 CST 2022]
-group1.statefulJob1 complete (5).
-group1.statefulJob2 complete (5).
---group1.statefulJob1 executing.[Wed Nov 30 00:16:35 CST 2022]
---group1.statefulJob2 executing.[Wed Nov 30 00:16:35 CST 2022]
-group1.statefulJob1 complete (6).
-group1.statefulJob2 complete (6).
---group1.statefulJob1 executing.[Wed Nov 30 00:16:45 CST 2022]
---group1.statefulJob2 executing.[Wed Nov 30 00:16:45 CST 2022]
-group1.statefulJob2 complete (7).
-group1.statefulJob1 complete (7).
---group1.statefulJob1 executing.[Wed Nov 30 00:16:55 CST 2022]
---group1.statefulJob2 executing.[Wed Nov 30 00:16:55 CST 2022]
-group1.statefulJob1 complete (8).
---group1.statefulJob1 executing.[Wed Nov 30 00:17:05 CST 2022]
-group1.statefulJob2 complete (8).
---group1.statefulJob2 executing.[Wed Nov 30 00:17:05 CST 2022]
-group1.statefulJob1 complete (9).
-group1.statefulJob2 complete (9).
---group1.statefulJob2 executing.[Wed Nov 30 00:17:15 CST 2022]
---group1.statefulJob1 executing.[Wed Nov 30 00:17:18 CST 2022]
-group1.statefulJob2 complete (10).
---group1.statefulJob2 executing.[Wed Nov 30 00:17:25 CST 2022]
-group1.statefulJob1 complete (10).
---group1.statefulJob1 executing.[Wed Nov 30 00:17:28 CST 2022]
-group1.statefulJob2 complete (11).
---group1.statefulJob2 executing.[Wed Nov 30 00:17:35 CST 2022]
-group1.statefulJob1 complete (11).
---group1.statefulJob1 executing.[Wed Nov 30 00:17:38 CST 2022]
-group1.statefulJob2 complete (12).
---group1.statefulJob2 executing.[Wed Nov 30 00:17:45 CST 2022]
-group1.statefulJob1 complete (12).
---group1.statefulJob1 executing.[Wed Nov 30 00:17:48 CST 2022]
-group1.statefulJob2 complete (13).
---group1.statefulJob2 executing.[Wed Nov 30 00:17:55 CST 2022]
-group1.statefulJob1 complete (13).
---group1.statefulJob1 executing.[Wed Nov 30 00:17:58 CST 2022]
-group1.statefulJob2 complete (14).
---group1.statefulJob2 executing.[Wed Nov 30 00:18:05 CST 2022]
-group1.statefulJob1 complete (14).
---group1.statefulJob1 executing.[Wed Nov 30 00:18:08 CST 2022]
-group1.statefulJob2 complete (15).
---group1.statefulJob2 executing.[Wed Nov 30 00:18:15 CST 2022]
-group1.statefulJob1 complete (15).
---group1.statefulJob1 executing.[Wed Nov 30 00:18:18 CST 2022]
-group1.statefulJob2 complete (16).
---group1.statefulJob2 executing.[Wed Nov 30 00:18:25 CST 2022]
-group1.statefulJob1 complete (16).
---group1.statefulJob1 executing.[Wed Nov 30 00:18:28 CST 2022]
-group1.statefulJob2 complete (17).
---group1.statefulJob2 executing.[Wed Nov 30 00:18:35 CST 2022]
-group1.statefulJob1 complete (17).
---group1.statefulJob1 executing.[Wed Nov 30 00:18:38 CST 2022]
-group1.statefulJob2 complete (18).
---group1.statefulJob2 executing.[Wed Nov 30 00:18:45 CST 2022]
-group1.statefulJob1 complete (18).
---group1.statefulJob1 executing.[Wed Nov 30 00:18:51 CST 2022]
-group1.statefulJob2 complete (19).
---group1.statefulJob2 executing.[Wed Nov 30 00:18:55 CST 2022]
-group1.statefulJob1 complete (19).
---group1.statefulJob1 executing.[Wed Nov 30 00:19:01 CST 2022]
-group1.statefulJob2 complete (20).
---group1.statefulJob2 executing.[Wed Nov 30 00:19:05 CST 2022]
-group1.statefulJob1 complete (20).
---group1.statefulJob1 executing.[Wed Nov 30 00:19:11 CST 2022]
-group1.statefulJob2 complete (21).
---group1.statefulJob2 executing.[Wed Nov 30 00:19:15 CST 2022]
-group1.statefulJob1 complete (21).
---group1.statefulJob1 executing.[Wed Nov 30 00:19:21 CST 2022]
-group1.statefulJob2 complete (22).
---group1.statefulJob2 executing.[Wed Nov 30 00:19:25 CST 2022]
-group1.statefulJob1 complete (22).
---group1.statefulJob1 executing.[Wed Nov 30 00:19:31 CST 2022]
-group1.statefulJob2 complete (23).
---group1.statefulJob2 executing.[Wed Nov 30 00:19:35 CST 2022]
-group1.statefulJob1 complete (23).
---group1.statefulJob1 executing.[Wed Nov 30 00:19:41 CST 2022]
-group1.statefulJob2 complete (24).
---group1.statefulJob2 executing.[Wed Nov 30 00:19:45 CST 2022]
-group1.statefulJob1 complete (24).
---group1.statefulJob1 executing.[Wed Nov 30 00:19:51 CST 2022]
-group1.statefulJob2 complete (25).
---group1.statefulJob2 executing.[Wed Nov 30 00:19:55 CST 2022]
-group1.statefulJob1 complete (25).
---group1.statefulJob1 executing.[Wed Nov 30 00:20:01 CST 2022]
-group1.statefulJob2 complete (26).
---group1.statefulJob2 executing.[Wed Nov 30 00:20:05 CST 2022]
-group1.statefulJob1 complete (26).
---group1.statefulJob1 executing.[Wed Nov 30 00:20:11 CST 2022]
-group1.statefulJob2 complete (27).
---group1.statefulJob2 executing.[Wed Nov 30 00:20:15 CST 2022]
-group1.statefulJob1 complete (27).
---group1.statefulJob1 executing.[Wed Nov 30 00:20:24 CST 2022]
-group1.statefulJob2 complete (28).
---group1.statefulJob2 executing.[Wed Nov 30 00:20:25 CST 2022]
-group1.statefulJob1 complete (28).
---group1.statefulJob1 executing.[Wed Nov 30 00:20:34 CST 2022]
-group1.statefulJob2 complete (29).
---group1.statefulJob2 executing.[Wed Nov 30 00:20:35 CST 2022]
-group1.statefulJob1 complete (29).
---group1.statefulJob1 executing.[Wed Nov 30 00:20:44 CST 2022]
-group1.statefulJob2 complete (30).
---group1.statefulJob2 executing.[Wed Nov 30 00:20:45 CST 2022]
-group1.statefulJob1 complete (30).
---group1.statefulJob1 executing.[Wed Nov 30 00:20:54 CST 2022]
-group1.statefulJob2 complete (31).
---group1.statefulJob2 executing.[Wed Nov 30 00:20:55 CST 2022]
-group1.statefulJob1 complete (31).
---group1.statefulJob1 executing.[Wed Nov 30 00:21:04 CST 2022]
-group1.statefulJob2 complete (32).
---group1.statefulJob2 executing.[Wed Nov 30 00:21:05 CST 2022]
-group1.statefulJob1 complete (32).
---group1.statefulJob1 executing.[Wed Nov 30 00:21:14 CST 2022]
-group1.statefulJob2 complete (33).
---group1.statefulJob2 executing.[Wed Nov 30 00:21:15 CST 2022]
-group1.statefulJob1 complete (33).
---group1.statefulJob1 executing.[Wed Nov 30 00:21:24 CST 2022]
-group1.statefulJob2 complete (34).
---group1.statefulJob2 executing.[Wed Nov 30 00:21:25 CST 2022]
-group1.statefulJob1 complete (34).
---group1.statefulJob1 executing.[Wed Nov 30 00:21:34 CST 2022]
-group1.statefulJob2 complete (35).
---group1.statefulJob2 executing.[Wed Nov 30 00:21:35 CST 2022]
-group1.statefulJob1 complete (35).
---group1.statefulJob1 executing.[Wed Nov 30 00:21:44 CST 2022]
-group1.statefulJob2 complete (36).
---group1.statefulJob2 executing.[Wed Nov 30 00:21:45 CST 2022]
-group1.statefulJob1 complete (36).
-group1.statefulJob2 complete (37).
---group1.statefulJob2 executing.[Wed Nov 30 00:21:55 CST 2022]
---group1.statefulJob1 executing.[Wed Nov 30 00:21:57 CST 2022]
-group1.statefulJob2 complete (38).
---group1.statefulJob2 executing.[Wed Nov 30 00:22:05 CST 2022]
-group1.statefulJob1 complete (37).
---group1.statefulJob1 executing.[Wed Nov 30 00:22:07 CST 2022]
-group1.statefulJob2 complete (39).
---group1.statefulJob2 executing.[Wed Nov 30 00:22:15 CST 2022]
-group1.statefulJob1 complete (38).
---group1.statefulJob1 executing.[Wed Nov 30 00:22:17 CST 2022]
-group1.statefulJob2 complete (40).
---group1.statefulJob2 executing.[Wed Nov 30 00:22:25 CST 2022]
-group1.statefulJob1 complete (39).
---group1.statefulJob1 executing.[Wed Nov 30 00:22:27 CST 2022]
-group1.statefulJob2 complete (41).
---group1.statefulJob2 executing.[Wed Nov 30 00:22:35 CST 2022]
-group1.statefulJob1 complete (40).
---group1.statefulJob1 executing.[Wed Nov 30 00:22:37 CST 2022]
-group1.statefulJob2 complete (42).
---group1.statefulJob2 executing.[Wed Nov 30 00:22:45 CST 2022]
-group1.statefulJob1 complete (41).
---group1.statefulJob1 executing.[Wed Nov 30 00:22:47 CST 2022]
-group1.statefulJob2 complete (43).
---group1.statefulJob2 executing.[Wed Nov 30 00:22:55 CST 2022]
-group1.statefulJob1 complete (42).
---group1.statefulJob1 executing.[Wed Nov 30 00:22:57 CST 2022]
-group1.statefulJob2 complete (44).
---group1.statefulJob2 executing.[Wed Nov 30 00:23:05 CST 2022]
-group1.statefulJob1 complete (43).
---group1.statefulJob1 executing.[Wed Nov 30 00:23:07 CST 2022]
-group1.statefulJob2 complete (45).
---group1.statefulJob2 executing.[Wed Nov 30 00:23:15 CST 2022]
-group1.statefulJob1 complete (44).
---group1.statefulJob1 executing.[Wed Nov 30 00:23:17 CST 2022]
-group1.statefulJob2 complete (46).
---group1.statefulJob2 executing.[Wed Nov 30 00:23:25 CST 2022]
-group1.statefulJob1 complete (45).
---group1.statefulJob1 executing.[Wed Nov 30 00:23:30 CST 2022]
-group1.statefulJob2 complete (47).
---group1.statefulJob2 executing.[Wed Nov 30 00:23:35 CST 2022]
-group1.statefulJob1 complete (46).
---group1.statefulJob1 executing.[Wed Nov 30 00:23:40 CST 2022]
-group1.statefulJob2 complete (48).
---group1.statefulJob2 executing.[Wed Nov 30 00:23:45 CST 2022]
-group1.statefulJob1 complete (47).
---group1.statefulJob1 executing.[Wed Nov 30 00:23:50 CST 2022]
-group1.statefulJob2 complete (49).
---group1.statefulJob2 executing.[Wed Nov 30 00:23:55 CST 2022]
-group1.statefulJob1 complete (48).
---group1.statefulJob1 executing.[Wed Nov 30 00:24:00 CST 2022]
-group1.statefulJob2 complete (50).
---group1.statefulJob2 executing.[Wed Nov 30 00:24:05 CST 2022]
-group1.statefulJob1 complete (49).
---group1.statefulJob1 executing.[Wed Nov 30 00:24:10 CST 2022]
-group1.statefulJob2 complete (51).
---group1.statefulJob2 executing.[Wed Nov 30 00:24:15 CST 2022]
-group1.statefulJob1 complete (50).
---group1.statefulJob1 executing.[Wed Nov 30 00:24:20 CST 2022]
-group1.statefulJob2 complete (52).
---group1.statefulJob2 executing.[Wed Nov 30 00:24:25 CST 2022]
-group1.statefulJob1 complete (51).
---group1.statefulJob1 executing.[Wed Nov 30 00:24:30 CST 2022]
-group1.statefulJob2 complete (53).
---group1.statefulJob2 executing.[Wed Nov 30 00:24:35 CST 2022]
-group1.statefulJob1 complete (52).
---group1.statefulJob1 executing.[Wed Nov 30 00:24:40 CST 2022]
-group1.statefulJob2 complete (54).
---group1.statefulJob2 executing.[Wed Nov 30 00:24:45 CST 2022]
-group1.statefulJob1 complete (53).
---group1.statefulJob1 executing.[Wed Nov 30 00:24:50 CST 2022]
-group1.statefulJob2 complete (55).
---group1.statefulJob2 executing.[Wed Nov 30 00:24:55 CST 2022]
-group1.statefulJob1 complete (54).
---group1.statefulJob1 executing.[Wed Nov 30 00:25:03 CST 2022]
-group1.statefulJob2 complete (56).
---group1.statefulJob2 executing.[Wed Nov 30 00:25:05 CST 2022]
-group1.statefulJob1 complete (55).
---group1.statefulJob1 executing.[Wed Nov 30 00:25:13 CST 2022]
-group1.statefulJob2 complete (57).
---group1.statefulJob2 executing.[Wed Nov 30 00:25:15 CST 2022]
-group1.statefulJob1 complete (56).
---group1.statefulJob1 executing.[Wed Nov 30 00:25:23 CST 2022]
-group1.statefulJob2 complete (58).
---group1.statefulJob2 executing.[Wed Nov 30 00:25:25 CST 2022]
-group1.statefulJob1 complete (57).
---group1.statefulJob1 executing.[Wed Nov 30 00:25:33 CST 2022]
-group1.statefulJob2 complete (59).
---group1.statefulJob2 executing.[Wed Nov 30 00:25:35 CST 2022]
[main] INFO org.quartz.examples.example5.MisfireExample - ------- Shutting Down ---------------------
[main] INFO org.quartz.core.QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED shutting down.
[main] INFO org.quartz.core.QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED paused.
-group1.statefulJob1 complete (58).
-group1.statefulJob2 complete (60).
[main] INFO org.quartz.core.QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED shutdown complete.
[main] INFO org.quartz.examples.example5.MisfireExample - ------- Shutdown Complete -----------------
[main] INFO org.quartz.examples.example5.MisfireExample - Executed 118 jobs.
Process finished with exit code 0

微信公众号

QQ交流群
原创网站开发,偏差难以避免。
如若发现错误,诚心感谢反馈。
愿你倾心相念,愿你学有所成。
愿你朝华相顾,愿你前程似锦。
如若发现错误,诚心感谢反馈。
愿你倾心相念,愿你学有所成。
愿你朝华相顾,愿你前程似锦。