spring实现可动态修改时间定时任务

来源:互联网 发布:查看centos系统版本 编辑:程序博客网 时间:2024/06/06 20:56

            前端时间开发接触了一个开源框架jeecg,里面封装了spring与quartz整合的定时任务实现方式。因为之前尝试过单纯使用quartz来实现定时任务,遇到一些问题,比如,无法通过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端实现:

          

@Controller@RequestMapping("/timeTaskController")public class TimeTaskController extends BaseController {@Autowiredprivate TimeTaskServiceI timeTaskService;@Autowiredprivate DynamicTask dynamicTask;@Autowiredprivate 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")@ResponseBodypublic 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")@ResponseBodypublic 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")@ResponseBodypublic 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")@ResponseBodypublic 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;}}

         动态调整定时任务:

/** * 动态任务,用以动态调整Spring的任务 * @author JueYue * @date 2013-9-20 * @version 1.0 */@Service(value="dynamicTask")public class DynamicTask {private static Logger logger = Logger.getLogger(DynamicTask.class);@Resourceprivate 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

阅读全文
1 0