Java定时任务调度工具详解Quartz(二)——代码实现
针对Java定时任务调度工具详解Quartz(一)基础内容,下面给出代码示例:
首先建立Maven工程:
一:创建业务逻辑实现类:即任务(job)了解及其属性的用法,代码如下:
public class HelloJob implements Job{ //定义传入的参数的键值,必须要与自定义JobDetail与Trigger传参的键值相同的命名方式;应用于方法三 //方法三,定义的类型开始 private String message; private Float floatValue; private Double doubleValue; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public Float getFloatValue() { return floatValue; } public void setFloatValue(Float floatValue) { this.floatValue = floatValue; } public Double getDoubleValue() { return doubleValue; } public void setDoubleValue(Double doubleValue) { this.doubleValue = doubleValue; } //方法三,定义的类型结束 @Override public void execute(JobExecutionContext context) throws JobExecutionException { //打印当前执行时间 Date data=new Date(); SimpleDateFormat ft=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.out.println("Current time is:"+ft.format(data)); // 编写具体的业务逻辑的实现 // System.out.println("Hellow World!!!"); //由上下文参数context,获取任务与触发器的name与group属性 JobKey jobkey=context.getJobDetail().getKey(); System.out.println("My job name and group is : "+jobkey.getName()+" : "+jobkey.getGroup()); TriggerKey trigger=context.getTrigger().getKey(); System.out.println("My trigger name and group is: "+trigger.getName()+" : "+trigger.getGroup()); //方法一:分别获取 //由上下文参数context,jobDataMap方法获取方法中自定义引入的参数 // JobDataMap dataMap=context.getJobDetail().getJobDataMap(); // String jobMessage=dataMap.getString("message"); //与任务jobDetail方法中自定义 // Float floatValue=dataMap.getFloat("floatValue"); // System.out.println("JobDetail's message is:"+jobMessage); // System.out.println("JobDetail's floatValue is:"+floatValue); // // JobDataMap tdataMap=context.getTrigger().getJobDataMap(); // String triggerMessage=tdataMap.getString("message"); // Double doubleValue=tdataMap.getDouble("doubleValue"); // System.out.println("Trigger's message is:"+triggerMessage); // System.out.println("Trigger's doubleValue is:"+doubleValue); //方法二:合并获取,存在键值相同的,取Trigger的值 // JobDataMap dataMap2=context.getMergedJobDataMap(); //getMergedJobDataMap方法将任务与触发器传参合并 // String msg=dataMap2.getString("message"); //任务DetailJob与触发器Trigger传参具有相同的键“message”,以触发器Trigger为准 // Float floatValue2=dataMap2.getFloat("floatValue"); // Double doubleValue2=dataMap2.getDouble("doubleValue"); // System.out.println("JobDetail's floatValue is:"+floatValue2); // System.out.println("msg is:"+msg); // System.out.println("Trigger's doubleValue is:"+doubleValue2); //方法三:根据getter与setter方法实现传参;通过设置变量属性,使用getter()和setter()方法来进行传值。 System.out.println("JobDetail's floatValue is:"+floatValue); System.out.println("msg is:"+message); System.out.println("Trigger's doubleValue is:"+doubleValue); } }
具体调度实现(代码):
public class HelloScheduler { public static void main(String[] args) throws SchedulerException { // 创建一个jobDetil实例,该实例与HelloJob Class绑定 JobDetail jobDetail = JobBuilder.newJob(HelloJob.class). // 获取类 withIdentity("myJob", "Jobgroup1"). // 任务唯一标识与组别 usingJobData("message", "myJob1"). //自定义传入参数(String类型) usingJobData("floatValue", 3.14F). //自定义传入参数(float类型) build(); // 创建实例 //打印jobdetail属性值(name,group,jobclass) // System.out.println("JobDetail's name:"+jobDetail.getKey().getName()); // System.out.println("JobDetail's group:"+jobDetail.getKey().getGroup()); // System.out.println("JobDetail's jobclass:"+jobDetail.getJobClass().getName()); // 创建一个Trigger实例,定义该job立即执行,并且每个2秒钟重复执行一次,直到永远 Trigger trigger = TriggerBuilder.newTrigger(). //获取trigger类 withIdentity("myTrigger", "Triggergourp1"). //任务唯一标识与组别 usingJobData("message", "myTrigger1"). //自定义传入参数(String类型) usingJobData("doubleValue", 1.70D). //自定义传入参数(double类型) startNow() //立即执行 .withSchedule(SimpleScheduleBuilder. //获取schedule类 simpleSchedule(). withIntervalInSeconds(2). //每个2秒执行一次 repeatForever()). //重复执行 build(); //创建实例 //创建Scheduler实例 SchedulerFactory fac=new StdSchedulerFactory(); Scheduler scheduler=fac.getScheduler(); scheduler.start(); //打印当前执行时间 Date data=new Date(); SimpleDateFormat ft=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.out.println("Current time is:"+ft.format(data)); scheduler.scheduleJob(jobDetail, trigger); } }
示例二:(了解trigger属性jobkey,starttime,endtime示例)
任务逻辑实现job:
/** * trigger属性jobkey,starttime,endtime示例 */ public class HelloJob2 implements Job{ @Override public void execute(JobExecutionContext context) throws JobExecutionException { //设置时间延迟,让该进程延迟结束 try { Thread.sleep(5000L); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } // 打印当前执行时间 Date data = new Date(); SimpleDateFormat ft = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.out.println("Current Exec time is:" + ft.format(data)); //示例一:应用于简单应用 System.out.println("Hello World!"); // Trigger dataTrigger=context.getTrigger(); // System.out.println("Start Time Is="+ft.format(dataTrigger.getStartTime())); // System.out.println("End Time Is="+ft.format(dataTrigger.getEndTime())); // JobKey jobkey=dataTrigger.getJobKey(); //获取任务job的属性值 // System.out.println("JobKey Info---"+" JobName is:"+jobkey.getName()+" JobGroup is:"+jobkey.getGroup()); } }
具体调度实现(代码):
/** * trigger属性jobkey,starttime,endtime示例 */ public class HelloScheduler2 { public static void main(String[] args) throws SchedulerException, InterruptedException { //打印当前执行时间 Date data=new Date(); SimpleDateFormat ft=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.out.println("Current time is:"+ft.format(data)); //获取当前时间3秒后 data.setTime(data.getTime()+3000); //获取当前时间6秒后 Date date2=new Date(); date2.setTime(date2.getTime()+6000); // 创建一个jobDetil实例,该实例与HelloJob Class绑定 JobDetail jobDetail = JobBuilder.newJob(HelloJob2.class). // 获取类 withIdentity("myJob", "Jobgroup1"). // 任务唯一标识与组别 build(); // 创建实例 // 示例11:创建一个Trigger实例,定义该job在当前时间3秒后执行,执行6秒后结束 // Trigger trigger = TriggerBuilder.newTrigger(). // 获取trigger类 // withIdentity("myTrigger", "Triggergourp1"). // 任务唯一标识与组别 // startAt(data) // 在当前时间3秒后执行 // .endAt(date2) // 在当前时间6秒后结束 // .withSchedule(SimpleScheduleBuilder. // 获取schedule类 // simpleSchedule().withIntervalInSeconds(2). // 每个2秒执行一次 // repeatForever()). // 重复执行 // build(); //示例一:检定应用,simpleTrigger示例 // SimpleTrigger trigger=(SimpleTrigger)TriggerBuilder.newTrigger(). // 获取SimpleTrigger类 // withIdentity("myTrigger", "Triggergourp1"). // 任务唯一标识与组别 // startAt(data) // 在当前时间3秒后执行 // .endAt(date2) // 在当前时间6秒后结束,优先于withRepeatCount // .withSchedule(SimpleScheduleBuilder. // 获取schedule类 // simpleSchedule().withIntervalInSeconds(2). // 每个2秒执行一次 //// withRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY)). // 设置执行次数,无限次执行 // withRepeatCount(3)). // 设置执行次数,总共是执行4次 // build(); // 创建实例 //示例二:Crontrigger示例,其中“*”表示“每”,“?”表示无 CronTrigger trigger=(CronTrigger)TriggerBuilder.newTrigger(). // 获取SimpleTrigger类 withIdentity("myTrigger", "Triggergourp1"). // 任务唯一标识与组别 withSchedule(CronScheduleBuilder.cronSchedule("* * * * * ? *")). //设置执行方式,每秒都在执行 build(); // 创建实例 //测试时,可以修改系统中日历进行调试 //1.2017年内每天10点15分触发一次 //0 15 10 ? * * 2017,即改写withSchedule(CronScheduleBuilder.cronSchedule("0 15 10 ? * * 2017"))即可 //2.每天的14点整至14点59分55秒,以及18点整59分55秒,每5秒钟触发一次 //0/5 * 14,18 * * ? //3、每月周一值周五的10点15分触发一次 //* 15 10 ? * MON-FRI //4、每月最后一天的10点15分触发一次 //* 15 10 L * ? //5、每月第三个周五的10点15分触发一次 //* 15 10 ? * 6#3 //6、如何定义每月最后一个工作日呢? //0 0 0 LW * ? // 创建Scheduler实例 SchedulerFactory fac = new StdSchedulerFactory(); Scheduler scheduler = fac.getScheduler(); scheduler.start(); System.out.println("scheduled time is :"+ft.format(scheduler.scheduleJob(jobDetail, trigger))); // //scheduler执行两秒后挂起 // Thread.sleep(2000L); //停2秒 // scheduler.standby(); //挂起 // //挂起3秒后重新开启 // Thread.sleep(3000L); // scheduler.start(); Thread.sleep(2000L); // shutdown(true)表示等待所有正在执行的job执行完毕之后,再关闭scheduler;可以让job休眠大于2秒,来进行测试,需要等待job执行完毕才关闭 // shutdown(false)即shutdown()表示直接关闭scheduler scheduler.shutdown(true); System.out.println("scheduler is shut down?"+scheduler.isShutdown()); } }
三:基于quartz.properties配置的信息(具体含义可以详见quartz官网):
# Default Properties file for use by StdSchedulerFactory # to create a Quartz Scheduler Instance, if a different # properties file is not explicitly specified. # # =========================================================================== # 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