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();
本文来自博客园,作者:咔咔皮卡丘,转载请注明原文链接:https://www.cnblogs.com/anquing/p/17637799.html