spring之quarze使用

一、依赖

<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.3.0</version>
</dependency>

 

二、一个类(实现job接口的类),三个实例(JobDetail、Trigger、Scheduler)

1、实现Job接口的类(HelloJob),实现exexute方法,编写具体处理逻辑
 
2、JobDetail jobDetail = JobBuilder.newJob(HelloJob.class).withIndentity("myJob","group1").build();
 
3、Trigger  trigger = TriggerBuilder.newTrigger().withIdentity("myJob","group1").startNow().withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(2).repeatForever()).build();
 
4、SchedulerFactory sfact = new StdSchedulerFactory();
Scheduler scheduler = sfact.getScheduler();
scheduler.start();
scheduler.scheduleJob(jobDetail ,trigger );  
 

三、数据传输

1、传入:JobDetail 、Trigger实例中使用.usingJobData("key","value") 传入
2、获取:
实现job接口的类中使用
2.1、context.getJobDetail().getJobDataMap();
context.getTrigger ().getJobDataMap();获取
2.2、也可以使用context.getMergedJobDataMap()来获取,如果key相同,trigger中的值会覆盖jobDetail中的值
2.3、定义与key相同的属性,添加get、set方法
 

四、trigger

1、属性
JobKey
StartTime
EndTime 
 
2、SimpleTriggerImpl
SimpleTrigger trigger = (SimpleTrigger)TriggerBuilder.newTrigger().withIdentity("myJob","group1").startNow().withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(2).repeatForever()).build(); 
 
3、CronTriggerImpl 基于日历的作业调试器
CronTriggertrigger = ( CronTrigger)TriggerBuilder.newTrigger().withIdentity("myJob","group1").withSchedule(CronScheduleBuilder.cronSchedule("* * * * * ? *").build();  //第七位是周,?表示不用管
 

五、Scheduler由SchedulerFactory创建,(SchedulerFactory有两个实现类:StdSchedulerFactory(重点),DirectSchedulerFactory)

1、Scheduler的创建:
1.1、SchedulerFactory sfact = new StdSchedulerFactory();
Scheduler scheduler = sfact.getScheduler();
1.2、 DirectSchedulerFactory  factory = DirectSchedulerFactory .getInstance ();
Scheduler scheduler =factory.sfact.getScheduler();
 
2、Scheduler的方法:
void start();//启动
Data shedulerJob(jobDetail,trigger);//将jobDetail与trigger关联起来,返回最近将要执行时间
void standby();//挂起,可以通过start();再次唤醒,唤醒后会将因挂起而没有执行的任务进行补回
void shutdown(bealoon);//关闭,如果true,则会等正在执行的任务执行完后再关闭,如果为false则是立马关闭(但正在执行的job还是会执行下去)
bealoon isShutdown();//返回sheduler是否已关闭
 
3、QuartzProperties文件
StdSchedulerFactory是通过读取quartz.properties文件配置信息进行初始化的
如果工程资源目录是没有quartz.properties配置文件,它就会去读quartzJar包中的quartz.properties
配置文件内容包括
3.1、调试器属性
3.2、线程池属性
3.3、作业存储设置
3.4、插件配置
# ===========================================================================
# Configure Main Scheduler Properties 调度器属性
# ===========================================================================
org.quartz.scheduler.instanceName: DefaultQuartzScheduler
org.quartz.scheduler.instanceid:AUTO
org.quartz.scheduler.rmi.export: false
org.quartz.scheduler.rmi.proxy: false
org.quartz.scheduler.wrapJobExecutionInUserTransaction: false
# ===========================================================================  
# Configure ThreadPool 线程池属性  
# ===========================================================================
#线程池的实现类(一般使用SimpleThreadPool即可满足几乎所有用户的需求)
org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
#指定线程数,至少为1(无默认值)(一般设置为1-100直接的整数合适)
org.quartz.threadPool.threadCount: 10
#设置线程的优先级(最大为java.lang.Thread.MAX_PRIORITY 10,最小为Thread.MIN_PRIORITY 1,默认为5)
org.quartz.threadPool.threadPriority: 5
#设置SimpleThreadPool的一些属性
#设置是否为守护线程
#org.quartz.threadpool.makethreadsdaemons = false
#org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true
#org.quartz.threadpool.threadsinheritgroupofinitializingthread=false
#线程前缀默认值是:[Scheduler Name]_Worker
#org.quartz.threadpool.threadnameprefix=swhJobThead;
# 配置全局监听(TriggerListener,JobListener) 则应用程序可以接收和执行 预定的事件通知
# ===========================================================================
# Configuring a Global TriggerListener 配置全局的Trigger监听器
# MyTriggerListenerClass 类必须有一个无参数的构造函数,和 属性的set方法,目前2.2.x只支持原始数据类型的值(包括字符串)
# ===========================================================================
#org.quartz.triggerListener.NAME.class = com.swh.MyTriggerListenerClass
#org.quartz.triggerListener.NAME.propName = propValue
#org.quartz.triggerListener.NAME.prop2Name = prop2Value
# ===========================================================================
# Configuring a Global JobListener 配置全局的Job监听器
# MyJobListenerClass 类必须有一个无参数的构造函数,和 属性的set方法,目前2.2.x只支持原始数据类型的值(包括字符串)
# ===========================================================================
#org.quartz.jobListener.NAME.class = com.swh.MyJobListenerClass
#org.quartz.jobListener.NAME.propName = propValue
#org.quartz.jobListener.NAME.prop2Name = prop2Value
# ===========================================================================  
# Configure JobStore 存储调度信息(工作,触发器和日历等)
# ===========================================================================
# 信息保存时间 默认值60秒
org.quartz.jobStore.misfireThreshold: 60000
#保存job和Trigger的状态信息到内存中的类
org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore
# ===========================================================================  
# Configure SchedulerPlugins 插件属性 配置
# ===========================================================================
# 自定义插件  
#org.quartz.plugin.NAME.class = com.swh.MyPluginClass
#org.quartz.plugin.NAME.propName = propValue
#org.quartz.plugin.NAME.prop2Name = prop2Value
#配置trigger执行历史日志(可以看到类的文档和参数列表)
org.quartz.plugin.triggHistory.class = org.quartz.plugins.history.LoggingTriggerHistoryPlugin  
org.quartz.plugin.triggHistory.triggerFiredMessage = Trigger {1}.{0} fired job {6}.{5} at: {4, date, HH:mm:ss MM/dd/yyyy}  
org.quartz.plugin.triggHistory.triggerCompleteMessage = Trigger {1}.{0} completed firing job {6}.{5} at {4, date, HH:mm:ss MM/dd/yyyy} with resulting trigger instruction code: {9}  
#配置job调度插件  quartz_jobs(jobs and triggers内容)的XML文档  
#加载 Job 和 Trigger 信息的类   (1.8之前用:org.quartz.plugins.xml.JobInitializationPlugin)
org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin
#指定存放调度器(Job 和 Trigger)信息的xml文件,默认是classpath下quartz_jobs.xml
org.quartz.plugin.jobInitializer.fileNames = my_quartz_job2.xml  
#org.quartz.plugin.jobInitializer.overWriteExistingJobs = false  
org.quartz.plugin.jobInitializer.failOnFileNotFound = true  
#自动扫描任务单并发现改动的时间间隔,单位为秒
org.quartz.plugin.jobInitializer.scanInterval = 10
#覆盖任务调度器中同名的jobDetail,避免只修改了CronExpression所造成的不能重新生效情况
org.quartz.plugin.jobInitializer.wrapInUserTransaction = false
# ===========================================================================  
# Sample configuration of ShutdownHookPlugin  ShutdownHookPlugin插件的配置样例
# ===========================================================================
#org.quartz.plugin.shutdownhook.class = \org.quartz.plugins.management.ShutdownHookPlugin
#org.quartz.plugin.shutdownhook.cleanShutdown = true
#
# Configure RMI Settings 远程服务调用配置
#
#如果你想quartz-scheduler出口本身通过RMI作为服务器,然后设置“出口”标志true(默认值为false)。
#org.quartz.scheduler.rmi.export = false
#主机上rmi注册表(默认值localhost)
#org.quartz.scheduler.rmi.registryhost = localhost
#注册监听端口号(默认值1099)
#org.quartz.scheduler.rmi.registryport = 1099
#创建rmi注册,false/never:如果你已经有一个在运行或不想进行创建注册
# true/as_needed:第一次尝试使用现有的注册,然后再回来进行创建
# always:先进行创建一个注册,然后再使用回来使用注册
#org.quartz.scheduler.rmi.createregistry = never
#Quartz Scheduler服务端端口,默认是随机分配RMI注册表
#org.quartz.scheduler.rmi.serverport = 1098
#true:链接远程服务调度(客户端),这个也要指定registryhost和registryport,默认为false
# 如果export和proxy同时指定为true,则export的设置将被忽略
#org.quartz.scheduler.rmi.proxy = false

 

六、Quartz与Spring整合

1、quartz使用到了spring上下文、事务,故需要引入
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
 
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
 
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.3</version>
</dependency>

 

2、使用的jobBean,三个实例(JobDetail、Trigger、Scheduler)分别为:
2.1、ScheduleJobBean继承QuartzJobBean接口,实现executeInternal方法(处理逻辑,此处可以通过反射,执行想要执行的方法)
例子:
public class ScheduleJobBean extends QuartzJobBean {
 
    private Logger log = LoggerFactory.getLogger(ScheduleJobBean.class);
    private ExecutorService service = Executors.newSingleThreadExecutor();
 
    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        String jsonJob = context.getMergedJobDataMap().getString(FinalValues.JOB_PARAM_KEY);
        ScheduleJob scheduleJob = JSON.parseObject(jsonJob, ScheduleJob.class);
        try {
            //执行任务
            log.info("任务准备执行,任务ID:" + scheduleJob.getJobId());
            ScheduleRunnable task = new ScheduleRunnable(scheduleJob.getBeanName(),
                    scheduleJob.getMethodName(), scheduleJob.getParams());
            Future<?> future = service.submit(task);
            future.get();
        } catch (Exception e) {
           log.error("任务执行失败,任务ID:"+ scheduleJob.getJobId());
           e.printStackTrace();
        }
    }
}

 

public class ScheduleRunnable implements Runnable {
private Object target;
private Method method;
private String params;
 
public ScheduleRunnable(String beanName, String methodName, String params) throws NoSuchMethodException, SecurityException {
this.target = SpringContextUtils.getBean(beanName);
this.params = params;
 
if(StringUtils.isNotBlank(params)){
this.method = target.getClass().getDeclaredMethod(methodName, String.class);
}else{
this.method = target.getClass().getDeclaredMethod(methodName);
}
}
 
@Override
public void run() {
try {
ReflectionUtils.makeAccessible(method);
if(StringUtils.isNotBlank(params)){
method.invoke(target, params);
}else{
method.invoke(target);
}
}catch (Exception e) {
throw new RuntimeException("执行定时任务失败", e);
}
}
 
}

 

2.2、scheduler:
注入bean
<bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"/>

 

在使用scheduler的类中:
@AutoWired
private SchedulerFactoryBean schedulerFactoryBean;
 
Scheduler scheduler = schedulerFactoryBean.getScheduler();

 

scheduler拥有的常用方法:
/**
     * 获取触发器key
     */
    public static TriggerKey getTriggerKey(Long jobId) {
        return TriggerKey.triggerKey(JOB_NAME + jobId);
    }
    
    /**
     * 获取jobKey
     */
    public static JobKey getJobKey(Long jobId) {
        return JobKey.jobKey(JOB_NAME + jobId);
    }
 
    /**
     * 获取表达式触发器
     */
    public static CronTrigger getCronTrigger(Scheduler scheduler, Long jobId) {
        try {
            TriggerKey id = getTriggerKey(jobId);
            return (CronTrigger) scheduler.getTrigger(id);
        } catch (SchedulerException e) {
            throw new RuntimeException("获取定时任务CronTrigger出现异常", e);
        }
    }
 
    /**
     * 创建定时任务
     */
    public static void createScheduleJob(Scheduler scheduler, ScheduleJob scheduleJob) {
        try {
         //构建job信息
            JobDetail jobDetail = JobBuilder.newJob(ScheduleJobBean.class).withIdentity(getJobKey(scheduleJob.getJobId())).build();
 
            //表达式调度构建器
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression())
             .withMisfireHandlingInstructionDoNothing();
 
            //按cronExpression表达式构建一个新的trigger
            TriggerKey triggerKey = getTriggerKey(scheduleJob.getJobId());
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
 
            //放入参数,运行时的方法可以获取
            jobDetail.getJobDataMap().put(FinalValues.JOB_PARAM_KEY, JSON.toJSONString(scheduleJob));
            scheduler.scheduleJob(jobDetail, trigger);
            
            //暂停任务
            if(scheduleJob.getStatus() == 0){
             pauseJob(scheduler, scheduleJob.getJobId());
            }
        } catch (SchedulerException e) {
            throw new RuntimeException("创建定时任务失败", e);
        }
    }
    
    /**
     * 更新定时任务
     */
    public static void updateScheduleJob(Scheduler scheduler, ScheduleJob scheduleJob) {
        try {
            TriggerKey triggerKey = getTriggerKey(scheduleJob.getJobId());
 
            //表达式调度构建器
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression())
             .withMisfireHandlingInstructionDoNothing();
 
            CronTrigger trigger = getCronTrigger(scheduler, scheduleJob.getJobId());
            
            //按新的cronExpression表达式重新构建trigger
            trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
            
            //参数
            trigger.getJobDataMap().put(FinalValues.JOB_PARAM_KEY, JSON.toJSONString(scheduleJob));
            scheduler.rescheduleJob(triggerKey, trigger);
            
            //暂停任务
            if(scheduleJob.getStatus() == 0){
             pauseJob(scheduler, scheduleJob.getJobId());
            }
            
        } catch (SchedulerException e) {
            throw new RuntimeException("更新定时任务失败", e);
        }
    }   
 
    /**
     * 立即执行任务
     */
    public static void run(Scheduler scheduler, ScheduleJob scheduleJob) {
        try {
         //参数
         JobDataMap dataMap = new JobDataMap();
         dataMap.put(FinalValues.JOB_PARAM_KEY, JSON.toJSONString(scheduleJob));
            scheduler.triggerJob(getJobKey(scheduleJob.getJobId()), dataMap);
        } catch (SchedulerException e) {
            throw new RuntimeException("立即执行定时任务失败", e);
        }
    }
 
    /**
     * 暂停任务
     */
    public static void pauseJob(Scheduler scheduler, Long jobId) {
        try {
            scheduler.pauseJob(getJobKey(jobId));
        } catch (SchedulerException e) {
            throw new RuntimeException("暂停定时任务失败", e);
        }
    }
 
    /**
     * 恢复任务
     */
    public static void resumeJob(Scheduler scheduler, Long jobId) {
        try {
            scheduler.resumeJob(getJobKey(jobId));
        } catch (SchedulerException e) {
            throw new RuntimeException("暂停定时任务失败", e);
        }
    }
 
    /**
     * 删除定时任务
     */
    public static void deleteScheduleJob(Scheduler scheduler, Long jobId) {
        try {
            scheduler.deleteJob(getJobKey(jobId));
        } catch (SchedulerException e) {
            throw new RuntimeException("删除定时任务失败", e);
        }
    }

 

2.3、JobDetail:
JobDetail jobDetail = JobBuilder.newJob(ScheduleJobBean.class).withIdentity("jobId").build();

 

2.4、Trigger:
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();

 

 
posted @ 2023-08-17 15:38  咔咔皮卡丘  阅读(35)  评论(0编辑  收藏  举报