quartz实现每周一至周五 非法定节假日 每天9:30-11:30,13:00-15:00执行定时任务

我的定时任务需求是:使用quartz实现每周一至周五,非法定节假日,每天9:30-11:30,13:00-15:00执行定时任务。
经过学习quartz,发现使用SimperTrigger和CronTrgger这两种触发器都无法满足这种需求的表达,我始终无法相信强大的quartz绝对不可能无法实现这种需求。
经过别人的指点,终于在一篇法文的blog中找到了类似的解决办法,需要借助于quartz的Calender来实现这种需求,这个过程非常曲折,遇到了很多问题,总体感觉quartz虽然强大,但是社区的活跃程度不够,文档还不是非常完善,这也许是很多开源项目的通病,可能很多复杂一些的需求,直接从文档中无法得到答案,有时候需要自己去阅读源代码,阅读javadoc才能找到答案,解决这一问题后再次印证了那句话,黄天不负有心人,只要你坚持问题总能解决的,
 
下面进入正题。
 

对于排除法定节假日,可以使用HolidayCalendar,但是该类只能排除某一个法定节假日,无法方便的排除一个列表的节假日,因此需要自己扩展该类,代码如下:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1.        private static Logger logger = Logger.getLogger(TradeDayCalendar.class);  
  2.   
  3. //默认的时间格式。  
  4. public static String DEFAULT_DATE_FROMART = "yyyy-MM-dd";  
  5.   
  6. //时间格式。  
  7. private String dateFormat = DEFAULT_DATE_FROMART;  
  8.   
  9. public String getDateFormat() {  
  10.     return dateFormat;  
  11. }  
  12.   
  13. /**  
  14.  * 设置日期格式。  
  15.  * @param dateFormat  
  16.  */  
  17. public void setDateFormat(String dateFormat) {  
  18.     this.dateFormat = dateFormat;  
  19. }  
  20.   
  21. public TradeDayCalendar() {  
  22. }  
  23.   
  24. public TradeDayCalendar(Calendar baseCalendar) {  
  25.     super(baseCalendar);  
  26. }  
  27.   
  28. public TradeDayCalendar(TimeZone timeZone) {  
  29.     super(timeZone);  
  30. }  
  31.   
  32. public TradeDayCalendar(Calendar baseCalendar, TimeZone timeZone) {  
  33.     super(baseCalendar, timeZone);  
  34. }  
  35.   
  36. /**  
  37.  * 构造一个日历对象,排除指定的那些法定节假日。  
  38.  * @param stringDates 日期列表字符串,一个日期列表字符串,多个日期以逗号隔开,默认的日期格式是 yyyy-MM-dd. 例如 : 2010-1-01,2010-10-01  
  39.  */  
  40. public TradeDayCalendar(String stringDates) {  
  41.     this(null, stringDates);  
  42. }  
  43.   
  44. /**  
  45.  *  构造一个日历对象,排除指定的那些法定节假日。  
  46.  *  
  47.  * @param baseCalendar, 与本日历对象关联的基础日历对象,在基础日历对象的基础上再排除指定的法定节假日,可以是null。  
  48.  * @param stringDates 日期列表字符串,一个日期列表字符串,多个日期以逗号隔开,默认的日期格式是 yyyy-MM-dd. 例如 : 2010-1-01,2010-10-01  
  49.  */  
  50. public TradeDayCalendar(Calendar baseCalendar, String stringDates) {  
  51.     super(baseCalendar);  
  52.   
  53.     //将日期字符串解析成字符数组。  
  54.     String[] stringDatesArray = stringDates.split(",");  
  55.     Date[] dates = null;  
  56.     try {  
  57.         dates = getDatesFromStrings(stringDatesArray);  
  58.     } catch (ParseException e) {  
  59.         logger.error(e.getMessage());  
  60.     }  
  61.   
  62.     if (dates != null && dates.length == stringDatesArray.length) {  
  63.         if (logger.isDebugEnabled())  
  64.             logger.debug("Excluded dates : " + stringDates);  
  65.         addExcludedDates(dates);  
  66.     } else {  
  67.         //某些日期无法解析。  
  68.         throw new IllegalArgumentException(  
  69.                 "Some configured dates were invalids (not parseable as "  
  70.                         + dateFormat + "). Full list of configured dates{"  
  71.                         + stringDates +"} valid dates " +stringDates);  
  72.     }  
  73. }  
  74.   
  75. /**  
  76.  * 将日历字符串数组,按照默认的日期格式转换为Date类型的数组。  
  77.  * @param stringDatesArray 日期字符串数组。  
  78.  * @return 转换后的Date型的数组。  
  79.  * @throws ParseException 输入的日期解析出错,日期格式有问题。  
  80.  */  
  81. private Date[] getDatesFromStrings(String[] stringDatesArray) throws ParseException{  
  82.     if(stringDatesArray==null || stringDatesArray.length==0)  
  83.         return null;  
  84.     Date[] dates = new Date[stringDatesArray.length];  
  85.     for(int i=0; i<stringDatesArray.length; i++){  
  86.         String stringDate = stringDatesArray[i];  
  87.         SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateFormat);  
  88.         dates[i] = simpleDateFormat.parse(stringDate);  
  89.     }  
  90.     return dates;  
  91. }  
  92.   
  93. /**  
  94.  * 循环添加数组中的日期到被排除的日期列表中,会跳过那些无法解析的日期。  
  95.  */  
  96. private void addExcludedDates(Date[] dates) {  
  97.     for (int i = 0; i < dates.length; i++) {  
  98.         Date legalHoliday = dates[i];  
  99.         addExcludedDate(legalHoliday);  
  100.     }  
  101. }  

为了方便修改法定节假日,可以将法定节假日的配置放在java properties文件中。

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
  2.     <property name="ignoreUnresolvablePlaceholders" value="true" />  
  3.     <property name="location" value="classpath:application.properties" />  
  4. </bean>  
  5. tradeDays.legalHolidays=2010-01-01,2010-10-01,2010-07-15  

spring配置文件中继续配置定时任务,配置如下:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <!-- 配置监控上交所行情的任务。 -->  
  2. <bean id="monitorShow2003" class="com.cssweb.quote.realtime.oracle.MonitorShow2003" />  
  3. <bean id="monitorShow2003JobDetail"  
  4.     class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">  
  5.     <property name="targetObject" ref="monitorShow2003" />  
  6.     <property name="targetMethod" value="run" />  
  7. </bean>  
  8. <!-- 配置上午监控上交所的任务触发器。 -->  
  9. <bean id="monitorShow2003AMTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">  
  10.     <property name="jobDetail" ref="monitorShow2003JobDetail" />  
  11.     <!-- 每隔一秒钟(1000毫秒)执行一次 -->  
  12.     <property name="repeatInterval" value="1000"></property>  
  13.     <property name="calendarName" value="tradeTimeAMCalendar"></property>  
  14. </bean>  
  15. <!-- 配置下午监控上交所的任务触发器。 -->  
  16. <bean id="monitorShow2003PMTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">  
  17.     <property name="jobDetail" ref="monitorShow2003JobDetail" />  
  18.     <!-- 每隔一秒钟(1000毫秒)执行一次 -->  
  19.     <property name="repeatInterval" value="1000"></property>  
  20.     <property name="calendarName" value="tradeTimePMCalendar"></property>  
  21. </bean>  
  22.   
  23. <!-- 排除周六和周日的日历。 -->  
  24. <bean id="excludeWeekendsCalendar" class="org.quartz.impl.calendar.WeeklyCalendar" />  
  25.   
  26. <!-- 排除法定节假日的日历。 -->  
  27. <bean id="tradeDayCalendar" class="com.csc108.quartz.TradeDayCalendar">  
  28.     <constructor-arg ref="excludeWeekendsCalendar" />  
  29.     <constructor-arg value="${tradeDays.legalHolidays}" />  
  30. </bean>  
  31.   
  32. <!-- 上午9:15到11:45的交易时间 -->  
  33. <bean id="tradeTimeAMCalendar" class="org.quartz.impl.calendar.DailyCalendar">  
  34.     <constructor-arg ref="tradeDayCalendar" />  
  35.     <constructor-arg value="09:15" type="java.lang.String" />  
  36.     <constructor-arg value="11:45" type="java.lang.String" />  
  37.     <!-- include hours between start and end -->  
  38.     <property name="invertTimeRange" value="true" />  
  39. </bean>  
  40.   
  41. <!-- 下午12:40到15:25的交易时间 -->  
  42. <bean id="tradeTimePMCalendar" class="org.quartz.impl.calendar.DailyCalendar">  
  43.     <constructor-arg ref="tradeDayCalendar" />  
  44.     <constructor-arg value="12:45" type="java.lang.String" />  
  45.     <constructor-arg value="15:25" type="java.lang.String" />  
  46.     <!-- include hours between start and end -->  
  47.     <property name="invertTimeRange" value="true" />  
  48. </bean>  
  49.   
  50. <!-- 上午和下午交易时间监控上交股票行情信息的任务调度。 -->  
  51. <bean id="schedulerFactoryBean"  
  52.     class="org.springframework.scheduling.quartz.SchedulerFactoryBean">  
  53.     <property name="calendars">  
  54.         <map>  
  55.             <entry key="tradeTimeAMCalendar" value-ref="tradeTimeAMCalendar"/>  
  56.             <entry key="tradeTimePMCalendar" value-ref="tradeTimePMCalendar"/>  
  57.         </map>  
  58.     </property>  
  59.     <property name="triggers">  
  60.         <list>  
  61.             <ref bean="monitorShow2003AMTrigger"/>  
  62.             <ref bean="monitorShow2003PMTrigger" />  
  63.         </list>  
  64.     </property>  
  65. </bean>  

猜你喜欢

转载自blog.csdn.net/Shirley_John_Thomas/article/details/60146783