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

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

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

        private static Logger logger = Logger.getLogger(TradeDayCalendar.class);//默认的时间格式。public static String DEFAULT_DATE_FROMART = "yyyy-MM-dd";//时间格式。private String dateFormat = DEFAULT_DATE_FROMART;public String getDateFormat() {return dateFormat;}/** * 设置日期格式。 * @param dateFormat */public void setDateFormat(String dateFormat) {this.dateFormat = dateFormat;}public TradeDayCalendar() {}public TradeDayCalendar(Calendar baseCalendar) {super(baseCalendar);}public TradeDayCalendar(TimeZone timeZone) {super(timeZone);}public TradeDayCalendar(Calendar baseCalendar, TimeZone timeZone) {super(baseCalendar, timeZone);}/** * 构造一个日历对象,排除指定的那些法定节假日。 * @param stringDates 日期列表字符串,一个日期列表字符串,多个日期以逗号隔开,默认的日期格式是 yyyy-MM-dd. 例如 : 2010-1-01,2010-10-01 */public TradeDayCalendar(String stringDates) {this(null, stringDates);}/** *  构造一个日历对象,排除指定的那些法定节假日。 * * @param baseCalendar, 与本日历对象关联的基础日历对象,在基础日历对象的基础上再排除指定的法定节假日,可以是null。 * @param stringDates 日期列表字符串,一个日期列表字符串,多个日期以逗号隔开,默认的日期格式是 yyyy-MM-dd. 例如 : 2010-1-01,2010-10-01 */public TradeDayCalendar(Calendar baseCalendar, String stringDates) {super(baseCalendar);//将日期字符串解析成字符数组。String[] stringDatesArray = stringDates.split(",");Date[] dates = null;try {dates = getDatesFromStrings(stringDatesArray);} catch (ParseException e) {logger.error(e.getMessage());}if (dates != null && dates.length == stringDatesArray.length) {if (logger.isDebugEnabled())logger.debug("Excluded dates : " + stringDates);addExcludedDates(dates);} else {//某些日期无法解析。throw new IllegalArgumentException("Some configured dates were invalids (not parseable as "+ dateFormat + "). Full list of configured dates{"+ stringDates +"} valid dates " +stringDates);}}/** * 将日历字符串数组,按照默认的日期格式转换为Date类型的数组。 * @param stringDatesArray 日期字符串数组。 * @return 转换后的Date型的数组。 * @throws ParseException 输入的日期解析出错,日期格式有问题。 */private Date[] getDatesFromStrings(String[] stringDatesArray) throws ParseException{if(stringDatesArray==null || stringDatesArray.length==0)return null;Date[] dates = new Date[stringDatesArray.length];for(int i=0; i<stringDatesArray.length; i++){String stringDate = stringDatesArray[i];SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateFormat);dates[i] = simpleDateFormat.parse(stringDate);}return dates;}/** * 循环添加数组中的日期到被排除的日期列表中,会跳过那些无法解析的日期。 */private void addExcludedDates(Date[] dates) {for (int i = 0; i < dates.length; i++) {Date legalHoliday = dates[i];addExcludedDate(legalHoliday);}}

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

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"><property name="ignoreUnresolvablePlaceholders" value="true" /><property name="location" value="classpath:application.properties" /></bean>tradeDays.legalHolidays=2010-01-01,2010-10-01,2010-07-15

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

<!-- 配置监控上交所行情的任务。 --><bean id="monitorShow2003" class="com.cssweb.quote.realtime.oracle.MonitorShow2003" /><bean id="monitorShow2003JobDetail"class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"><property name="targetObject" ref="monitorShow2003" /><property name="targetMethod" value="run" /></bean><!-- 配置上午监控上交所的任务触发器。 --><bean id="monitorShow2003AMTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean"><property name="jobDetail" ref="monitorShow2003JobDetail" /><!-- 每隔一秒钟(1000毫秒)执行一次 --><property name="repeatInterval" value="1000"></property><property name="calendarName" value="tradeTimeAMCalendar"></property></bean><!-- 配置下午监控上交所的任务触发器。 --><bean id="monitorShow2003PMTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean"><property name="jobDetail" ref="monitorShow2003JobDetail" /><!-- 每隔一秒钟(1000毫秒)执行一次 --><property name="repeatInterval" value="1000"></property><property name="calendarName" value="tradeTimePMCalendar"></property></bean> <!-- 排除周六和周日的日历。 --><bean id="excludeWeekendsCalendar" class="org.quartz.impl.calendar.WeeklyCalendar" /><!-- 排除法定节假日的日历。 --><bean id="tradeDayCalendar" class="com.csc108.quartz.TradeDayCalendar"><constructor-arg ref="excludeWeekendsCalendar" /><constructor-arg value="${tradeDays.legalHolidays}" /></bean><!-- 上午9:15到11:45的交易时间 --><bean id="tradeTimeAMCalendar" class="org.quartz.impl.calendar.DailyCalendar"><constructor-arg ref="tradeDayCalendar" /><constructor-arg value="09:15" type="java.lang.String" /><constructor-arg value="11:45" type="java.lang.String" /><!-- include hours between start and end --><property name="invertTimeRange" value="true" /></bean><!-- 下午12:40到15:25的交易时间 --><bean id="tradeTimePMCalendar" class="org.quartz.impl.calendar.DailyCalendar"><constructor-arg ref="tradeDayCalendar" /><constructor-arg value="12:45" type="java.lang.String" /><constructor-arg value="15:25" type="java.lang.String" /><!-- include hours between start and end --><property name="invertTimeRange" value="true" /></bean> <!-- 上午和下午交易时间监控上交股票行情信息的任务调度。 --><bean id="schedulerFactoryBean"class="org.springframework.scheduling.quartz.SchedulerFactoryBean"><property name="calendars"><map><entry key="tradeTimeAMCalendar" value-ref="tradeTimeAMCalendar"/><entry key="tradeTimePMCalendar" value-ref="tradeTimePMCalendar"/></map></property><property name="triggers"><list><ref bean="monitorShow2003AMTrigger"/><ref bean="monitorShow2003PMTrigger" /></list></property></bean>


0 0
原创粉丝点击