使用quartz开源调度框架,写服务实现在一些指定场景发送特定短信,创建一个实现org.quartz.Job接口的java类。Job接口包含唯一的方法:
public void execute(JobExecutionContext context) throws JobExecutionException;
在你的Job接口实现类里面,添加一些逻辑到
execute()方法。一旦你配置好Job实现类并设定好调度时间表,Quartz将密切注意剩余时间。当调度程序确定该是通知你的作业的时候,
Quartz框架将调用你Job实现类(作业类)上的
execute()方法并允许做它该做的事情。无需报告任何东西给调度器或调用任何特定的东西。仅仅
执行任务和结束任务即可。如果配置你的作业在随后再次被调用,Quartz框架将
在恰当的时间再次调用它;
存放调度器(Job 和 Trigger)信息的xml配置文件中:
<!-- 实时扫描短信数据表,没有发送的调用运营商给的接口推送,完成发送短信操作 --> <job> <name>ReceiveMessageJob</name> <job-class>com.xxx.cscns.sms.ReceiveMessageJob</job-class> </job> <trigger> <simple> <name>ReceiveMessageJob</name> <job-name>ReceiveMessageJob</job-name> <repeat-count>-1</repeat-count> <repeat-interval>1</repeat-interval> </simple> </trigger>
<!-- 每天给项目经理发送短信避免短信服务挂了 定时每天08:30执行--> <job> <name>SendToManagerJob</name> <job-class>com.xxx.cscns.sms.SendToManagerJob</job-class> </job> <trigger> <cron> <name>SendToManagerJob</name> <job-name>SendToManagerJob</job-name> <cron-expression>0 30 8 * * ?</cron-expression> </cron> </trigger>
其中<cron-expression>标签的值表示执行的时间和频率信息,有一套完整的格式规范:
序号 说明 是否必填 允许填写的值 允许的通配符
1 秒 是 0-59 , - * /
2 分 是 0-59 , - * /
3 小时 是 0-23 , - * /
4 日 是 1-31 , - * ? / L W
5 月 是 1-12 or JAN-DEC , - * /
6 周 是 1-7 or SUN-SAT , - * ? / L #
7 年 否 empty 或 1970-2099 , - * /
上面短信发送任务的 0 30 8 * * ? 表示“每天早上八点半执行一次”的意思;
其中通配符说明:* 表示所有值,例如:在分的字段上设置 "*",表示每一分钟都会触发;
? 表示不指定值。使用的场景为不需要关心当前设置这个字段的值。例如:要在每月的10号触发一个操作,但不关心是周几,所以需要周位置的那个字段设置为"?" ;
- 表示区间。例如 在小时上设置 "10-12",表示 10,11,12点都会触发。, 表示指定多个值,例如在周字段上设置 "MON,WED,FRI" 表示周一,周三和周五触发 ;
/ 用于递增触发。如在秒上面设置"5/15" 表示从5秒开始,每增15秒触发(5,20,35,50)。 在日字段上设置'1/3'所示每月1号开始,每隔三天触发一次 ;
L 表示最后的意思。在日字段设置上,表示当月的最后一天(依据当前月份,如果是二月还会依据是否是润年[leap]), 在周字段上表示星期六,相当于"7"或"SAT",
如果在"L"前加上数字,则表示该数据的最后一个。例如在周字段上设置"6L"这样的格式,则表示“本月最后一个星期五",因为7是星期六,1是星期日;
W 表示离指定日期的最近那个工作日(周一至周五). 例如在日字段上设置"15W",表示离每月15号最近的那个工作日触发;
'L'和 'W'可以一组合使用。如果在日字段上设置"LW",则表示在本月的最后一个工作日触发;
**简单和复杂的配置job和trigger:
simple 简单任务的触发器,可以调度用于重复执行的任务 name(必填) 触发器名称,同一个分组中的名称必须不同 group(选填) 触发器组 description(选填) 触发器描述 job-name(必填) 要调度的任务名称,该job-name必须和对应job节点中的name完全相同 job-group(选填) 调度任务(job)所属分组,该值必须和job中的group完全相同 start-time(选填) 任务开始执行时间utc时间,北京时间需要+08:00,如:<start-time>2012-04-01T08:00:00+08:00</start-time>表示北京时间2012年4月1日上午8:00开始执行,注意服务启动或重启时都会检测此属性,若没有设置此属性或者start-time设置的时间比当前时间较早,则服务启动后会立即执行一次调度,若设置的时间比当前时间晚,服务会等到设置时间相同后才会第一次执行任务,一般若无特殊需要请不要设置此属性 repeat-count(必填) 任务执行次数,如:<repeat-count>-1</repeat-count>表示无限次执行,<repeat-count>10</repeat-count>表示执行10次 repeat-interval(必填) 任务触发间隔(毫秒),如:<repeat-interval>10000</repeat-interval> 每10秒执行一次
cron复杂任务触发器--使用cron表达式定制任务调度(强烈推荐) name(必填) 触发器名称,同一个分组中的名称必须不同 group(选填) 触发器组 description(选填) 触发器描述 job-name(必填) 要调度的任务名称,该job-name必须和对应job节点中的name完全相同 job-group(选填) 调度任务(job)所属分组,该值必须和job中的group完全相同 start-time(选填) 任务开始执行时间utc时间,北京时间需要+08:00,如:<start-time>2012-04-01T08:00:00+08:00</start-time>表示北京时间2012年4月1日上午8:00开始执行,注意服务启动或重启时都会检测此属性,若没有设置此属性,服务会根据cron-expression的设置执行任务调度;若start-time设置的时间比当前时间较早,则服务启动后会忽略掉cron-expression设置,立即执行一次调度,之后再根据cron-expression执行任务调度;若设置的时间比当前时间晚,则服务会在到达设置时间相同后才会应用cron-expression,根据规则执行任务调度,一般若无特殊需要请不要设置此属性 cron-expression(必填) cron表达式,如:<cron-expression>0/10 * * * * ?</cron-expression>每10秒执行一次
根据配置的调度信息,找到job的实现类和其业务逻辑实施层方法,如下实例:
job实现类的代码:
package com.xxx.cscns.sms; import org.quartz.DisallowConcurrentExecution; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import com.xxx.core.xxxFrameDsManager; import com.xxx.cscns.service.MessageService; @DisallowConcurrentExecution public class SendToManagerJob implements Job{ @Override public void execute(JobExecutionContext arg0) throws JobExecutionException { try { xxxFrameDsManager.begin(null); MessageService messageService = new MessageService(); // 调用业务逻辑实施层方法,实现发短信操作 messageService.sendToManger(); System.out.println("上班前半小时发送一次短信给项目经理成功!"); } catch (Exception e) { xxxFrameDsManager.rollback(); e.printStackTrace(); System.out.println("上班前半小时发送一次短信给项目经理异常:"+e.toString()); } finally { xxxFrameDsManager.close(); } } }
封装的业务逻辑实施层的方法:
/* * * 每天给项目经理发送短信避免短信服务挂了 */ public void sendToManger() { try { //系统参数配置项目经理手机号码,这儿是封装的方法,只要能获取到项目经理手机号就行 String messageTarget = new FrameConfigService9().getFrameConfigValue("ASP_MESSAGE_TEST_TEL"); //时间格式化 SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String sql = "insert into Messages_center ( MessageItemGuid, Content, GenerateDate, IsSchedule, MessageTarget, sendMode,messagetype)"; sql += "values( '" + UUID.randomUUID().toString() + "', '【XXX项目】短信服务正常。', to_date('" + sdf2.format(new Date())+ "', 'yyyy-mm-dd hh24:mi:ss'), 0, '" + messageTarget + "', 1,'短信')"; if(StringUtil.isNotBlank(messageTarget)){ dao.execute(sql); } } catch (Exception e) { e.printStackTrace(); dao.rollBackTransaction(); } finally { if (dao != null){ dao.close(); } } }