本文介绍了如何使用Java代码在系统中创建和执行调度计划和调度作业,但作者并不推荐这种做法,而是建议在系统服务云的调度管理界面中进行操作。文章详细说明了创建调度作业和调度计划的步骤,包括创建动态表单页面、编写代码创建作业和计划、通过点击按钮触发执行等。同时,给出了创建调度作业和调度计划的代码示例,包括设置作业类型、时间、参数等,并展示了如何执行单次调度作业、设置调度计划、删除和查询调度作业的方法。此外,还提供了一个自定义的调度任务类KDFLogTask的示例,展示了任务执行的基本框架。
创作不易,如果文章对您有帮助,请为我点击一个朴实无华的赞^_^
关键词:调度
一、需求
用java代码创建和执行调度计划和调度作业。
我并不推荐用代码去创建调度计划和调度作业,请开发者们尽量在【系统服务云】【系统管理】,
左侧边栏【调度管理】中,使用界面化的方式来创建调度计划和调度作业。
关于如何使用调度任务、调度计划、调度作业,请查看我的另一篇文章:
https://club.kdcloud.com/article/173120773756899840
二、思路与方案
1.创建动态表单页面,拖入几个工具栏的按钮
2.编写代码,创建和执行调度计划、调度作业
3.进入页面中,点击工具栏按钮,让代码中的调度计划开始执行
三、实现过程
1.创建单据页面,用来为第2步骤的插件提供点击事件
2.编写插件
关于创建调度作业有很多种方式,使用JobForm、JobDispatcherProxy、JobClient
下面使用JobForm或者JobDispatcherProxy创建调度作业和调度计划。
(有开发者私信我提出疑问,为什么要在单据中使用调度作业,觉得并不符合实际场景。
在这里做一些解释,本文只是为了探讨调度作业和调度计划的使用方式,请各位开发者根据实际业务场景进行开发)
创建调度作业
private JobInfo getJobInfo () { JobInfo jobInfo = new JobInfo(); // 执行类所在的应用名 jobInfo.setAppId("kdec_wrx_col_app"); // 实时作业,即时执行 // jobInfo.setJobType(JobType.REALTIME); // 业务作业,等到开始时间节点时才执行 jobInfo.setJobType(JobType.BIZ); Date now = new Date(); SimpleDateFormat sf = new SimpleDateFormat("yyyyMMdd_HHmmss"); // 设置调度作业名称yyyyMMddHHmmss jobInfo.setName("赋能部wrx插件作业_" + sf.format(now)); // 设置调度作业编码 jobInfo.setNumber("kdf_job_wrx_p_" + sf.format(now)); // 随机产生一个JobId (任务目标的标识) /*String id = UUID.randomUUID().toString(); jobInfo.setId(id);*/ jobInfo.setTaskClassname("kd.bos.api.task.KDFLogTask"); // 自定义参数 Map<String,Object> params = new HashMap<>(); params.put("time", 10); // 自定义参数,示例任务执行循环次数,10次 jobInfo.setParams(params); // 回调参数,设置一个回调处理标识(actionId) return jobInfo; }
创建调度计划
private PlanInfo getPlanInfo (JobInfo jobInfo) { PlanInfo planInfo = new PlanInfo(); // 设置作业 planInfo.setJobId(jobInfo.getId()); SimpleDateFormat sf = new SimpleDateFormat("yyyyMMdd_HHmmss"); Date now = new Date(); // 设置调度计划名称 planInfo.setName("赋能部wrx插件计划_" + sf.format(now)); // 设置调度计划编码 planInfo.setNumber("kdf_plan_wrx_p_" + sf.format(now)); // 设置开始时间结束时间 Calendar startCalendar = Calendar.getInstance(); // 开始时间为:当前时间1分钟之后 startCalendar.setTime(new Date(now.getTime() + 1000 * 60 * 1)); Calendar endCalendar = Calendar.getInstance(); // 结束时间为:当前时间5分钟之后,整个调度计划执行时间为 endCalendar.setTime(new Date(now.getTime() + 1000 * 60 * 5)); planInfo.setStartTime(startCalendar); planInfo.setEndTime(endCalendar); // 设置重复模式,1分钟 planInfo.setRepeatMode(RepeatModeEnum.ByMinutes); // 设置周期,1次 // 周期+重复模式,表示这个调度计划为1分钟执行1次 planInfo.setPeriod(1); return planInfo; }
执行单次调度作业,不配置调度计划
@Override public void itemClick(ItemClickEvent evt) { super.itemClick(evt); if (evt.getItemKey().equals("kdec_tool_job_c")) { // 直接执行一条调度作业,不设置调度计划 JobInfo jobInfo = getJobInfo(); CloseCallBack closeCallBack = new CloseCallBack(this, "taskcloseback"); // 发布任务,并显示进度 JobForm.dispatch(jobInfo, this.getView(), closeCallBack); System.out.println("JobId: " + jobInfo.getId()); } } /** * 回调事件,在任务处理完毕后继续后续处理 */ @Override public void closedCallBack(ClosedCallBackEvent closedCallBackEvent) { super.closedCallBack(closedCallBackEvent); if (StringUtils.equals(closedCallBackEvent.getActionId(), "taskcloseback")) { this.taskCallBack(closedCallBackEvent.getReturnData()); } } private void taskCallBack(Object returnData) { if (returnData == null) { return; } if (returnData instanceof Map<?, ?>) { @SuppressWarnings("unchecked") Map<String, Object> result = (Map<String, Object>)returnData; if (result.containsKey("taskinfo")) { String taskInfoStr = (String)result.get("taskinfo"); if (StringUtils.isNotBlank(taskInfoStr)) { TaskInfo taskInfo = SerializationUtils.fromJsonString(taskInfoStr, TaskInfo.class); if (taskInfo.isTaskEnd()) { // 获取任务执行完毕,生成的内容 String data = taskInfo.getData(); Map map = SerializationUtils.fromJsonString(data, Map.class); data = map.get(KDFLOGTASK_CON).toString(); this.getView().showMessage(data); } } } } }
设置调度计划和调度作业
// 执行调度计划 JobDispatcherProxy proxy = new JobDispatcherProxy(); // 创建调度作业 JobInfo jobInfo = getJobInfo(); String jobId = proxy.dispatch(jobInfo); // 创建调度计划 PlanInfo planInfo = getPlanInfo(jobInfo); String planId = proxy.createPlan(planInfo); System.out.println("JobId: " + jobId + ", Number= " + jobInfo.getNumber()); System.out.println("PlanId: " + planId + ", Number= " + planInfo.getNumber()); System.out.println("TaskId: " + jobInfo.getTaskId()); getView().showMessage("JobId: " + jobId + ", Number: " + jobInfo.getNumber() + "\n & " + "PlanId: " + planId + ", Number: " + planInfo.getNumber() + "\n & " + "TaskId: " + jobInfo.getTaskId());
删除调度作业
JobDispatcherProxy proxy = new JobDispatcherProxy(); boolean success = proxy.deleteJob(getModel().getValue("kdec_inputid").toString()); if (success) { System.out.println("删除调度作业成功"); }
删除调度计划
JobDispatcherProxy proxy = new JobDispatcherProxy(); boolean success = proxy.deletePlan(getModel().getValue("kdec_inputid").toString()); if (success) { System.out.println("删除调度计划成功"); }
查询调度作业
JobDispatcherProxy proxy = new JobDispatcherProxy(); TaskInfo taskInfo = proxy.queryTask(getModel().getValue("kdec_inputid").toString()); System.out.println("JobId: " + taskInfo.getJobId());
创建调度任务类
package kd.bos.api.task;
import kd.bos.context.RequestContext;
import kd.bos.exception.KDException;
import kd.bos.schedule.executor.AbstractTask;
import kd.bos.logging.Log;
import kd.bos.logging.LogFactory;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import com.alibaba.fastjson.JSONObject;
public class KDFLogTask extends AbstractTask {
private static final Log log = LogFactory.getLog(KDFLogTask.class);
public static final String KDFLOGTASK_CON = "KDFLogTaskCallBackData";
@Override
public void execute(RequestContext requestContext, Map<String, Object> map) throws KDException {
Map<String, Object> resmap = new HashMap<>();
if (map.get("time") instanceof Integer) {
for (int i = 0; i < (Integer)map.get("time"); i++) {
try {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
System.out.println("打印日志测试:" + df.format(new Date()));// new Date()为获取当前系统时间
log.info("打印日志测试:" + df.format(new Date()));
resmap.put(KDFLOGTASK_CON, "KDFLogTask execute success");
} catch(Exception e) {
// 捕获到异常,反馈进度
feedbackProgress(i);
// 有异常就终止调度任务
if (isStop()) {
stop();
}
resmap.put(KDFLOGTASK_CON, "KDFLogTask execute fail");
}
}
}
feedbackCustomdata(resmap);
}
}
进入页面中,点击工具栏按钮,让代码中的调度计划开始创建和执行
四、效果图
查看调度作业/调度计划的列表,调度作业的执行情况
五、开发环境版本
六、注意事项
开发过程中遇到的问题场景和解决方案:
调度任务传递参数发生改变
在开发过程中,如果用户选择业务模式启动调度计划,传递DynamicObject为参数,在调度任务中,DynamicObject会被转为JsonObject。
如果这时候不做参数判断,直接把JsonObject传入SaveServiceHelper中进行保存操作,saveOpera方法调用之后,返回结果是保存失败的。
解决方案:把JsonObject构造成DynamicObject,或者用BusinessDataServiceHelper重新查一次。
七、参考资料
八、附件
附件包含补丁包和java源代码。
补丁包包含jar包和元数据包,请在mc中安装补丁包,如果是在开发平台里面直接导入,那么jar包不生效,需要复制代码,手动添加插件。
附件里的案例和本文的一些截图,在界面上略有差异,但实现方式是一致的。
插件文件:CreateJobPlanPlugIn.java,KDFLogTask.java已上传。
Java插件,代码创建调度计划和调度作业.zip(26.76KB)
推荐阅读