四. 创建一个工作流 Job
最后,我们需要介绍启动工作流的 Quartz Job 。当 Scheduler 调用了它,Quartz Job 就查找工作流的名字,并启动、运行相应的工作流。如果没有在 JobDataMap 中配置工作流的名字,Job 就会直接退出。
代码 14.13 显示了 WorkflowJob.
代码 14.13. Quartz WorkflowJob 设计为调用一个 OSWorkflowJob
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
public class WorkflowJob implements Job { static Log logger = LogFactory.getLog(WorkflowJob.class); /** * Called by the scheduler to execute a workflow */ public void execute(JobExecutionContext context) throws JobExecutionException { JobDataMap jobDataMap = context.getJobDataMap(); String wfName = jobDataMap.getString("WORKFLOW_NAME"); if (wfName != null && wfName.length() > 0) { try { executeWorkflow(wfName, jobDataMap); } catch (Exception ex) { logger.error(ex); throw new JobExecutionException(ex.getMessage()); } } else { logger.error("No Workflow name in JobDataMap"); } } protected void executeWorkflow(String workflowName, JobDataMap jobDataMap) throws WorkflowException { // Create the inputs for the workflow from JobDataMap Map workflowInputs = new HashMap(); Iterator iter = jobDataMap.keySet().iterator(); while (iter.hasNext()) { String key = (String) iter.next(); Object obj = jobDataMap.get(key); workflowInputs.put(key, obj); } // Create and execute the workflow Workflow workflow = new BasicWorkflow("someuser"); workflow.setConfiguration(new DefaultConfiguration()); long workflowId = workflow.initialize(workflowName, 1, workflowInputs); workflow.doAction(workflowId, 1, workflowInputs); } } |
这个工作流实际是在代码 14.13 的 executeWorkflow() 方法中启动的。一个新的工作流实例被创建了。它通过从 JobDataMap 中读取到的工作流名字来初始化的。工作流实例的 initialize() 和 doAction() 方法用了一个 java.util.Map 作为第三个参数。Map 中的值会通过 transientVars 参数传递到工作流的每一个函数中。如果你回头看看代码 14.11,你会看到 SCAN_DIR 是如何从 transientVars 抽取出来的。这个数据最初是在 JobDataMap 的。
本例中,我们从 Quartz Job 中获得 JobDataMap 并传值到工作流中。这是集成这两个框架的其中一种方式,简单也很直截。
最后,代码 14.14 显示了 Scheduler 的代码,它用于部署 WorkflowJob 并把工作流名称和 SCAN_DIR 存入到 JobDataMap 中。
代码 14.14. WorkflowJob 以正常方式部署,但必须存工作流名称到 JobDataMap 中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
public class WorkflowScheduler { static Log logger = LogFactory.getLog(WorkflowScheduler.class); public static void main(String[] args) { try { // Create and start the Scheduler Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); scheduler.start(); JobDetail jobDetail = new JobDetail("WorkflowJob", null, WorkflowJob.class); // Store the scan directory and workflow name JobDataMap dataMap = jobDetail.getJobDataMap(); dataMap.put("SCAN_DIR", "c:\\quartz-book\\input"); dataMap.put("WORKFLOW_NAME", "data-import"); // Create a simple trigger Trigger trigger = TriggerUtils.makeSecondlyTrigger(30000, -1); trigger.setName("WorkflowTrigger"); trigger.setStartTime(new Date()); // schedule the job scheduler.scheduleJob(jobDetail, trigger); } catch (SchedulerException ex) { logger.error(ex); } } } |
你看到代码 14.14 时不应感到惊讶。唯一要注意的事情是我们存储了工作流名称到 JobDataMap 中。和本章前面的 Job 串联例子一样,假如你想使用 JobInitializationPlugin,你可以简单的在文件中指定工作流的名称。
五. 小结
我们从本章中学到了什么?首先,Job 串联可由 Quartz 框架实现。你可用所介绍的两种方法,只是不借助于监听器实现的方式或许会让你有些头疼。我希望你带走的另一课是 Job 串联并非工作流。它也许看起来像工作流,你可能还对此存有疑虑,只要回到前面从头至尾构建一个自己的例子就能清楚了。一定要读一读 OSWorkflow 的文档并找出我们未提及的特性。你就能明白工作流比 Job 串联丰富多了。
最后,你应该了解到了同 Quartz 一同使用 OSWorkflow 实际是颇为简单的。所有要用到的就是几个二进制包,几个配置文件和一些工作流函数。把它们同工作流定义文件打包到一块,你就大功告成了。很快,你就将构建出一个可重用的函数库和一连串工作流来运行你的业务。不久,你就会有一个为之自豪的精致小巧的应用程序。
本文链接 https://yanbin.blog/quartz-job-scheduling-framework-14-4/, 来自 隔叶黄莺 Yanbin Blog
[版权声明] 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。
加油!!!
请教一个问题,JobDetail初始化时为什么是传Class而不是传实例化而的对象?传Class的问题在于Job类无法使用有参数的构造方法初始化。把初始化任务放在Job.execute()每次循环都执行效率有问题吧。比如
class MyJob implements Job {
private String config;
MyJob(String config) {
this.config = config;
}
}
class Example {
public static void main(String[] arg) {
......
JobDetail job = new JobDetail("job1", null, MyJob.class);
......
}
}
这样MyJob.config就没办法用构造函数设置了呀,有什么解决方法吗?
相信我在QQ里给你的解答你已经很清楚了,因为问及,不妨也在这里回答一下。因为 Quartz 设计为线程安全的,也就是每次执行 Job 都需要创建一个新的 Job 实例,所以你所希望的初始工作放在 Job 的构造方法或是 execute() 方法中效率都会是一样的,因此该考虑其他方法来进行你要的初始化操作。