摘要:在项目的管理功能中,对定时任务的管理有时会很常见。但一般定时任务配置都在xml中完成,包括cronExpression表达式,十分的方便。但是如果我的任务信息是保存在数据库的,想要动态的初始化,还有就是任务较多的时候不是得有一大堆的xml配置?或者说我要修改一下trigger的表达式,使原来5秒运行一次的任务变成10秒运行一次,或者说我要控制定时任务的 “ 暂停 ” 呢?暂停之后又要在某个时间点 “ 重启 ” 该定时任务呢?或者说直接 “ 删除 ” 该定时任务呢?要 改变某定时任务的触发时间呢?这时问题就来了,试过在配置文件中不传入cronExpression等参数,但是启动时就报错了,难道我每次都修改xml文件然后重启应用吗,这显然不合适的。
最理想的是在与spring整合的同时又能实现动态任务的添加、删除及修改配置,而且不需要重启应用。
首先我们来回顾一下spring中使用quartz的配置代码:
<!-- 使用MethodInvokingJobDetailFactoryBean,任务类可以不实现Job接口,通过targetMethod指定调用方法--> <bean id="taskJob" class="com.tyyd.dw.task.DataConversionTask"/> <bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="group" value="job_work"/> <property name="name" value="job_work_name"/> <!--false表示等上一个任务执行完后再开启新的任务--> <property name="concurrent" value="false"/> <property name="targetObject"> <ref bean="taskJob"/> </property> <property name="targetMethod"> <value>execute</value> </property> </bean> <!-- 调度触发器 --> <bean id="myTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> <property name="name" value="work_default_name"/> <property name="group" value="work_default"/> <property name="jobDetail"> <ref bean="jobDetail" /> </property> <property name="cronExpression"> <value>0/5 * * * * ?</value> </property> </bean> <!-- 调度工厂 --> <bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="myTrigger"/> </list> </property> </bean>
所有的配置都在xml中完成,包括cronExpression表达式,十分的方便。但是如果定时任务一多并且需要手动变化时,就得有一大堆的xml配置,不方便管理。
于是在设计时我想到以下几点
1、减少spring的配置文件。
2、用户可以通过页面等方式添加、启用、禁用某个任务。
3、用户可以修改某个已经在运行任务的运行时间表达式,即CronExpression。
4、为方便维护,简化任务的运行调用处理,任务的运行入口即Job实现类最好只有一个,该Job运行类相当于工厂类,在实际调用时把任务的相关信息通过参数方式传入,由该工厂类根据任务信息来具体执行需要的操作。
就像如下图所示:
1、可在页面直接查看任务详情
2、可添加、修改
3、可立即执行,并查看执行详情
在上面的思路下来进行我们的开发吧。
一、初始化用的数据库脚本
SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for task_detail -- ---------------------------- DROP TABLE IF EXISTS `task_detail`; CREATE TABLE `task_detail` ( `job_id` int(100) NOT NULL AUTO_INCREMENT, `job_name` varchar(200) DEFAULT NULL COMMENT '任务名称', `job_group` varchar(100) DEFAULT NULL COMMENT '任务分组', `job_status` varchar(5) DEFAULT NULL COMMENT '任务状态 0禁用 1启用 2删除', `cron_expression` varchar(200) DEFAULT NULL COMMENT '任务运行时间表达式', `bean_class` varchar(300) DEFAULT NULL COMMENT '任务执行类', `execute_method` varchar(100) DEFAULT NULL COMMENT '任务执行方法', `create_time` date DEFAULT NULL COMMENT '任务创建时间', `update_time` date DEFAULT NULL COMMENT '任务更新时间', `job_desc` varchar(500) DEFAULT NULL COMMENT '任务描述', PRIMARY KEY (`job_id`) ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of task_detail -- ---------------------------- INSERT INTO `task_detail` VALUES ('9', '测试手动设置任务', 'testQuartzTask', null, '0 0 1 * * ?', 'com.zealer.cps.task.executor.TestQuartzTask', 'printOneWord', '2017-06-22', '2017-06-22', '打印一句话');
然后创建对应的实体类ScheduleJob.java
1 package com.zealer.cps.task.value; 2 3 /** 4 * 定时任务封装类 5 * @author xiaohe 6 */ 7 public class ScheduleJob 8 { 9 /** 任务id */ 10 private int jobId; 11 12 /** 任务名称 */ 13 private String jobName; 14 15 /** 任务分组 */ 16 private String jobGroup; 17 18 /** 任务状态 0禁用 1启用 2删除*/ 19 private String jobStatus; 20 21 /** 任务运行时间表达式 */ 22 private String cronExpression; 23 24 /** 任务执行类 */ 25 private String beanClass; 26 27 /** 任务执行方法 */ 28 private String executeMethod; 29 30 /** 任务创建时间 */ 31 private String createTime; 32 33 /** 任务更新时间 */ 34 private String updateTime; 35 36 /** 任务描述 */ 37 private String jobDesc; 38 39 //set与get方法这里省略,大家可以自己生成 40 ...... 41 }
二、spring配置文件spring.xml
<bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" />
然后在web.xml加入
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring.xml</param-value> </context-param>
三、编写任务控制器TaskController.java
1 package com.zealer.cps.task.controller; 2 3 import java.text.SimpleDateFormat; 4 import java.util.Date; 5 import java.util.HashMap; 6 import java.util.Map; 7 8 import javax.annotation.Resource; 9 import javax.servlet.http.HttpServletRequest; 10 11 import org.slf4j.Logger; 12 import org.slf4j.LoggerFactory; 13 import org.springframework.http.HttpStatus; 14 import org.springframework.http.ResponseEntity; 15 import org.springframework.stereotype.Controller; 16 import org.springframework.ui.Model; 17 import org.springframework.web.bind.annotation.ModelAttribute; 18 import org.springframework.web.bind.annotation.RequestMapping; 19 import org.springframework.web.bind.annotation.RequestMethod; 20 import org.springframework.web.bind.annotation.RequestParam; 21 import org.springframework.web.bind.annotation.ResponseBody; 22 import org.springframework.web.servlet.mvc.support.RedirectAttributes; 23 import com.zealer.cps.base.annotation.Log; 24 import com.zealer.cps.base.constant.AppConstant; 25 import com.zealer.cps.base.controller.BaseController; 26 import com.zealer.cps.base.message.SuccessActionResult; 27 import com.zealer.cps.base.model.vo.PaginationBean; 28 import com.zealer.cps.base.util.HttpUtils; 29 import com.zealer.cps.task.manage.JobMethod; 30 import com.zealer.cps.task.service.QuartzJobService; 31 import com.zealer.cps.task.value.ScheduleJob; 32 import com.zealer.cps.task.value.ScheduleJobItem; 33 import com.zealer.cps.task.value.ScheduleJobReq; 34 35 @Controller 36 @RequestMapping( "/taskController" ) 37 public class TaskController extends BaseController 38 { 39 private static Logger log = LoggerFactory.getLogger( TaskController.class ); 40 41 @Resource( name = "quartzJobService" ) 42 private QuartzJobService quartzJobService; 43 44 @Resource( name = "JobMethod" ) 45 private JobMethod jobMethod; 46 47 @RequestMapping( "/list" ) 48 @Log( "任务列表" ) 49 public String listJob( @ModelAttribute("job") ScheduleJobReq jobReq, Model model, HttpServletRequest request ) 50 { 51 PaginationBean<ScheduleJob> pb = quartzJobService.getJobsByPage( jobReq ); 52 try { 53 pb.setUrl( HttpUtils.getRequestInfo( request, true ) ); 54 } catch ( Exception e ) { 55 log.error( "get request url error", e ); 56 } 57 model.addAttribute( "pb", pb ); 58 return("task/taskList"); 59 } 60 61 62 /** 63 * 立即执行定时任务 64 * @param job 任务实体 65 * @param model 66 * @return 67 */ 68 @ResponseBody 69 @RequestMapping( value = "/executeJob", produces = "application/json;charset=utf-8" ) 70 @Log( "立即执行任务" ) 71 public ResponseEntity<Map<String, Object> > executeJob( ScheduleJob job, Model model ) 72 { 73 jobMethod.runJobNow( job ); 74 return(new ResponseEntity<Map<String, Object> > ( new HashMap<String, Object>(), HttpStatus.OK ) ); 75 } 76 77 78 /** 79 * 跳转到添加定时任务的页面 80 * @param model 81 * 储存结果的实体 82 */ 83 @RequestMapping( value = "/addJob", method = RequestMethod.GET ) 84 @Log( "初始化添加表单" ) 85 public String addForm( Model model ) 86 { 87 model.addAttribute( "job", new ScheduleJob() ); 88 return("task/addJob"); 89 } 90 91 92 /** 93 * 添加定时任务记录 94 * @param job 任务实体 95 */ 96 @RequestMapping( value = "/addJob", method = RequestMethod.POST ) 97 @Log( "新增操作员" ) 98 public String addUser( @ModelAttribute("job") ScheduleJob job, RedirectAttributes ra, Model model, 99 HttpServletRequest request ) 100 { 101 SimpleDateFormat format = new SimpleDateFormat( AppConstant.DATE_FORMAT_YYYYMMDDHHMMSS ); 102 job.setCreateTime( format.format( new Date() ) ); 103 quartzJobService.inserJob( job ); 104 ra.addFlashAttribute( "actionResult", new SuccessActionResult() ); 105 return("redirect:/taskController/list.do"); 106 } 107 108 109 /** 110 * 初始化修改表单 111 * @param jobId 112 * @return 跳转地址 113 */ 114 @RequestMapping( value = "/updateJob", method = RequestMethod.GET ) 115 @Log( "初始化修改表单" ) 116 public String updateForm( @RequestParam("id") Integer jobId, Model model, 117 HttpServletRequest request ) 118 { 119 ScheduleJob job = quartzJobService.getScheduleJobById( jobId ); 120 model.addAttribute( "job", job ); 121 return("task/updateJob"); 122 } 123 124 125 /** 126 * 修改定时任务记录信息 127 * @param job 待修改的操作员实体 128 * @param model 封装处理结果的实体 129 * @param request 请求对象 130 * @return 跳转地址 131 */ 132 @RequestMapping( value = "/updateJob", method = RequestMethod.POST ) 133 @Log( "修改定时任务" ) 134 public String updateJob( @ModelAttribute ScheduleJob job, RedirectAttributes ra, Model model, 135 HttpServletRequest request ) 136 { 137 SimpleDateFormat format = new SimpleDateFormat( AppConstant.DATE_FORMAT_YYYYMMDDHHMMSS ); 138 job.setUpdateTime( format.format( new Date() ) ); 139 quartzJobService.updateJob( job ); 140 ra.addFlashAttribute( "actionResult", new SuccessActionResult() ); 141 return("redirect:/taskController/list.do"); 142 } 143 144 145 /** 146 * 删除一条定时任务记录信息 147 * @return 148 */ 149 @RequestMapping( value = "/deleteJob" ) 150 @Log( "删除任务" ) 151 public String deleteJob( @RequestParam("id") int jobId, RedirectAttributes ra ) 152 { 153 quartzJobService.deleteJob( jobId ); 154 ra.addFlashAttribute( "actionResult", new SuccessActionResult() ); 155 return("redirect:/taskController/list.do"); 156 } 157 158 159 /** 160 * 校验执行任务的表达式是否正确 161 * @param expression 162 * @return 163 */ 164 @ResponseBody 165 @RequestMapping( value = "/checkExp", produces = "application/json;charset=utf-8" ) 166 @Log( "校验任务表达式" ) 167 public ResponseEntity<Map<String, Object> > checkExpression( String expression ) 168 { 169 Map<String, Object> map = new HashMap<String, Object>(); 170 map.put( AppConstant.SYSTEM_JSON_CODE, AppConstant.SYSTEM_JSON_ERROR ); 171 if ( jobMethod.checkCron( expression ) ) 172 { 173 map.put( AppConstant.SYSTEM_JSON_CODE, AppConstant.SYSTEM_JSON_SUCCESS ); 174 } 175 return(new ResponseEntity<Map<String, Object> > ( map, HttpStatus.OK ) ); 176 } 177 178 179 /** 180 * 某个定时任务下的所有执行记录信息列表 181 * @param jobReq 182 * @return 183 */ 184 @RequestMapping( "/itemJob" ) 185 @Log( "任务执行信息列表" ) 186 public String executeJobList( @ModelAttribute("job") ScheduleJobReq jobReq, int jobId, 187 Model model, HttpServletRequest request ) 188 { 189 PaginationBean<ScheduleJobItem> pb = quartzJobService.getJobItemsByPage( jobId, jobReq ); 190 try { 191 pb.setUrl( HttpUtils.getRequestInfo( request, true ) ); 192 } catch ( Exception e ) { 193 log.error( "get request url error", e ); 194 } 195 model.addAttribute( "pb", pb ); 196 model.addAttribute( "jobId", jobId ); 197 return("task/taskItemList"); 198 } 199 }
四、编写任务运行入口,即JobMethod.java
1 package com.zealer.cps.task.manage; 2 3 import java.util.List; 4 5 import javax.annotation.Resource; 6 7 import org.apache.commons.logging.Log; 8 import org.apache.commons.logging.LogFactory; 9 import org.quartz.CronScheduleBuilder; 10 import org.quartz.CronTrigger; 11 import org.quartz.JobBuilder; 12 import org.quartz.JobDetail; 13 import org.quartz.JobKey; 14 import org.quartz.Scheduler; 15 import org.quartz.SchedulerException; 16 import org.quartz.TriggerBuilder; 17 import org.quartz.TriggerKey; 18 import org.springframework.stereotype.Component; 19 20 import com.zealer.cps.task.QuartzJobFactory; 21 import com.zealer.cps.task.service.QuartzJobService; 22 import com.zealer.cps.task.value.ScheduleJob; 23 24 25 /** 26 * 提供Job任务相关的方法 27 * @author xiaohe 28 */ 29 @Component( "JobMethod" ) 30 public class JobMethod 31 { 32 @Resource( name = "schedulerFactoryBean" ) 33 private Scheduler scheduler; 34 35 @Resource( name = "quartzJobService" ) 36 private QuartzJobService quartzJobService; 37 38 private static Log log = LogFactory.getLog( JobMethod.class ); 39 40 41 /** 42 * 任务框架初始化方法 43 * @throws 44 */ 45 public void init() 46 { 47 /* 从数据库获得所有的任务信息记录 */ 48 List<ScheduleJob> jobList = quartzJobService.getAllJobs(); 49 50 if ( jobList != null && !jobList.isEmpty() ) 51 { 52 for ( ScheduleJob scheduleJob : jobList ) 53 { 54 /* 判断任务状态,是否为执行状态 */ 55 56 TriggerKey triggerKey = TriggerKey.triggerKey( scheduleJob 57 .getJobName(), scheduleJob.getJobGroup() ); 58 CronTrigger trigger; 59 try 60 { 61 trigger = (CronTrigger) scheduler.getTrigger( triggerKey ); 62 if ( null == trigger ) 63 { 64 JobDetail jobDetail = JobBuilder.newJob( 65 QuartzJobFactory.class ).withIdentity( 66 scheduleJob.getJobName(), 67 scheduleJob.getJobGroup() ).build(); 68 69 jobDetail.getJobDataMap().put( "scheduleJob", 70 scheduleJob ); 71 72 CronScheduleBuilder scheduleBuilder = CronScheduleBuilder 73 .cronSchedule( scheduleJob.getCronExpression() ); 74 75 trigger = TriggerBuilder.newTrigger().withIdentity( 76 scheduleJob.getJobName(), 77 scheduleJob.getJobGroup() ).withSchedule( 78 scheduleBuilder ).build(); 79 scheduler.scheduleJob( jobDetail, trigger ); 80 }else { 81 /* Trigger已存在,那么更新相应的定时设置 */ 82 CronScheduleBuilder scheduleBuilder = CronScheduleBuilder 83 .cronSchedule( scheduleJob.getCronExpression() ); 84 85 /* 按新的cronExpression表达式重新构建trigger */ 86 trigger = trigger.getTriggerBuilder().withIdentity( 87 triggerKey ).withSchedule( scheduleBuilder ) 88 .build(); 89 90 /* 按新的trigger重新设置job执行 */ 91 scheduler.rescheduleJob( triggerKey, trigger ); 92 } 93 } 94 catch ( SchedulerException e ) 95 { 96 log.error( "Task init failed.", e ); 97 } 98 } 99 } 100 } 101 102 103 /** 104 * 暂停一个job 105 * 106 * @param scheduleJob 107 * @throws SchedulerException 108 */ 109 public void pauseJob( ScheduleJob scheduleJob ) 110 { 111 JobKey jobKey = JobKey.jobKey( scheduleJob.getJobName(), scheduleJob.getJobGroup() ); 112 try 113 { 114 scheduler.pauseJob( jobKey ); 115 } 116 catch ( SchedulerException e ) 117 { 118 log.error( "Task pause failed.", e ); 119 } 120 } 121 122 123 /** 124 * 恢复一个job 125 * 126 * @param scheduleJob 127 * @throws SchedulerException 128 */ 129 public void resumeJob( ScheduleJob scheduleJob ) 130 { 131 JobKey jobKey = JobKey.jobKey( scheduleJob.getJobName(), scheduleJob.getJobGroup() ); 132 try 133 { 134 scheduler.resumeJob( jobKey ); 135 } 136 catch ( SchedulerException e ) 137 { 138 log.error( "Task resume failed.", e ); 139 } 140 } 141 142 143 /** 144 * 删除一个job 145 * 146 * @param scheduleJob 147 * @throws SchedulerException 148 */ 149 public void deleteJob( ScheduleJob scheduleJob ) 150 { 151 JobKey jobKey = JobKey.jobKey( scheduleJob.getJobName(), scheduleJob.getJobGroup() ); 152 try 153 { 154 scheduler.deleteJob( jobKey ); 155 } 156 catch ( SchedulerException e ) 157 { 158 log.error( "Task delete failed.", e ); 159 } 160 } 161 162 163 /** 164 * 立即执行job 165 * 166 * @param scheduleJob 167 * @throws SchedulerException 168 */ 169 public void runJobNow( ScheduleJob scheduleJob ) 170 { 171 JobKey jobKey = JobKey.jobKey( scheduleJob.getJobName(), scheduleJob.getJobGroup() ); 172 try 173 { 174 scheduler.triggerJob( jobKey ); 175 } 176 catch ( SchedulerException e ) 177 { 178 log.error( "Task run failed.", e ); 179 } 180 } 181 182 183 /** 184 * 更新job时间表达式 185 * 186 * @param scheduleJob 187 * @throws SchedulerException 188 */ 189 public void updateJobCron( ScheduleJob scheduleJob ) throws SchedulerException 190 { 191 TriggerKey triggerKey = TriggerKey.triggerKey( scheduleJob.getJobName(), 192 scheduleJob.getJobGroup() ); 193 /* 获取trigger,即在spring配置文件中定义的 bean id="schedulerFactoryBean" */ 194 CronTrigger trigger = (CronTrigger) scheduler.getTrigger( triggerKey ); 195 /* 表达式调度构建器 */ 196 CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule( scheduleJob 197 .getCronExpression() ); 198 /*按新的cronExpression表达式重新构建trigger */ 199 trigger = trigger.getTriggerBuilder().withIdentity( triggerKey ) 200 .withSchedule( scheduleBuilder ).build(); 201 /*按新的trigger重新设置job执行 */ 202 scheduler.rescheduleJob( triggerKey, trigger ); 203 } 204 205 206 /** 207 * 判断表达式是否可用 208 * @param cron 209 * @return 210 * @throws 211 */ 212 public boolean checkCron( String cron ) 213 { 214 try 215 { 216 CronScheduleBuilder.cronSchedule( cron ); 217 } 218 catch ( Exception e ) 219 { 220 return(false); 221 } 222 return(true); 223 } 224 }
五、编写业务层类QuartzJobService.java
1 package com.zealer.cps.task.service; 2 3 import java.util.HashMap; 4 import java.util.List; 5 import java.util.Map; 6 7 import javax.annotation.Resource; 8 9 import org.springframework.stereotype.Service; 10 import org.springframework.transaction.annotation.Propagation; 11 import org.springframework.transaction.annotation.Transactional; 12 13 import com.zealer.cps.base.dao.BaseDaoInterface; 14 import com.zealer.cps.base.model.vo.PaginationBean; 15 import com.zealer.cps.task.value.ScheduleJob; 16 import com.zealer.cps.task.value.ScheduleJobItem; 17 import com.zealer.cps.task.value.ScheduleJobReq; 18 19 @Service( "quartzJobService" ) 20 public class QuartzJobService 21 { 22 public static final String JOB_LIST = "quartzJob.jobsList"; 23 public static final String JOB_SELECT_BYID = "quartzJob.selectById"; 24 public static final String JOB_INSERT = "quartzJob.addJob"; 25 public static final String JOB_UPDATE = "quartzJob.updateJob"; 26 public static final String JOB_DELETE = "quartzJob.deleteJob"; 27 public static final String JOB_LIST_PAGE = "quartzJob.jobListPage"; 28 29 public static final String JOBITEM_LIST_PAGE = "jobItem.selectListPageByMap"; 30 public static final String JOBITEM_INSERT = "jobItem.insertJobItem"; 31 public static final String JOBITEM_SELETE_BYID = "jobItem.selectByPrimaryKey"; 32 33 @Resource( name = "mybatisBaseDao" ) 34 private BaseDaoInterface baseDao; 35 36 37 /** 38 * 获取所有的定时任务记录信息 39 * @return 40 */ 41 public List<ScheduleJob> getAllJobs() 42 { 43 return(this.baseDao.queryForList( JOB_LIST, null ) ); 44 } 45 46 47 /** 48 * 根据id获取任务记录 49 * @param id 50 * @return 51 */ 52 public ScheduleJob getScheduleJobById( int id ) 53 { 54 return(this.baseDao.query( JOB_SELECT_BYID, id ) ); 55 } 56 57 58 /** 59 * 插入一条定时任务记录 60 * @param job 61 */ 62 public void inserJob( ScheduleJob job ) 63 { 64 this.baseDao.insertData( JOB_INSERT, job ); 65 } 66 67 68 /** 69 * 更新一条定时任务记录 70 * @param job 71 */ 72 public void updateJob( ScheduleJob job ) 73 { 74 this.baseDao.updateData( JOB_UPDATE, job ); 75 } 76 77 78 /** 79 * 删除一条定时任务记录 80 * @param job 81 */ 82 public void deleteJob( int id ) 83 { 84 this.baseDao.deleteData( JOB_DELETE, id ); 85 } 86 87 88 /** 89 * 分页获取定时任务记录信息 90 * @return 91 */ 92 public PaginationBean<ScheduleJob> getJobsByPage( ScheduleJobReq jobReq ) 93 { 94 PaginationBean<ScheduleJob> pb = new PaginationBean<ScheduleJob>( jobReq.getCurrent(), 0, jobReq.getPageSize() ); 95 Map<String, Object> map = new HashMap<String, Object>(); 96 map.put( "page", pb ); 97 return(this.baseDao.queryForListPageByMap( JOB_LIST_PAGE, map ) ); 98 } 99 100 101 /** 102 * 分页获取定时任务执行记录信息 103 * @return 104 */ 105 public PaginationBean<ScheduleJobItem> getJobItemsByPage( Integer jobId, ScheduleJobReq jobReq ) 106 { 107 PaginationBean<ScheduleJobItem> pb = new PaginationBean<ScheduleJobItem>( jobReq.getCurrent(), 0, jobReq.getPageSize() ); 108 Map<String, Object> map = new HashMap<String, Object>(); 109 map.put( "jobId", jobId ); 110 map.put( "page", pb ); 111 return(this.baseDao.queryForListPageByMap( JOBITEM_LIST_PAGE, map ) ); 112 } 113 114 115 /** 116 * 插入一条定时任务执行记录信息 117 * @param jobItem 118 */ 119 @Transactional( propagation = Propagation.REQUIRED ) 120 public void inserJobItem( ScheduleJobItem jobItem ) 121 { 122 this.baseDao.insertData( JOBITEM_INSERT, jobItem ); 123 } 124 125 126 /** 127 * 根据ID获取一条定时任务执行记录信息 128 * @param id 129 * @return 130 */ 131 public ScheduleJobItem getScheduleJobItemById( int id ) 132 { 133 return(this.baseDao.query( JOBITEM_SELETE_BYID, id ) ); 134 } 135 }
六、编写sql映射xml文件QuartzJob.xml
1 <?xml version="1.0" encoding="utf-8"?> 2 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 3 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 4 <mapper namespace="quartzJob"> 5 <resultMap id="jobsResultMap" type="com.lutongnet.cps.task.value.ScheduleJob"> 6 <result column="job_id" property="jobId" /> 7 <result column="job_name" property="jobName" /> 8 <result column="job_group" property="jobGroup" /> 9 <result column="job_status" property="jobStatus" /> 10 <result column="cron_expression" property="cronExpression" /> 11 <result column="bean_class" property="beanClass" /> 12 <result column="execute_method" property="executeMethod" /> 13 <result column="create_time" property="createTime" /> 14 <result column="update_time" property="updateTime" /> 15 <result column="job_desc" property="jobDesc" /> 16 </resultMap> 17 <insert id="addJob" parameterType="com.lutongnet.cps.task.value.ScheduleJob">insert into task_detail (job_name, job_group, job_status, cron_expression, bean_class, execute_method, create_time, update_time, job_desc) values (#{jobName},#{jobGroup},#{jobStatus},#{cronExpression},#{beanClass},#{executeMethod},#{createTime},#{updateTime},#{jobDesc})</insert> 18 <delete id="deleteJob" parameterType="com.lutongnet.cps.task.value.ScheduleJob">delete from task_detail where job_id = #{jobId}</delete> 19 <update id="updateJob" parameterType="com.lutongnet.cps.task.value.ScheduleJob">update task_detail 20 <set> 21 <if test="jobName != null">job_name = #{jobName},</if> 22 <if test="jobGroup != null">job_group = #{jobGroup},</if> 23 <if test="jobStatus != null">job_status = #{jobStatus},</if> 24 <if test="cronExpression != null">cron_expression = #{cronExpression},</if> 25 <if test="beanClass != null">bean_class = #{beanClass},</if> 26 <if test="executeMethod != null">execute_method = #{executeMethod},</if> 27 <if test="updateTime != null">update_time = #{updateTime},</if> 28 <if test="jobDesc != null">job_desc = #{jobDesc},</if> 29 </set>where job_id = #{jobId}</update> 30 <select id="jobListPage" resultMap="jobsResultMap" parameterType="java.util.Map">select job_name, job_group, job_status, cron_expression, bean_class, execute_method, create_time, update_time, job_desc,job_id from task_detail where 1=1 31 <if test="createTime != null">and create_time = #{createTime}</if> 32 <if test="updateTime == null">and update_time = #{updateTime}</if> 33 <if test="beanClass != null">and bean_class = #{beanClass}</if> 34 <if test="executeMethod == null">and execute_method = #{executeMethod}</if> 35 <if test="jobStatus != null">and business_code = #{propertyGroups}</if> 36 <if test="jobName == null">and create_time = #{createTime}</if></select> 37 <select id="jobsList" resultMap="jobsResultMap" parameterType="java.util.Map">select job_name, job_group, job_status, cron_expression, bean_class, execute_method, create_time, update_time, job_desc,job_id from task_detail</select> 38 </mapper>
七、修改和列表页面
updateJob.jsp
1 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> 2 <%@ include file="../common/common_tags.jsp" %> 3 <!DOCTYPE html> 4 <html lang="en"> 5 <head> 6 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 7 <title>修改定时任务</title> 8 </head> 9 <body> 10 <div id="accordion" class="accordion"> 11 <div class="accordion-group"> 12 <div class="accordion-heading"> 13 <div class="title">系统管理 >任务管理>修改任务</div> 14 </div> 15 <div id="addAccordion" class="accordion-body in"> 16 <div class="accordion-inner" style="border: 0px solid red;"> 17 <form:form action="${path}/taskController/updateJob.do" method="post" modelAttribute="job" cssClass="form-horizontal"> 18 <form:hidden path="jobId"/> 19 <form:hidden path="createTime"/> 20 <div class="control-group"> 21 <label class="control-label" for="jobName"><span class="help-inline input_msg_style">*</span>任务名称</label> 22 <div class="controls"> 23 <form:input path="jobName"/> 24 <span style="color:red" class="help-inline"></span> 25 </div> 26 </div> 27 28 <div class="control-group"> 29 <label class="control-label" for="jobGroup"><span class="help-inline input_msg_style">*</span>任务分组</label> 30 <div class="controls"> 31 <form:input path="jobGroup"/> 32 <span style="color:red" class="help-inline"></span> 33 </div> 34 </div> 35 <div class="control-group"> 36 <label class="control-label"><span class="help-inline input_msg_style">*</span>任务表达式</label> 37 <div class="controls"> 38 <form:input path="cronExpression"/> 39 <span style="color:red" class="help-inline"></span> 40 </div> 41 </div> 42 <div class="control-group"> 43 <label class="control-label"><span class="help-inline input_msg_style">*</span>任务执行类</label> 44 <div class="controls"> 45 <form:input path="beanClass"/> 46 <span style="color:red" class="help-inline"></span> 47 </div> 48 </div> 49 <div class="control-group"> 50 <label class="control-label"><span class="help-inline input_msg_style">*</span>执行方法</label> 51 <div class="controls"> 52 <form:input path="executeMethod"/> 53 <span style="color:red" class="help-inline"></span> 54 </div> 55 </div> 56 <div class="control-group"> 57 <label class="control-label" for="jobDesc">任务描述</label> 58 <div class="controls"> 59 <form:textarea path="jobDesc" rows="3" cols="20"/> 60 <span style="color:red" class="help-inline"></span> 61 </div> 62 </div> 63 <div class="form-actions"> 64 <button class="lt_sys_commit" type="submit" 65 onmouseover="this.className='lt_sys_commit2'" onmouseout="this.className='lt_sys_commit'"> </button> 66 <button id="btn_back" class="lt_sys_back" type="button" 67 onmouseover="this.className='lt_sys_back2'" onmouseout="this.className='lt_sys_back'"> </button> 68 </div> 69 </form:form> 70 </div> 71 </div> 72 </div> 73 </div> 74 <script type="text/javascript" src="<w:path/>resources/js/pc.js"></script> 75 <script type="text/javascript"> 76 $('#job').validate({ 77 rules:{ 78 jobName:{ 79 required:true, 80 maxlength:50 81 }, 82 jobGroup:{ 83 required:true, 84 maxlength:50 85 }, 86 cronExpression: { 87 required:true, 88 maxlength:200 89 }, 90 beanClass: { 91 required:true, 92 maxlength:300 93 }, 94 executeMethod: { 95 required:true, 96 maxlength:100 97 }, 98 remark:{ 99 maxlength:400, 100 } 101 }, 102 messages:{ 103 jobName:{ 104 required:"请输入任务名称", 105 maxlength:"最长为50个字符", 106 }, 107 jobGroup:{ 108 required:"请输入任务名称", 109 maxlength:"最长为50个字符", 110 }, 111 cronExpression:{ 112 required:"请输入执行表达式", 113 maxlength:'最长为200个字符', 114 }, 115 beanClass:{ 116 required:"请输入任务执行类路径", 117 maxlength:'最长为300个字符', 118 }, 119 executeMethod:{ 120 required:"请输入执行任务的方法", 121 maxlength:'最长为100个字符', 122 }, 123 remark:{ 124 maxlength:"长度不能超过400个字符", 125 } 126 }, 127 onfocusout: function(element) { 128 $(element).valid(); 129 }, 130 submitHandler: function(form){ 131 var exp = $("#cronExpression").val(); 132 $.post('${path}/taskController/checkExp.do',{'expression':exp},function(data) 133 { 134 if(data.code==0){ 135 form.submit(); 136 }else{ 137 showSimpleMessage("输入的表达式不正确,请重新输入!"); 138 $("#cronExpression").focus(); 139 } 140 }); 141 142 }, 143 errorElement: 'span', 144 errorPlacement: function(error, element) { 145 error.appendTo(element.next()); 146 } 147 }); 148 149 $('#btn_back').click(function(){ 150 window.location.href = '${path}/taskController/list.do'; 151 }) 152 </script> 153 </body> 154 </html>
taskList.jsp
1 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> 2 <%@ include file="../common/common_tags.jsp" %> 3 <!DOCTYPE html> 4 <html lang="en"> 5 <head> 6 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 7 <title>任务管理>任务列表</title> 8 9 </head> 10 <body> 11 <div id="accordion" class="accordion"> 12 <div class="accordion-group"> 13 <div class="accordion-heading"> 14 <div class="title">任务管理>任务列表</div> 15 </div> 16 <div id="addAccordion" class="accordion-body in"> 17 <div class="accordion-inner"> 18 <div style="border: 0px solid red; height: 33px;"> 19 <form:form action="${path}/taskController/list.do" method="post" modelAttribute="job" cssClass="form-inline"></form:form> 20 <lt:img menuName="任务列表" moduleName="运营管理"></lt:img> 21 </div> 22 <table class="table table-hover table-condensed"> 23 <thead> 24 <tr> 25 <th width="4%"><input id="checkAll" name="checkAll" type="checkbox" style="margin-top: 0px;">全选</th> 26 <th>任务名称</th> 27 <th>任务分组</th> 28 <th>任务描述</th> 29 <th>创建时间</th> 30 <th>更新时间</th> 31 <th>任务表达式</th> 32 <th>执行类</th> 33 <th>执行方法</th> 34 <th>操作</th> 35 </tr> 36 </thead> 37 <tbody> 38 <c:forEach items="${pb.dataList}" var="job" varStatus="status"> 39 <tr> 40 <td><input name="checkItem" type="checkbox" value="${job.jobId}" style="margin-top: 0px;"></td> 41 <td>${job.jobName}</td> 42 <td>${job.jobGroup}</td> 43 <td>${job.jobDesc}</td> 44 <td>${job.createTime}</td> 45 <td>${job.updateTime}</td> 46 <td>${job.cronExpression}</td> 47 <td>${job.beanClass}</td> 48 <td>${job.executeMethod}</td> 49 <td> 50 <img src="${path}/resources/img/zengjian.png"> 51 <a href="${path}/taskController/itemJob.do?jobId=${job.jobId}" >详细</a> 52 <lt:img menuName="任务列表" moduleName="运营管理" privilegeName="执行定时任务" clickName="立即执行" 53 clickMethod="executeJob('${job.jobName}','${job.jobGroup}','${job.jobId}');"></lt:img> 54 </td> 55 </tr> 56 </c:forEach> 57 <tr> 58 <td colspan="10" form-id="job" class="paginationPanel"><ltPage:page pageBean="${pb}" /></td> 59 </tr> 60 </tbody> 61 </table> 62 </div> 63 </div> 64 </div> 65 </div> 66 <script type="text/javascript"> 67 68 function executeJob(name,group,id){ 69 $.ajax({ 70 type: "POST", 71 url: "${path}/taskController/executeJob.do", 72 data: "jobName="+name+"&jobGroup="+group+"&jobId"+id, 73 success:function(data){ 74 showSimpleMessage("定时任务已执行,执行结果请查看详情!"); 75 } 76 }); 77 } 78 79 </script> 80 </body> 81 </html>
到这里,我们的spring3 整合quartz 2的定时任务功能终于是告一段落了,对常用的一些功能进行了实现,相信可以满足一般项目的需求了。