Quartz 定时任务使用 —— Web项目监听中调用(二)

Quartz 定时任务使用

在Web应用中使用Quartz

Quartz也常用在Web应用中,常见的是交由Spring托管的形式,但这里并非介绍这个。这里介绍Quartz在Web应用中单独使用。

一般来说,Web应用启动时,应注册已经确定的定时任务;一些动态的、未确定触发时间的定时任务,后续可通过静态的Scheduler注册。

这里使用监听器在应用启动时注册,记得在web.xml注册这个监听器哦;在关闭Web应用时,也要相应的注销定时任务

其他配置文件、Java类与上例子相同,这里只是注册定时任务的地方换成此监听器了。

package com.anson.listener;

import com.anson.example1.HelloJob;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

/**
 * 自定义一个应用监听器
 */
public class ApplicationContextListener implements ServletContextListener {
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    public static Scheduler scheduler = null;

    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        this.logger.info("Web应用开始...");

        /* 注册定时任务 */
        try {
            // 获取Scheduler实例
            scheduler = StdSchedulerFactory.getDefaultScheduler();
            scheduler.start();

            // 具体任务
            JobDetail job = JobBuilder.newJob(HelloJob.class).withIdentity("job1", "group1").build();

            // 触发时间点
            SimpleScheduleBuilder simpleScheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
                    .withIntervalInSeconds(5).repeatForever();
                    
            Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1")
                    .startNow().withSchedule(simpleScheduleBuilder).build();

            // 交由Scheduler安排触发
            scheduler.scheduleJob(job, trigger);

            this.logger.info("调度器开始注册:The scheduler register...");
        } catch (SchedulerException se) {
            logger.error(se.getMessage(), se);
        }
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        this.logger.info("Web应用停止...");

        /* 注销定时任务 */
        try {
            // 关闭Scheduler
            scheduler.shutdown();

            this.logger.info("调度器已关闭:The scheduler shutdown...");
        } catch (SchedulerException se) {
            logger.error(se.getMessage(), se);
        }
    }
}

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <!-- 加入自定义监听器 -->
    <listener>
        <listener-class>com.anson.listener.ApplicationContextListener</listener-class>
    </listener>

</web-app>

把Web项目在Tomcat中运行测试

[INFO] 09 九月 06:19:56.121 下午 RMI TCP Connection(2)-127.0.0.1 [com.anson.listener.ApplicationContextListener]
Web应用开始...
[INFO] 09 九月 06:19:56.146 下午 RMI TCP Connection(2)-127.0.0.1 [org.quartz.impl.StdSchedulerFactory]
Using default implementation for ThreadExecutor
[INFO] 09 九月 06:19:56.160 下午 RMI TCP Connection(2)-127.0.0.1 [org.quartz.core.SchedulerSignalerImpl]
Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
[INFO] 09 九月 06:19:56.161 下午 RMI TCP Connection(2)-127.0.0.1 [org.quartz.core.QuartzScheduler]
Quartz Scheduler v.2.2.3 created.
[INFO] 09 九月 06:19:56.161 下午 RMI TCP Connection(2)-127.0.0.1 [org.quartz.simpl.RAMJobStore]
RAMJobStore initialized.
[INFO] 09 九月 06:19:56.162 下午 RMI TCP Connection(2)-127.0.0.1 [org.quartz.core.QuartzScheduler]
Scheduler meta-data: Quartz Scheduler (v2.2.3) 'MyScheduler' 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 3 threads.
  Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.
[INFO] 09 九月 06:19:56.162 下午 RMI TCP Connection(2)-127.0.0.1 [org.quartz.impl.StdSchedulerFactory]
Quartz scheduler 'MyScheduler' initialized from default resource file in Quartz package: 'quartz.properties'
[INFO] 09 九月 06:19:56.162 下午 RMI TCP Connection(2)-127.0.0.1 [org.quartz.impl.StdSchedulerFactory]
Quartz scheduler version: 2.2.3
[INFO] 09 九月 06:19:56.162 下午 RMI TCP Connection(2)-127.0.0.1 [org.quartz.core.QuartzScheduler]
Scheduler MyScheduler_$_NON_CLUSTERED started.
[INFO] 09 九月 06:19:56.168 下午 RMI TCP Connection(2)-127.0.0.1 [com.anson.listener.ApplicationContextListener]
调度器开始注册:The scheduler register...
Hello Job
[DEBUG] 09 九月 06:19:56.177 下午 MyScheduler_Worker-1 [com.anson.example1.HelloJob]
com.anson.example1.HelloJob trigger...
[2017-09-09 06:19:56,206] Artifact quartz_example:war exploded: Artifact is deployed successfully
[2017-09-09 06:19:56,206] Artifact quartz_example:war exploded: Deploy took 643 milliseconds
Hello Job
[DEBUG] 09 九月 06:20:01.168 下午 MyScheduler_Worker-2 [com.anson.example1.HelloJob]
com.anson.example1.HelloJob trigger...
09-Sep-2017 18:20:05.276 信息 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [/Users/liurenkui/myLibrary/apache-tomcat-8.5.15/webapps/manager]
09-Sep-2017 18:20:05.305 信息 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/Users/liurenkui/myLibrary/apache-tomcat-8.5.15/webapps/manager] has finished in [28] ms
Hello Job
[DEBUG] 09 九月 06:20:06.167 下午 MyScheduler_Worker-3 [com.anson.example1.HelloJob]
com.anson.example1.HelloJob trigger...
...
...
... 省略大部分web应用开启时的任务输出重复日志 ...
...
...

Hello Job
[DEBUG] 09 九月 06:23:26.170 下午 MyScheduler_Worker-1 [com.anson.example1.HelloJob]
com.anson.example1.HelloJob trigger...
/Users/liurenkui/myLibrary/apache-tomcat-8.5.15/bin/catalina.sh stop
09-Sep-2017 18:23:26.783 信息 [main] org.apache.catalina.core.StandardServer.await A valid shutdown command was received via the shutdown port. Stopping the Server instance.
09-Sep-2017 18:23:26.783 信息 [main] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["http-nio-8080"]
09-Sep-2017 18:23:26.840 信息 [main] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["ajp-nio-8009"]
09-Sep-2017 18:23:26.894 信息 [main] org.apache.catalina.core.StandardService.stopInternal Stopping service [Catalina]
[INFO] 09 九月 06:23:26.900 下午 localhost-startStop-2 [com.anson.listener.ApplicationContextListener]
Web应用停止...
[INFO] 09 九月 06:23:26.900 下午 localhost-startStop-2 [org.quartz.core.QuartzScheduler]
Scheduler MyScheduler_$_NON_CLUSTERED shutting down.
[INFO] 09 九月 06:23:26.900 下午 localhost-startStop-2 [org.quartz.core.QuartzScheduler]
Scheduler MyScheduler_$_NON_CLUSTERED paused.
[INFO] 09 九月 06:23:26.900 下午 localhost-startStop-2 [org.quartz.core.QuartzScheduler]
Scheduler MyScheduler_$_NON_CLUSTERED shutdown complete.
[INFO] 09 九月 06:23:26.900 下午 localhost-startStop-2 [com.anson.listener.ApplicationContextListener]
调度器已关闭:The scheduler shutdown...
09-Sep-2017 18:23:26.911 信息 [main] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["http-nio-8080"]
09-Sep-2017 18:23:26.913 信息 [main] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["ajp-nio-8009"]
09-Sep-2017 18:23:26.917 信息 [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["http-nio-8080"]
09-Sep-2017 18:23:26.917 信息 [main] org.apache.c

注,如果你在Eclipse中调试,可能发现无法看到contextDestroyed方法的执行,请注意用Stop方式(图一)关闭应用,而不是Terminate(图二)。

图一

屏幕快照 2017-09-09 18.26.13.png

图二

屏幕快照 2017-09-09 18.26.17.png

如何不重复执行任务?

如果仔细阅读代码你会发现这块的代码

// 触发时间点
SimpleScheduleBuilder simpleScheduleBuilder = SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(5).repeatForever();

其中,最后结尾的是repeatForever()方法,这个方法的意思表示永远执行。

如果删除这行代码,那么job任务,也就只会执行一次,任务就挂起了,直到调度器关闭。

也可以自定义重复执行的次数,使用withRepeatCount(10)方法,10表示执行了10次


未经允许请勿转载:程序喵 » Quartz 定时任务使用 —— Web项目监听中调用(二)

点  赞 (2) 打  赏
分享到: