四. Quartz 与 OSWorkflow 的集成
OSWorkflow 与 Quartz 集成的第一步是要改变关于 Job 的思维方式。当把 OSWorkflow 引入到你的 Quartz 应用时你需要以完全不同的方式来思考。那也不是说你当前的想法就是糟糕的或不正确的,只是与 Quartz 一同用工作流强迫你生发一些关于是什么组成 Job 的新的思维。你过去概念中的 Job 现成变成了一个 OSWorkflow 函数。你可以认为是你原有 Job 实质上存在的逻辑作为工作流中的步骤。你仍然需要使用 Quartz 的 Job,但是,当与 Quartz 框架集成工作流时,一个 Quartz Job 将用来初始化工作流。在工作流运行时,这个 Job 将会等待它直至结束。
在本章前面部分,当我们谈到串联 Job 时,每个 Job 代表了一个独立的任务。Jox X 执行后并完成一个任务,接着通知 Job Y 去执行一个有点关联却是独立的任务。在这两个任务间必须有一些依赖关系,否则你不能把它们链接在一起。
当加入工作流到这个流程中时,那些独立的 Job 就变身为工作流中的步骤了,而且你仅需要创建单个的 Job。当收到 Scheduler 的通知时,那个 Job 就起过工作流然后等待着工作流的完成。这其中有一些严格的寓意。好消息是,通过使用 OSWorkflow,你只需更少的 Quartz Job,因为早先的 Job 现在成了步骤(实际是函数)。坏消息是假如你有创建了大量的 Job,将要耗费一些工作量去转换 Job 到 OSWorkflow 的函数。
·下载和安装 OSWorkflow
你可以从它在 OpenSymphony 站点 http://www.opensymphony.com/osworkflow 的主页下载完整的发行版。从发布页的根目录获取到二进制版的 OSWorkflow 和其他第三方的库,它们在 <OSWORKFLOW_DISTRIBUTION>/lib/core 目录下。把这些二进制包扔到你的项目的 lib 目录中。这应当和 Quartz 二进制包所在的同一目录。
你必须建立两个配置文件并放置到你的 classes 目录中。第一个你需要创建的配置文件叫做 osworkflow.xml。这个文件在 OSWorkflow 启动并配置运行时环境时被加载。我们例子中的该文件如代码 14.8 中显示。
代码 14.8. osworkfllow.xml 文件用于配置 OSWorkflow 的运行时环境
| 1 2 3 4 5 6 7 | <osworkflow>   <persistence     class="com.opensymphony.workflow.spi.memory.MemoryWorkflowStore"/>   <factory class="com.opensymphony.workflow.loader.XMLWorkflowFactory">     <property name="resource" value="workflows.xml" />   </factory> </osworkflow> | 
假如你再看看 OSWorkflow 的文档,你会发现你可以从多种类型的持久性存储和工作流工厂中作出选择。在代码 14.8 中所用的都是最简单的并且为我们的例子工作的很好的。
配置在代码 14.8 中的工作流工厂类叫做 XMLWorkflowFactory,它包括一个称为 resource 的属性。XMLWorkflowFactory 用于加载一个包含了所有工作流的资源文件。在这里的 resource 属性的值是 workflows.xml。只要你想要多少个,就允许你可以有多少个不同的工作流。每个工作流驻留在一个单独的 XML 文件中,但是你需要以某种方式指定可用的工作流列表给 OSWorkflow 引擎。因为我们已经指定工厂为 XMLWorkflowFactory,所以框架会查看 workflows.xml 文件来得到可用的工作流并加载它们。代码 14.9 显示了我们例子里的 workflows.xml 文件。
代码 14.9. workflows.xml 文件定义了应用可用的工作流列表
| 1 2 3 4 5 6 | <workflows>   <workflow     name="data-import"     type="resource"     location="data-import-workflow.xml"/> </workflows> | 
代码 14.9 只列了一个工作流:data-import,它将在我们启动工作流时用作参考。实际的工作流定义是破存储在文件 data-import-workflow.xml 中的。代码 14.10 显示了 data-import 工作流。
代码 14.10. data-import 工作流被定义在一个 XML 文件中
| 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 45 46 47 48 49 50 51 52 53 54 55 56 | <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE workflow PUBLIC                  "-//OpenSymphony Group//DTD OSWorkflow 2.7//EN"                  "http://www.opensymphony.com/osworkflow/workflow_2_7.dtd"> <workflow>     <initial-actions>         <action id="1" name="Start Workflow">             <results>                 <unconditional-result old-status="Finished" status="Queued"                     step="1" />             </results>         </action>     </initial-actions>     <steps>         <step id="1" name="Read Files">             <actions>                 <action id="2" name="Get the files" auto="true">                     <pre-functions>                         <function type="class">                             <arg name="class.name">                                org.cavaness.quartzbook.chapter14.ReadFileFunction                             </arg>                         </function>                     </pre-functions>                     <results>                         <unconditional-result old-status="Finished"                             status="Underway" step="2" />                     </results>                 </action>             </actions>         </step>         <step id="2" name="Send Email Notification">             <actions>                 <action id="3" name="Get the files" auto="true">                     <pre-functions>                         <function type="class">                             <arg name="class.name">                                org.cavaness.quartzbook.chapter14.SendEmailFunction                             </arg>                         </function>                     </pre-functions>                     <results>                         <unconditional-result old-status="Finished"                             status="Underway" step="3" />                     </results>                 </action>             </actions>         </step>         <step id="3" name="finished" />     </steps> </workflow> | 
定义在代码 14.10 的工作流包含两个步骤:“读文件” 和 "发 e-mail 通知"。当工作流启动后,initial-actions 块被执行,继而它调用步骤 1。当进入到步骤 1 后,org.cavaness.quartzbook.chapter14.ReadFileFunction 的 execute() 方法就被调用。代码 14.11 显示了这一函数。
代码 14.11. 工作流引擎在步骤 1 其间调用 ReadFileFunction
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | public class ReadFileFunction implements FunctionProvider {      static Log logger = LogFactory.getLog(ReadFileFunction.class);      public void execute(Map transientVars, Map args, PropertySet ps)                throws WorkflowException {           logger.info("Entered " + this.getClass().getName());           // Read the files and process the data           String dirName = (String)transientVars.get("SCAN_DIR");           if ( dirName == null ) {                throw new InvalidInputException( "Scan dir not set" );           }           File dir = new File( dirName );           File[] files = dir.listFiles();           int fileCount = files.length;           ps.setInt( "FILE_COUNT", fileCount );      } } | 
当 ReadFileFunction 的 execute() 方法完成后,工作流会转换到步骤 2。在步骤 2,org.cavaness.quartzbook.chapter14.SendEmailFunction 被调用并获得机会执行。SendEmailFunction 显示在代码 14.12 中。
代码 14.12. SendEmailFunction 在工作流的步骤 2 期间被调用
| 1 2 3 4 5 6 7 8 9 10 11 12 13 | public class SendEmailFunction implements FunctionProvider {      static Log logger = LogFactory.getLog(SendEmailFunction.class);      public void execute(Map transientVars, Map args, PropertySet ps)                throws WorkflowException {           logger.info("Entered " + this.getClass().getName());           int fileCount = ps.getInt("FILE_COUNT");           logger.info( "File count " + fileCount );           // Email creation code not shown      } } | 
显然我们漏下了这个函数的实例;也没有对此多加以说明。我们假定你知道如何使用 JavaMail 发送电子邮件。
本文链接 https://yanbin.blog/quartz-job-scheduling-framework-14-3/, 来自 隔叶黄莺 Yanbin Blog
[版权声明]  本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。
 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。