`
chennaid2
  • 浏览: 51047 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论
  • b_l_east: 在主动模式下,如果有多个客户端,服务器对每一个客户端均使用20 ...
    ftp

广告项目:(2)spring的动态设置定时任务执行时间

阅读更多

1.定时器:

 

1.1  先看看配置文件:quartz.properties

  #============================================================================ # \u914d\u7f6e Main Scheduler Properties #============================================================================ org.quartz.scheduler.instanceName = DefaultQuartzScheduler org.quartz.scheduler.rmi.export = false org.quartz.scheduler.rmi.proxy = false org.quartz.scheduler.wrapJobExecutionInUserTransaction = false #============================================================================ # \u914d\u7f6e\u6267\u884c\u7ebf\u7a0b\u6c60 #============================================================================ org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool org.quartz.threadPool.threadCount = 20 org.quartz.threadPool.threadPriority = 5 org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true #============================================================================ # \u914d\u7f6e JobStore #============================================================================ org.quartz.jobStore.misfireThreshold = 60000 #\u5185\u5b58\u4e2dJobStore, \u670d\u52a1\u5668\u91cd\u542f\u65f6\u6267\u884c\u8bb0\u5f55\u4f1a\u4e22\u5931,,\u9ed8\u8ba4\u914d\u7f6e org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore #\u6570\u636e\u5e93\u4e2dJobStore


 

1.2 applicationContext-quartz.xml

 

 

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <!-- 执行的任务--> <bean id="cronTriggerBean" class="org.springframework.scheduling.quartz.CronTriggerBean" /> <bean id="taskCommand" class="com.dvnchina.itv.advert.services.taskmanager.TaskCommand" parent="cronTriggerBean" autowire="byName" > <property name="scheduler" ref="quartzScheduler"/> </bean> <!-- 任务日程安排 --> <bean name="quartzScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="cronTriggerQueryPlayItem" /> <ref bean="cronTriggerSendFtp" /> </list> </property> <property name="configLocation" value="classpath:spring/quartz.properties" /> </bean> <!-- 查询系统当前时间 ,所属那个播放时段--> <bean id="queryPlayItemCommand" class="com.dvnchina.itv.advert.services.taskmanager.PlayItemListenerCommand" autowire="byName" > <property name="taskCommand" ref="taskCommand"/> </bean> <bean id="jobDetailQueryPlayItem" name="jobDetailQueryPlayItem" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject" ref="queryPlayItemCommand" /> <property name="targetMethod" value="timerQueryTimer" /> <property name="concurrent" value="false" /> </bean> <!-- 触发器_1 --> <!-- 每隔30秒钟触发一次 --> <bean id="cronTriggerQueryPlayItem" class="org.springframework.scheduling.quartz.CronTriggerBean"> <property name="jobDetail" ref="jobDetailQueryPlayItem" /> <property name="cronExpression" value="0/30 * * * * ?" /> </bean> <!-- 自动发布定时任务 --> <bean id="sendFtpCommand" class="com.dvnchina.itv.advert.services.taskmanager.SendFtpListenerCommand" autowire="byName" > <property name="taskCommand"> <ref bean="taskCommand" /> </property> </bean> <bean id="jobDetailSendFtp" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject" ref="sendFtpCommand" /> <property name="targetMethod" value="sendAdvertFolderJob" /> <property name="concurrent" value="false" /> </bean> <!-- 触发器_2 --> <bean id="cronTriggerSendFtp" class="org.springframework.scheduling.quartz.CronTriggerBean" autowire="byName" > <property name="jobDetail" ref="jobDetailSendFtp" /> <!-- 每隔2分钟触发一次 --> <property name="cronExpression" value="0 0/2 * * * ?" /> </bean> </beans>

 配置文件设置任务启动时间,系统每隔30秒去查询数据库。来设置另一个任务执行的时间。

2.1 java 代码   TaskCommand.java

 

package com.dvnchina.itv.advert.services.taskmanager; import java.io.Serializable; import java.text.ParseException; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.springframework.scheduling.quartz.CronTriggerBean; import com.dvnchina.itv.advert.dao.TaskManagerDao; import com.dvnchina.itv.advert.model.PlayItem; import com.dvnchina.itv.advert.model.Task; import com.dvnchina.itv.advert.services.TaskManagerService; import com.dvnchina.itv.advert.utils.Transform; import com.dvnchina.itv.advert.utils.config.ConfigureProperties; import com.dvnchina.itv.advert.utils.cron.CronExpConversion; /** * 任务命令执行类 * * @author Administrator * */ public class TaskCommand extends CronTriggerBean implements Serializable { private static final long serialVersionUID = 4052201904609332228L; private static final Log log = LogFactory.getLog(TaskCommand.class); private TaskManagerDao taskManagerDao; private TaskManagerService taskManagerService; // private static String file_p = DirectoryUtils.getSerlvetContextPath()+"/template/automanager.properties"; //private static String file_p =TaskCommand.class.getClassLoader().getResource("").getPath()+"configuration.properties"; private static ConfigureProperties CONFIG_P = ConfigureProperties.getInstance(); private Scheduler scheduler; /** * 构造方法 */ public TaskCommand() { } /** * @return 当前时间所在时段内的,或者当前时间在开始时间之前的 时段对象 */ public List<PlayItem> getCurrentPlayItemList() { List<PlayItem> playList = taskManagerDao.getAllByState(); List<PlayItem> reslutList = new ArrayList<PlayItem>(); if(playList != null && playList.size() > 0){ reslutList.add(playList.get(0)); } return reslutList; } /** * 设置另一个任务的触发的时间 * * @throws SchedulerException * @throws ParseException */ public void setCronTiggercronExpression() throws SchedulerException, ParseException{ List<PlayItem> playItemList = this.getCurrentPlayItemList(); if(null != playItemList && playItemList.size() > 0){ //取得时间的差值,提前多长时间发送 String advanceSendTime = CONFIG_P.getValueByKey("advance.send.time").trim(); long advanceTime = Long.valueOf(advanceSendTime)*1000; /** * 运行时可通过动态注入的scheduler得到trigger */ CronTriggerBean trigger = (CronTriggerBean) scheduler.getTrigger("cronTriggerSendFtp", Scheduler.DEFAULT_GROUP); String taskBeginTime = playItemList.get(0).getStartDate()+" "+playItemList.get(0).getStartTime(); long startTimeL = Transform.StringtoCalendar(taskBeginTime).getTimeInMillis(); //发送的时间点 taskBeginTime = Transform.CalendartoString(new Date(startTimeL-advanceTime)); String endTimeStr = playItemList.get(0).getEndDate() + " " + playItemList.get(0).getEndTime(); long endTimeL = Transform.StringtoCalendar(endTimeStr).getTimeInMillis(); long currentTimeL = new Date().getTime(); if(startTimeL < currentTimeL && currentTimeL <= endTimeL){ executeJobDetail(playItemList);//立即执行 }else{ String cronExpression = CronExpConversion.convertDateToCronExp(taskBeginTime); log.info("设置的发送时间:=# "+taskBeginTime+" #= 表达式为:==### "+cronExpression+" ### == "); String originConExpression = trigger.getCronExpression(); /** * 判断从DB中取得的任务时间(dbCronExpression)和现在的quartz线程中的任务时间(originConExpression)是否相等 * 如果相等,则表示用户并没有重新设定数据库中的任务时间,这种情况不需要重新rescheduleJob */ if(!originConExpression.equalsIgnoreCase(cronExpression)){ trigger.setCronExpression(cronExpression); scheduler.rescheduleJob("cronTriggerSendFtp", Scheduler.DEFAULT_GROUP, trigger); } } } } /** * 具体的job内容 * * @param playItemList 时段列表 */ protected void executeJobDetail(List<PlayItem> playItemList) { // OperatePropertyFile propertiesFile = new OperatePropertyFile(file_p); String isAutoSend = CONFIG_P.getValueByKey("auto.ftp.send").trim(); for (PlayItem bean : playItemList) { Integer itemId = bean.getId(); List<Task> taskList = taskManagerDao.getByPlayItem(itemId); if(taskList== null || taskList.size() ==0 ){ log.info("当前时间没有待发送的任务!"); }else{ Integer taskSate = 0; // 任务状态:任务状态(0代表未发送、1代表已发送)默认是0 Integer operateType = 0; // 是否需要归档 0-没有更新不需要归档 1-有更新需要归档 //0-0 0-1 1-0 1-1 String archiveFilePath = ""; if (null != taskList && taskList.size() > 0) { Task task = taskList.get(0); taskSate = task.getTaskState(); operateType = task.getOperateType(); archiveFilePath = task.getFinalPath(); } if (StringUtils.isNotBlank(archiveFilePath) && "1".equals(isAutoSend)) {// 设置了自动发送, if(taskSate==0 ){//此时仅仅执行发送,将taskSate-1 if(operateType == 0){ executeJobSendIsArchive(itemId, archiveFilePath, 0, new Date(), true); // 设置任务状态,1-已发送 }else if(1 == operateType){ executeJobSendIsArchive(itemId, archiveFilePath, 0, new Date(), true); // 先归档,归档设置任务状态,1-已发送 } }else if(taskSate ==1 ){ if(operateType == 1){ executeJobSendIsArchive(itemId, archiveFilePath, 0, new Date(), true); // 先归档,归档设置任务状态,1-已发送 } } } } } } /** * 执行归档,并发送,然后更行任务表的状态:taskState;和 updateDate 字段 * * @param itemId * 时段的ID * @param archiveFileDir * 素材归档的路径 * @param operateType * 操作类型: 是否需要归档 0-没有更新不需要归档 1-有更新需要归档 * @param taskState * 任务状态:任务状态(0代表未发送、1代表已发送)默认是0 * @param taskType * 任务的类型:0代表普通广告,1-开机广告 * @param updateTime * 更新时间 * @param isArchive * boolean : 是否归档 */ protected void executeJobSendIsArchive(Integer playItemId, String archiveFileDir,Integer taskType , Date updateTime,boolean isArchive) { if(isArchive){ if(taskType==0){ archiveFileDir = taskManagerService.archiveCommGenerateJS(playItemId); } if(taskType==1){ archiveFileDir = taskManagerService.archiveStart(playItemId); } } boolean flag = taskManagerService.checkArchiveFilesSize(taskType,archiveFileDir); if(flag){//审核通过 boolean isConenct = taskManagerService.checkFtpServer(); if(isConenct){//判断ftp是否连接 if(StringUtils.isNotBlank(archiveFileDir)){ boolean uploadResult = false; //上传结果 uploadResult = taskManagerService.sendTaskByPlayItemId(playItemId, taskType, archiveFileDir); if(uploadResult){//上传成功后更新数据 log.info("素材上传成功!开始更新任务表的数据!"); String updateDate = Transform.CalendartoString(updateTime); taskManagerService.updateTaskByItemId(playItemId, 1, 0, archiveFileDir, taskType, updateDate); log.info("素材上传成功!更新任务表的数据结束!"); } }else{ log.info("数据不正确,归档文件目录不存在,请查看任务表final_path 字段 查询条件playIetmId="+playItemId); } }else{ log.info("FTP服务端没有连接,素材不能上传。"); } }else{ log.info("审核没有通过,素材文件大小超过不符合规范"); } } public TaskManagerService getTaskManagerService() { return taskManagerService; } public void setTaskManagerService(TaskManagerService taskManagerService) { this.taskManagerService = taskManagerService; } public TaskManagerDao getTaskManagerDao() { return taskManagerDao; } public void setTaskManagerDao(TaskManagerDao taskManagerDao) { this.taskManagerDao = taskManagerDao; } public Scheduler getScheduler() { return scheduler; } public void setScheduler(Scheduler scheduler) { this.scheduler = scheduler; } public static void main(String[] args) { // Calendar calendar = Transform.StringtoCalendar("2012-03-13 20:10:00"); // long ss = calendar.getTimeInMillis(); // System.out.println(ss); // Date date = new Date(); // date.getTime(); // System.out.println(new Date().getTime() + "系统时间"); // System.out.println(); String beginTimeStr = "2012-03-12"+" "+"8:00:00"; long beginTimeL = Transform.StringtoCalendar(beginTimeStr).getTimeInMillis(); System.out.println(beginTimeL); Date date = new Date(beginTimeL); String ss = Transform.CalendartoString(date); System.out.println(ss); String beginTimeStr2 = "2012-03-12"+" "+"8:00:01"; long beginTimeL2 = Transform.StringtoCalendar(beginTimeStr2).getTimeInMillis(); System.out.println(beginTimeL2); Date date2 = new Date(beginTimeL2); String ss2 = Transform.CalendartoString(date2); System.out.println(ss2); System.out.println(beginTimeL2-beginTimeL); } }

 

2.2  PlayItemListenerCommand

 

该类实现ServletContextListener 接口目的是系统启动时处理一些时间,只要实现默认的两个方法就可以做到了。

 

package com.dvnchina.itv.advert.services.taskmanager; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.context.ApplicationContext; import org.springframework.web.context.WebApplicationContext; /** * 定时管理任务 * * @author Administrator */ public class PlayItemListenerCommand implements ServletContextListener { private static final Log log = LogFactory.getLog(PlayItemListenerCommand.class); private PlayItemListenerCommand queryPlayItemCommand ; private TaskCommand taskCommand ; /** * 默认的构造方法 */ public PlayItemListenerCommand() { } /** * 销毁实例 */ @Override public void contextDestroyed(ServletContextEvent arg0) { } /** * 系统启动时 * 初始化实例</br> * <li>加载当前时间时段内的时段对象</li> */ @Override public void contextInitialized(ServletContextEvent event) { long begin = System.currentTimeMillis(); ApplicationContext context = (ApplicationContext) event.getServletContext().getAttribute( WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); TaskCommand task = (TaskCommand) context.getBean("taskCommand"); task.getCurrentPlayItemList(); log.info("加载树时间(秒)" + (System.currentTimeMillis() - begin) / 1000); } /** * 触发器 触发的方法 */ public void timerQueryTimer(){ PlayItemListenerCommand command = queryPlayItemCommand; log.info("定时器启动,开始查询,设置发送时间。"); if(null != command){ command.executeCommand(); }else{ log.error("查询错误"); } } /** * 当前时间所在时段内的对象 */ public void executeCommand(){ try { taskCommand.setCronTiggercronExpression(); } catch (Exception e) { log.info("查询错误"); e.printStackTrace(); } } public PlayItemListenerCommand getQueryPlayItemCommand() { return queryPlayItemCommand; } public void setQueryPlayItemCommand(PlayItemListenerCommand queryPlayItemCommand) { this.queryPlayItemCommand = queryPlayItemCommand; } public TaskCommand getTaskCommand() { return taskCommand; } public void setTaskCommand(TaskCommand taskCommand) { this.taskCommand = taskCommand; } }

 

 2.3 SendFtpListenerCommand

package com.dvnchina.itv.advert.services.taskmanager; import java.text.ParseException; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.quartz.Scheduler; import org.quartz.SchedulerException; import com.dvnchina.itv.advert.dao.TaskDao; import com.dvnchina.itv.advert.model.PlayItem; public class SendFtpListenerCommand { private static final long serialVersionUID = -3893344013520261515L; private static final Log log = LogFactory.getLog(SendFtpListenerCommand.class); private TaskDao taskDao; private TaskCommand taskCommand; /** * 设值注入,通过setter方法传入被调用者的实例scheduler */ private Scheduler scheduler; public void sendAdvertFolderJob() throws SchedulerException, ParseException { List<PlayItem> playItemList = taskCommand.getCurrentPlayItemList(); if (null != playItemList && playItemList.size() > 0) { log.info("自动发送任务开始执行"); // 下面是具体的job内容,可自行设置 taskCommand.executeJobDetail(playItemList); log.info("自动发送任务结束"); } } public Scheduler getScheduler() { return scheduler; } public void setScheduler(Scheduler scheduler) { this.scheduler = scheduler; } public TaskDao getTaskDao() { return taskDao; } public void setTaskDao(TaskDao taskDao) { this.taskDao = taskDao; } public TaskCommand getTaskCommand() { return taskCommand; } public void setTaskCommand(TaskCommand taskCommand) { this.taskCommand = taskCommand; } }

  

 

 3. 工具类   时间字符串转换为 cronExpression

 

package com.dvnchina.itv.advert.utils.cron; import java.text.SimpleDateFormat; import java.util.Date; import org.apache.commons.lang.StringUtils; /** * 页面设置转为UNIX cron expressions 转换类 CronExpConversion */ public class CronExpConversion { public static void main(String[] args) { String ss = "2012-03-07 09:14:19"; convertDateToCronExp(ss); } /** * 页面设置转为UNIX cron expressions 转换算法 * * @param dateSring (n-y-r s:f:m) 2012-03-07 09:14:19 * @return cron expression */ public static String convertDateToCronExp(String dateSring) { String cronEx = ""; if(StringUtils.isNotBlank(dateSring)){ StringBuffer buffer = new StringBuffer(); String date[] = dateSring.split(" "); String nyr = date[0]; //年-月-日 String[] ymd = nyr.split("-"); //{year,month,day} String year = ymd[0]; String month = ymd[1]; String day = ymd[2]; String sfm = date[1]; //时:分:秒 String[] hms = sfm.split(":");//hour:minute:second String hour = hms[0]; String minute = hms[1]; String second = hms[2]; buffer.append(Integer.valueOf(second)); buffer.append(CronExRelated._BLANKSPACE); buffer.append(Integer.valueOf(minute)); buffer.append(CronExRelated._BLANKSPACE); buffer.append(Integer.valueOf(hour)); buffer.append(CronExRelated._BLANKSPACE); buffer.append(Integer.valueOf(day)); buffer.append(CronExRelated._BLANKSPACE); buffer.append(Integer.valueOf(month)); buffer.append(CronExRelated._BLANKSPACE); buffer.append(CronExRelated._ANY); buffer.append(CronExRelated._BLANKSPACE); buffer.append(Integer.valueOf(year)); cronEx = buffer.toString(); } return cronEx; } /** * 页面设置转为UNIX cron expressions 转换算法 * * @param date java.util.date * @return cron expression */ public static String convertDateToCronExp(Date date) { String cronEx = ""; if(date != null){ SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); sdf.format(date); cronEx=convertDateToCronExp(sdf.format(date)); } return cronEx; } /** * 页面设置转为UNIX cron expressions 转换算法 * * @param everyWhat * @param commonNeeds * 包括 second minute hour * @param monthlyNeeds * 包括 第几个星期 星期几 * @param weeklyNeeds * 包括 星期几 * @param userDefinedNeeds * 包括具体时间点 * @return cron expression */ public static String convertDateToCronExp(String everyWhat, String[] commonNeeds, String[] monthlyNeeds, String weeklyNeeds, String userDefinedNeeds) { String cronEx = ""; return cronEx; } }

 

 

 

package com.dvnchina.itv.advert.utils.cron; import java.util.HashMap; import java.util.Map; /** * 这个类封装了一些Quartz时间规则的常量,便于自己使用,定义比较灵活,可以根据您的具体情况扩展。 Quartz时间规则常量类 CronExRelated * * @author chennaidong */ @SuppressWarnings("unchecked") public class CronExRelated { public static final String _BLANKSPACE=" "; /** * 使用星号(*) 指示着你想在这个域上包含所有合法的值 */ public static final String _EVERY = "*"; /** * ? 号只能用在日和周域上,但是不能在这两个域上同时使用。 */ public static final String _ANY = "?"; /** * 中划线 (-) 用于指定一个域的范围。域的值不允许回卷,所以像 50-10 这样的值是不允许的 */ public static final String _RANGES = "-"; /** * 斜杠 (/) 是用于时间表的递增的。 */ public static final String _INCREMENTS = "/"; /** * 逗号 (,) 是用来在给某个域上指定一个值列表的。表达式样例:0 0,15,30,45 * * * ? 意义:每刻钟触发一次 trigger */ public static final String _ADDITIONAL = ","; /** * L 说明了某域上允许的最后一个值。它仅被日和周域支持。 */ public static final String _LAST = "L"; /** * W 字符代表着平日 (Mon-Fri),并且仅能用于日域中。 */ public static final String _WEEKDAY = "W"; /** * # 字符仅能用于周域中。它用于指定月份中的第几周的哪一天。例如,如果你指定周域的值为 6#3,它意思是某月的第三个周五 (6=星期五,#3意味着月份中的第三周)。另一个例子 2#1 意思是某月的第一个星期一 (2=星期一,#1意味着月份中的第一周)。注意,假如你指定 #5,然而月份中没有第 5 周,那么该月不会触发。 */ public static final String _THENTH = "#"; /** * 日历 */ public static final String _CALENDAR = "calendar"; public static final String _TYPE = "type"; /** * 0 0 6 ? * 1#1 ? monthly 0 0 6 ? * 1 ? weekly 0 0 6 30 7 ? 2006 useDefined */ static String[] headTitle = { "TYPE", "SECONDS", "MINUTES", "HOURS", "DAYOFMONTH", "MONTH", "DAYOFWEEK", "YEAR" }; /** * cron expression special characters Map specialCharacters */ public static Map specialCharacters; static { specialCharacters = new HashMap(10); specialCharacters.put(_EVERY, "*"); specialCharacters.put(_ANY, "?"); specialCharacters.put(_RANGES, "-"); specialCharacters.put(_INCREMENTS, "/"); specialCharacters.put(_ADDITIONAL, ","); specialCharacters.put(_LAST, "L"); specialCharacters.put(_WEEKDAY, "W"); specialCharacters.put(_THENTH, "#"); specialCharacters.put(_CALENDAR, "C"); specialCharacters.put(_TYPE, headTitle); } public static void set(String ex, int index) { ((String[]) specialCharacters.get(_TYPE))[index] = ex; } }


  

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics