quartz实际使用

前言

之前写了一个quart指南,事后自己看都觉得十分的凌乱,不知从何下手,于是决定再写一篇,争取比上一篇写的好。

quartz优势

quartz实现了监听时钟,定时执行
quartz实现了持久化任务到数据库,并从数据库中读取数据定时执行
优化执行效率,多线程管理,配置线程池
等等

从一个实际的例子入手

需求
提供接口,实现
1. 调用可以立即执行一个service(其实这个不是quartz的优势)
2. 调用可以周期性执行一个service ,如果项目停掉,再重启可重新启动对这个servcie的调用
【注: 由于我用在ofbiz上,这个service是指ofbiz中的service,其实就是指一个具体实现某个业务的java方法,可替换修改】

分析

  1. 项目启动时应该吧执行job,监测trigger,的scheduler 启动起来(job和trigger分别是任务和触发器,不在详述,上一篇有说明)
  2. 启动后应该有两个方法供我们调用,分别实现上面的立即执行和周期性执行
  3. 配置quartz的数据库,以持久化job和trigger的数据,方便下次调用

实现
准备工作,官网下载quartz包,将里面的jar包导入到项目

1.在web.xml中配置了启动servlet,来启动scheduler

  <servlet>
        <servlet-name>SchedulerServlet</servlet-name>
        <servlet-class>cn.metasolo.manager.StartScheduler</servlet-class>
        <load-on-startup>1</load-on-startup>
  </servlet>

StartScheduler启动和停止

//继承HttpServlet 重写init()和destroy()方法
public class StartScheduler extends HttpServlet {

    /**
     * start quartz scheduler
     */
    private static Logger logger =LogManager.getLogger("quartz");
    private static final long serialVersionUID = 1L;
    public void init(){
        SchedulerManager.start();
        logger.info("[quart scheduler start]");
    }
    public void destroy(){
        SchedulerManager.shutdown();
        logger.info("[quart scheduler shutdown]");
    }
}

2.创建SchedulerManager来提供api
代码看起来有点长,只是包含了4个方法1个内部类,方法用途分别是:启动,停止,立即执行某个service,周期性执行某个service,内部类是用于实现Job的。
注:这里的delegator 和dispatcher 是ofbiz 中的一些工具类,你在用的时候完全可以去掉,把serviceName 想办法换成你的java方法调用。

import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;
import static org.quartz.CronScheduleBuilder.cronSchedule;
import java.util.Map;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.ofbiz.entity.Delegator;
import org.ofbiz.entity.DelegatorFactory;
import org.ofbiz.service.GenericServiceException;
import org.ofbiz.service.LocalDispatcher;
import org.ofbiz.service.ServiceContainer;
import org.quartz.CronTrigger;
import org.quartz.Job;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleTrigger;
import org.quartz.impl.StdSchedulerFactory;


public class SchedulerManager {
    private static Logger logger =LogManager.getLogger("quartz");

    private static Scheduler sched;
    private static JobDetail job;
    private static CronTrigger trigger;
    private static Delegator delegate;
    private static LocalDispatcher dispatcher;

    public static void start() {
        try {
            SchedulerFactory sf = new StdSchedulerFactory();
            try {
                sched=sf.getScheduler();
                delegate = DelegatorFactory.getDelegator("default");
                dispatcher = ServiceContainer.getLocalDispatcher(delegate.getDelegatorName(), delegate);
            } catch (SchedulerException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            if(sched!=null&&!sched.isStarted()){
                sched.start();
            }
        } catch (SchedulerException e) {

            e.printStackTrace();
        }

    }

    public static void shutdown() {
        try {
            if(sched!=null&&!sched.isShutdown()){
                sched.shutdown();;
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        }


    }
    /**
     * addJobRunCyclicity
     * @author xkl
     * @param serviceName
     * @param maps
     * @param cyclicity
     * <b>execute cyclicity</b>
     */
    public static void addJobRunCyclicity(String serviceName,Map<String, Object> maps,String cyclicity){
        //如果已经存在任务列表里,不再添加
        JobKey key = new JobKey(serviceName, "serviceGroup");
        try {
            if(sched.checkExists(key)){

                logger.info("This job is exists!add failed!");
                return;
            }
        } catch (SchedulerException e1) {
            logger.error("Check job key exists error:"+e1.getMessage());
        }
        job = newJob(ServiceJob.class).withIdentity(serviceName, "serviceGroup").build();
        job.getJobDataMap().put("conditions", maps);
        trigger = newTrigger().withIdentity("trigger_"+serviceName,"serviceGroup").startNow().withSchedule(cronSchedule(cyclicity)).build();
        try {
            sched.scheduleJob(job, trigger);
            logger.info("[execute service "+serviceName+" by  cyclicity of "+ cyclicity+"]");
        } catch (SchedulerException e) {
            logger.error("Add scheduler Job error:"+e.getMessage());
        }
    }
    /**
     * addJobRunImmediately
     * @param serviceName
     * @param maps
     *<p> execute immediately</p>
     */
    public static void addJobRunImmediately(String serviceName,Map<String, Object> maps){
        //如果已经存在任务列表里,不再添加
        JobKey key = new JobKey(serviceName, "serviceGroup");
        try {
            if(sched.checkExists(key)){
                logger.info("This job is exists!add failed!");
                return;
            }
        } catch (SchedulerException e1) {
            logger.error("Check job key exists error:"+e1.getMessage());
        }
        job = newJob(ServiceJob.class).withIdentity(serviceName, "serviceGroup").build();
        job.getJobDataMap().put("conditions", maps);
        SimpleTrigger trigger = (SimpleTrigger) newTrigger().withIdentity("trigger_"+serviceName, "group1").startNow().build();
        try {
            sched.scheduleJob(job, trigger);
            logger.info("[execute service "+serviceName+" immediately]");
        } catch (SchedulerException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    public static class ServiceJob implements Job{
        @Override
        public void execute(JobExecutionContext context) throws JobExecutionException {
            try {
                JobKey jobKey = context.getJobDetail().getKey();
                Map<String,Object> maps = context.getJobDetail().getJobDataMap();
                Map<String,Object> conditions = null;

                if(maps.get("conditions")!=null){
                    conditions = (Map<String,Object>)maps.get("conditions");
                }

                dispatcher.runSync(jobKey.getName(),conditions);
                logger.info("执行了ServiceJob任务");
            } catch (GenericServiceException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }

    }
}

3.如何持久化:持久化需要配置数据库了,quart包中的 \quartz-2.2.3\docs\dbTables 目录中有初始化创建各种数据表的 sql 语句,根据你的需要创建不同的数据库以及 数据库表
我用的是tables_postgres.sql 不贴了,自己打开找一下吧

生成表后还需要配置一下quartz.properties配置文件:(名字不能改,放在classpath下)


#============================================================================
# Configure Main Scheduler Properties  
#============================================================================

org.quartz.scheduler.instanceName: SchedulerManager
org.quartz.scheduler.instanceId: AUTO

org.quartz.scheduler.skipUpdateCheck: true

#============================================================================
# Configure ThreadPool  
#============================================================================

org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount: 5
org.quartz.threadPool.threadPriority: 5

#============================================================================
# Configure JobStore  
#============================================================================

org.quartz.jobStore.misfireThreshold: 60000

#org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore

org.quartz.jobStore.class: org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass: org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
org.quartz.jobStore.useProperties: false
org.quartz.jobStore.dataSource: myDS
org.quartz.jobStore.tablePrefix: QRTZ_
org.quartz.jobStore.isClustered: false


#============================================================================
# Configure Datasources  
#============================================================================

org.quartz.dataSource.myDS.driver: org.postgresql.Driver
org.quartz.dataSource.myDS.URL: jdbc:postgresql://localhost/ErpQuartz
org.quartz.dataSource.myDS.user:****
org.quartz.dataSource.myDS.password:***
org.quartz.dataSource.myDS.maxConnections: 5

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值