Spring实现可动态修改时间定时任务
我正在做的一个项目最近有个需求,使用一些校验功能需要在系统空闲时间启动自动校验,也需要有客户自定义一个校验时间启动校验,所以...目前最简单的实现就是使用定时任务咯:
首先了解一下,定时任务有三种技术实现方式:java自带的Timer类,可以让程序保持一定频度执行,但是无法按照某个时间执行;quartz,一个功能强大的调度器,是由java编写的作业调度框架,简单易用;spring3.0之后自带task,轻量级Quartz。
梳理实现过程:
(1)pom文件引入需要jar包:这里spring版本为4.0.9.RELEASE,quartz版本为1.6.2
(2)xml文件配置执行策略,执行的触发器,并将触发器注入到任务调度器中
<!-- 定时任务配置 scheduler 方式 --> <context:component-scan base-package="org.jeecgframework.core.timer" /> <task:executor id="executor" pool-size="5" /> <task:scheduler id="scheduler" pool-size="10" /> <task:annotation-driven executor="executor" scheduler="scheduler" /> <!-- 定时任务配置 smsSendTask 可配置到管理界面 --> <bean id="smsSendTaskJob" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject" ref="smsSendTask" /> //要执行的发送邮件的方法 <property name="targetMethod" value="run" /> <property name="concurrent" value="true" /> </bean> <bean id="smsSendTaskCronTrigger" class="org.jeecgframework.core.timer.DataBaseCronTriggerBean"> <property name="jobDetail" ref="smsSendTaskJob" /> <property name="cronExpression" value="0 0/1 * * * ?" /> //每分钟执行一次 </bean> <!-- 定时任务调度器 org.jeecgframework.core.timer.DataBaseSchedulerFactoryBean--> <bean id="schedulerFactory" lazy-init="false" autowire="no" class="org.jeecgframework.web.system.util.SchedulerFactoryBeanWithShutdownDelay"> <property name="triggers"> <list> <ref bean="smsSendTaskCronTrigger" /> </list> </property> </bean>
由上面配置可知,定时任务是由spring注入的方式,因此要执行的方法直接按照spring的标准就可以 了。这样定时任务就算完成了,系统启动后,会按照执行策略动态执行。
(3)实现定时任务管理过程:
(3.1)定义定时间任务实体(描述任务信息):
@Entity @Table(name = "t_s_timetask", schema = "") @DynamicUpdate(true) @DynamicInsert(true) @SuppressWarnings("serial") public class TSTimeTaskEntity implements java.io.Serializable { /**id*/ private java.lang.String id; /**任务ID*/ private java.lang.String taskId; /**任务描述*/ private java.lang.String taskDescribe; /**cron表达式*/ private java.lang.String cronExpression; /**是否生效了0未生效,1生效了*/ private java.lang.String isEffect; /**是否运行0停止,1运行*/ private java.lang.String isStart; /**创建时间*/ private java.util.Date createDate; /**创建人ID*/ private java.lang.String createBy; /**创建人名称*/ private java.lang.String createName; /**修改时间*/ private java.util.Date updateDate; /**修改人ID*/ private java.lang.String updateBy; /**修改人名称*/ private java.lang.String updateName; /**执行的job名称*/ private java.lang.String jobeName; {get;set} }(3.2)前台实现效果:
![]()
任务id要与xml任务调度器配置一致。
(3.3)controller端实现:
<code class="language-java">@Controller @RequestMapping("/timeTaskController") public class TimeTaskController extends BaseController { @Autowired private TimeTaskServiceI timeTaskService; @Autowired private DynamicTask dynamicTask; @Autowired private SystemService systemService; /** * 定时任务管理列表 页面跳转 * @return */ @RequestMapping(params = "timeTask") public ModelAndView timeTask(HttpServletRequest request) { return new ModelAndView("system/timetask/timeTaskList"); } /** * easyui AJAX请求数据 * @param request * @param response * @param dataGrid * @param user */ @RequestMapping(params = "datagrid") public void datagrid(TSTimeTaskEntity timeTask,HttpServletRequest request, HttpServletResponse response, DataGrid dataGrid) { CriteriaQuery cq = new CriteriaQuery(TSTimeTaskEntity.class, dataGrid); //查询条件组装器 org.jeecgframework.core.extend.hqlsearch.HqlGenerateUtil.installHql(cq, timeTask, request.getParameterMap()); this.timeTaskService.getDataGridReturn(cq, true); TagUtil.datagrid(response, dataGrid); } /** * 删除定时任务管理 * @return */ @RequestMapping(params = "del") @ResponseBody public AjaxJson del(TSTimeTaskEntity timeTask, HttpServletRequest request) { String message = null; AjaxJson j = new AjaxJson(); timeTask = systemService.getEntity(TSTimeTaskEntity.class, timeTask.getId()); message = "定时任务管理删除成功"; timeTaskService.delete(timeTask); systemService.addLog(message, Globals.Log_Type_DEL, Globals.Log_Leavel_INFO); j.setMsg(message); return j; } /** * 添加定时任务管理 * @param ids * @return */ @RequestMapping(params = "save") @ResponseBody public AjaxJson save(TSTimeTaskEntity timeTask, HttpServletRequest request) { String message = null; AjaxJson j = new AjaxJson(); CronTrigger trigger = new CronTrigger(); try { trigger.setCronExpression(timeTask.getCronExpression()); } catch (ParseException e) { j.setMsg("Cron表达式错误"); return j; } if (StringUtil.isNotEmpty(timeTask.getId())) { message = "定时任务管理更新成功"; TSTimeTaskEntity t = timeTaskService.get(TSTimeTaskEntity.class, timeTask.getId()); try { if(!timeTask.getCronExpression().equals(t.getCronExpression())){ timeTask.setIsEffect("0"); } MyBeanUtils.copyBeanNotNull2Bean(timeTask, t); timeTaskService.saveOrUpdate(t); systemService.addLog(message, Globals.Log_Type_UPDATE, Globals.Log_Leavel_INFO); } catch (Exception e) { e.printStackTrace(); message = "定时任务管理更新失败"; } } else { message = "定时任务管理添加成功"; timeTaskService.save(timeTask); systemService.addLog(message, Globals.Log_Type_INSERT, Globals.Log_Leavel_INFO); } j.setMsg(message); return j; } /** * 定时任务管理列表页面跳转 * @return */ @RequestMapping(params = "addorupdate") public ModelAndView addorupdate(TSTimeTaskEntity timeTask, HttpServletRequest req) { if (StringUtil.isNotEmpty(timeTask.getId())) { timeTask = timeTaskService.getEntity(TSTimeTaskEntity.class, timeTask.getId()); req.setAttribute("timeTaskPage", timeTask); } return new ModelAndView("system/timetask/timeTask"); } /** * 更新任务时间使之生效 */ @RequestMapping(params = "updateTime") @ResponseBody public AjaxJson updateTime(TSTimeTaskEntity timeTask, HttpServletRequest request) { AjaxJson j = new AjaxJson(); timeTask = timeTaskService.get(TSTimeTaskEntity.class, timeTask.getId()); boolean isUpdate = dynamicTask.updateCronExpression(timeTask.getTaskId() , timeTask.getCronExpression()); if(isUpdate){ timeTask.setIsEffect("1"); timeTask.setIsStart("1"); timeTaskService.updateEntitie(timeTask); } j.setMsg(isUpdate?"定时任务管理更新成功":"定时任务管理更新失败"); return j; } /** * 启动或者停止任务 */ @RequestMapping(params = "startOrStopTask") @ResponseBody public AjaxJson startOrStopTask(TSTimeTaskEntity timeTask, HttpServletRequest request) { AjaxJson j = new AjaxJson(); boolean isStart = timeTask.getIsStart().equals("1"); timeTask = timeTaskService.get(TSTimeTaskEntity.class, timeTask.getId()); boolean isSuccess = false; try { isSuccess = dynamicTask.startOrStop(timeTask.getTaskId() ,isStart); } catch (Exception e) { j.setMsg(isSuccess?"定时任务管理更新成功":"定时任务管理更新失败"); } if(isSuccess){ timeTask.setIsStart(isStart?"1":"0"); timeTaskService.updateEntitie(timeTask); systemService.addLog((isStart?"开启任务":"停止任务")+timeTask.getTaskId(), Globals.Log_Type_UPDATE, Globals.Log_Leavel_INFO); } j.setMsg(isSuccess?"定时任务管理更新成功":"定时任务管理更新失败"); return j; } } </code>动态调整定时任务:/** * 动态任务,用以动态调整Spring的任务 * @version 1.0 */ @Service(value="dynamicTask") public class DynamicTask { private static Logger logger = Logger.getLogger(DynamicTask.class); @Resource private Scheduler schedulerFactory; /** * 更新定时任务的触发表达式 * * @param triggerName * 触发器名字 * @param start * 触发表达式 * @return 成功则返回true,否则返回false */ public boolean startOrStop(String triggerName, boolean start) { try { CronTrigger trigger = (CronTrigger) getTrigger(triggerName, Scheduler.DEFAULT_GROUP); if(start){ schedulerFactory.resumeTrigger(trigger.getName(), trigger.getGroup()); logger.info("trigger the start successfully!!"); }else{ schedulerFactory.pauseTrigger(trigger.getName(), trigger.getGroup()); logger.info("trigger the pause successfully!!"); } return true; } catch (SchedulerException e) { logger.error("Fail to reschedule. " + e); return false; } } /** * 更新定时任务的触发表达式 * * @param triggerName * 触发器名字 * @param cronExpression * 触发表达式 * @return 成功则返回true,否则返回false */ public boolean updateCronExpression(String triggerName, String cronExpression) { try { CronTrigger trigger = (CronTrigger) getTrigger(triggerName, Scheduler.DEFAULT_GROUP); if (trigger == null) { return false; } if (StringUtils.equals(trigger.getCronExpression(), cronExpression)) { logger.info("cronExpression is same with the running Schedule , no need to update."); return true; } trigger.setCronExpression(cronExpression); schedulerFactory.rescheduleJob(trigger.getName(), trigger.getGroup(), trigger); updateSpringMvcTaskXML(trigger,cronExpression); logger.info("Update the cronExpression successfully!!"); return true; } catch (ParseException e) { logger.error("The new cronExpression - " + cronExpression + " not conform to the standard. " + e); return false; } catch (SchedulerException e) { logger.error("Fail to reschedule. " + e); return false; } } /** * 获取触发器 * * @param triggerName * 触发器名字 * @param groupName * 触发器组名字 * @return 对应Trigger */ private Trigger getTrigger(String triggerName, String groupName) { Trigger trigger = null; if (StringUtils.isBlank(groupName)) { logger.warn("Schedule Job Group is empty!"); return null; } if (StringUtils.isBlank(triggerName)) { logger.warn("Schedule trigger Name is empty!"); return null; } try { trigger = schedulerFactory.getTrigger(triggerName, groupName); } catch (SchedulerException e) { logger.warn("Fail to get the trigger (triggerName: " + triggerName + ", groupName : " + groupName + ")"); return null; } if (trigger == null) { logger.warn("Can not found the trigger of triggerName: " + triggerName + ", groupName : " + groupName); } return trigger; } /** * 更新spring-mvc-timeTask.xml 配置文件 * @param trigger * @param cronExpression */ @SuppressWarnings("unchecked") public synchronized static void updateSpringMvcTaskXML(CronTrigger trigger, String cronExpression) { Document document = null; File file = null; SAXReader saxReader = new SAXReader(); try { URI url = DynamicTask.class.getClassLoader().getResource("spring-mvc-timeTask.xml").toURI(); file = new File(url.getPath()); document = saxReader.read(new FileInputStream(file)); } catch (Exception e) { logger.error("读取系统中用到的SQL 语句XML出错"); throw new RuntimeException("---------读取spring-mvc-timeTask.xml文件出错:" + e.getMessage()); } Element root = document.getRootElement(); List<Element> beans = root.elements(); for (Element bean : beans) { if(bean.attribute("id")!=null&& bean.attribute("id").getValue().equals(trigger.getName())){ beans = bean.elements(); for (Element temp : beans) { if(temp.attribute("name")!=null&& temp.attribute("name").getValue().equals("cronExpression")){ temp.attribute("value").setValue(cronExpression); break; } } break; } } XMLWriter fileWriter = null; try { OutputFormat xmlFormat = OutputFormat.createPrettyPrint(); xmlFormat.setEncoding("utf-8"); fileWriter = new XMLWriter(new FileOutputStream(file),xmlFormat); fileWriter.write(document); } catch (IOException e) { e.printStackTrace(); }finally{ try { fileWriter.close(); } catch (IOException e) { e.printStackTrace(); } } } }在产品中,定时任务主要应用于统计数据,每日,每季度统计数据报表!是否创建会员用户到期情况等。出现内存溢出时解决方案:http://blog.csdn.net/dslztx/article/details/47276953
学习参考资料:《Spring 整合 Quartz 实现动态定时任务》
文章demo:http://download.csdn.net/detail/u012466304/9906761
转自:https://blog.csdn.net/whp15369657805/article/details/75647362
发表吐槽
你肿么看?
既然没有吐槽,那就赶紧抢沙发吧!