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

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







内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://bjspace.net/post/42

相关推荐

发表吐槽

你肿么看?

你还可以输入 250 / 250 个字

嘻嘻 大笑 可怜 吃惊 抛媚眼 调皮 鄙视 示爱 哭 开心 偷笑 嘘 奸笑 委屈 抱抱 Dog 大兵 威武

评论信息框

吃奶的力气提交吐槽中...


既然没有吐槽,那就赶紧抢沙发吧!