【问题标题】:quartz scheduler using QuartzInitializerServlet使用 QuartzInitializerServlet 的石英调度器
【发布时间】:2014-10-15 15:42:38
【问题描述】:

我遇到了quartz 2.x 的所有示例,但我没有得到一个明确的示例来说明如何使用Quartz Initializer Servlet 来初始化quartz 调度程序。

每个人都声明一个 Servlet 并在属性文件中写入一些东西。 但是没有人告诉如何使用这个 Quartz Initializer Servlet。

如何配置我的调度程序以及何时调用调度程序的 start 方法,我特别提出这个问题,因为我在一些博客中读到,即使我们没有显式调用 start 方法,servlet 也会负责调用它!! 这是真的吗? 任何人都可以通过示例工作来举例清楚地解释,而不是从谷歌复制粘贴quartz.properties

因为这个主题有很多未解决的问题?

对不起,如果我拼错了。

【问题讨论】:

    标签: jakarta-ee servlets quartz-scheduler


    【解决方案1】:

    嗨,quartz 是一个很棒的库,但是关于如何在 web 项目上实现的例子很少。大多数例子都是在 spring 上,但它们太复杂了。所以经过多次试验和错误,我终于能够在我的Web 应用程序。我尝试过 Quartz RamJobStore、XmlJob(在 xml 文件中存储作业和触发器)和持久作业(在 mysql 数据库中存储作业和触发器)。关于石英的最好的事情是对于这三种不同的方法,我不需要做任何额外的事情,我的意思是工作和触发器创建逻辑对于所有这三种方法都保持不变,但是我们只需要配置我们的属性文件以使其工作。

    所以我已经在 java web 应用程序中实现了quartz。我使用 net-beans ide。下面是让你开始的代码。在这个例子中,我使用 jdbcjobstore,这意味着我正在创建作业和触发器并将它们存储在 MySQL 中,这样即使我的系统重新启动作业和触发器也可以作为它们保存在持久存储 (MySQL) 中。

    1> 首先我在 net-beans 中创建了简单的 java web 项目。

    2> 从我从那里下载的“quartz-2.2.1”包中的 lib 文件夹中添加所有 jars 到你的 net-beans 项目和 MySQL 连接器 jar 中。

    3> 配置 log4j:为此创建 log4j.properties 文件并添加以下行:

    log4j.rootLogger=INFO, stdout
    log4j.logger.org.quartz=DEBUG
    log4j.appender.stdout=org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n
    

    ** 将此 log4j.properties 文件放在:

    NetBeansProjects
        ->QurtzWebApp
            ->src
                ->java
                    ->MySomePackage
                        ->HelloWorldJob.java
                    log4j.properties
                    quartz.properties
    

    4> 在 net-beans 项目窗口的项目层次结构树中,右键单击 source packages 创建 HelloWorldJob 类。

    我的 HelloWorldJob 类包含以下代码:

    package MySomePackage;
    
    import java.io.BufferedWriter;
    import java.io.File;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.net.URL;
    import java.util.Date;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    import org.quartz.Job;
    import org.quartz.JobExecutionContext;
    import org.quartz.JobExecutionException;
    
    public class HelloWorldJob implements Job {
    @Override
    public void execute(JobExecutionContext context)throws JobExecutionException {   
            try
            {
                String content = "Quartz 2 example @ ["+new Date()+"]";
                File file = new File("C:\\DemoMsg.txt");
    
                if (!file.exists()) {
                   file.createNewFile();
                }
    
                FileWriter fw = new FileWriter(file.getAbsoluteFile(),true);
                BufferedWriter bw = new BufferedWriter(fw);
                bw.write(content);
                bw.close();
            }
            catch(Exception ex)
            {
                System.out.println("ex = "+ex.getMessage());
            }
        }
    }
    

    上面的代码只是在 c 驱动器中创建 DemoMsg 文本文件,如果尚未创建,并在定义的触发间隔将消息定义写入内容变量。例如,如果我创建了每 5 分钟执行一次的触发器,那么您应该在每 5 分钟后看到此消息文本文件中的最小间隔。我特意添加了日期值,以便您可以在这种情况下每 5 分钟后验证文件是否按照触发计划写入。

    5>在第 3 步指定的位置创建 quartz.properties 文件并在其中写入以下代码:

    org.quartz.scheduler.instanceName = MY_SCHEDULER
    org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
    org.quartz.threadPool.threadCount = 4
    org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
    
    org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
    org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
    org.quartz.jobStore.dataSource = MyDataStore
    org.quartz.jobStore.tablePrefix = qrtz_
    org.quartz.jobStore.misfireThreshold = 60000
    org.quartz.jobStore.isClustered = false
    
    org.quartz.dataSource.MailDataStore.driver = com.mysql.jdbc.Driver
    org.quartz.dataSource.MailDataStore.URL = jdbc:mysql://localhost:3306/quartz
    org.quartz.dataSource.MailDataStore.user = yourdbusername
    org.quartz.dataSource.MailDataStore.password = yourdbpassword
    org.quartz.dataSource.MailDataStore.maxConnections = 20
    

    在mysql中创建quartz数据库,创建quartz表。创建表的代码在quartz-2.2.1\docs\dbTables\tables_mysql.sql目录下,导入这个sql文件即可。

    5> 创建 web.xml 文件并添加以下条目:

    <listener>
    <listener-class>
    org.quartz.ee.servlet.QuartzInitializerListener
    </listener-class>
    </listener>
    

    6> 然后创建简单的 jsp 页面,其中包含表格和表单,只接受来自用户的 jobid jobname cro 表达式并将其发布到另一个页面。

    7> 发布表单详细信息的jsp文件代码如下:

        type=request.getParameter("type");
    
        if(type.equals("createSchedule"))
        {
            String jobName="",jobDesc="",jobData="",cronVal="";
    
            jobName=request.getParameter("txtJobName");
            jobDesc=request.getParameter("txtJobDesc");
            jobData=request.getParameter("txtJobData");
            cronVal=request.getParameter("txtCronExrp");
    
            SchedulerFactory sf = new StdSchedulerFactory();
            Scheduler sched = sf.getScheduler();
            System.out.println("------- Initialization Complete --------");
    
            System.out.println("------- Intitalizing Jobs ----------------");
    
            JobKey jobKey = new JobKey(""+jobName, "JobGroupName");
            JobDetail jobDetail = JobBuilder.newJob(HelloWorldJob.class).withIdentity(jobKey).build();
            jobDetail.getJobDataMap().put("jobData",""+jobData);
            jobDetail.getJobDataMap().put("jobDesc",""+jobDesc);
    
            System.out.println("------- Intitalizing Triggers ----------------");
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(""+jobName+"_"+"Trigger", "TriggerGroup").withSchedule(CronScheduleBuilder.cronSchedule(""+cronVal)).build();
    
    
            System.out.println("------- Starting Scheduler ----------------");
    
            JobKey jk=new JobKey(""+jobName);
            TriggerKey tk=new TriggerKey (""+jobName+"_"+"Trigger");
            JobDetail Searchjob = sched.getJobDetail(jk);
            System.out.println("Job found = " + Searchjob);
    
             //Check if job already exist
            if (Searchjob == null) // job not exist
            {
                Date ft = sched.scheduleJob(jobDetail, trigger);
                System.out.println(sched.getSchedulerName());
                System.out.println(jobDetail.getKey() + " has been scheduled to run at: " + ft+ " and repeat based on expression: " + trigger.getCronExpression() );
    
            } 
            else //job exist
            {
                sched.rescheduleJob(tk, trigger);
            }
    
            sched.start();
    
            %>Schedule Created Successfully !<%
        }
    

    8> 我传递参数来检查我是否要创建、编辑或删除作业。 对于编辑和删除作业,您需要在创建作业时定义的作业 ID。

    我知道答案太长了,但我希望它能在你的场景中帮助你。

    【讨论】:

      【解决方案2】:

      QuartzInitializerServlet 将为您启动调度程序,并在 ServletContext 中放置一个 StdSchedulerFactory。

      检索已经启动的调度程序:

      ServletContext ctx = request.getServletContext();
      StdSchedulerFactory factory = (StdSchedulerFactory) ctx.getAttribute( QuartzInitializerServlet.QUARTZ_FACTORY_KEY);  
      Scheduler scheduler = factory.getScheduler();
      

      其中“请求”是当前的 HTTPServletRequest。

      可以在类路径或 WEB-INF 中使用“属性”文件配置调度程序(我没有对此进行测试)。配置文件的名称必须在 web.xml 中指定为 QuartzInitializerServlet 的 init-param:

      <servlet>
            <servlet-name>QuartzInitializer</servlet-name>
            <servlet-class>org.quartz.ee.servlet.QuartzInitializerServlet</servlet-class>
              <init-param>
               <param-name>config-file</param-name>
               <param-value>quartz.properties</param-value>
            </init-param>
            <init-param>
              <param-name>shutdown-on-unload</param-name>
              <param-value>true</param-value>
            </init-param>
            <load-on-startup>2</load-on-startup>
      </servlet>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-11-04
        • 1970-01-01
        • 2020-09-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多