博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring 3整合Quartz 2实现手动设置定时任务:新增,修改,删除,暂停和恢复
阅读量:6691 次
发布时间:2019-06-25

本文共 22053 字,大约阅读时间需要 73 分钟。

 ---每一个你不满意的当下,都有一个你不曾努力的过去---

摘要:在项目的管理功能中,对定时任务的管理有时会很常见。但一般定时任务配置都在xml中完成,包括cronExpression表达式,十分的方便。但是如果我的任务信息是保存在数据库的,想要动态的初始化,还有就是任务较多的时候不是得有一大堆的xml配置?或者说我要修改一下trigger的表达式,使原来5秒运行一次的任务变成10秒运行一次,或者说我要控制定时任务的 “ 暂停 ” 呢?暂停之后又要在某个时间点 “ 重启 ” 该定时任务呢?或者说直接 “ 删除 ” 该定时任务呢?要 改变某定时任务的触发时间呢?这时问题就来了,试过在配置文件中不传入cronExpression等参数,但是启动时就报错了,难道我每次都修改xml文件然后重启应用吗,这显然不合适的。

最理想的是在与spring整合的同时又能实现动态任务的添加、删除及修改配置,而且不需要重启应用。

 首先我们来回顾一下spring中使用quartz的配置代码:

execute
0/5 * * * * ?

 

所有的配置都在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

package com.zealer.cps.task.value;/** * 定时任务封装类 * @author   xiaohe */public class ScheduleJob{    /** 任务id */    private int jobId;        /** 任务名称 */    private String jobName;        /** 任务分组 */    private String jobGroup;        /** 任务状态 0禁用 1启用 2删除*/    private String jobStatus;        /** 任务运行时间表达式 */    private String cronExpression;        /** 任务执行类 */    private String beanClass;        /** 任务执行方法 */    private String executeMethod;        /** 任务创建时间 */    private String createTime;        /** 任务更新时间 */    private String updateTime;        /** 任务描述 */    private String jobDesc;       //set与get方法这里省略,大家可以自己生成    ......  }

 

二、spring配置文件spring.xml

然后在web.xml加入

contextConfigLocation
classpath:spring.xml

三、编写任务控制器TaskController.java

package com.zealer.cps.task.controller;import java.text.SimpleDateFormat;import java.util.Date;import java.util.HashMap;import java.util.Map;import javax.annotation.Resource;import javax.servlet.http.HttpServletRequest;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.http.HttpStatus;import org.springframework.http.ResponseEntity;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.ModelAttribute;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.ResponseBody;import org.springframework.web.servlet.mvc.support.RedirectAttributes;import com.zealer.cps.base.annotation.Log;import com.zealer.cps.base.constant.AppConstant;import com.zealer.cps.base.controller.BaseController;import com.zealer.cps.base.message.SuccessActionResult;import com.zealer.cps.base.model.vo.PaginationBean;import com.zealer.cps.base.util.HttpUtils;import com.zealer.cps.task.manage.JobMethod;import com.zealer.cps.task.service.QuartzJobService;import com.zealer.cps.task.value.ScheduleJob;import com.zealer.cps.task.value.ScheduleJobItem;import com.zealer.cps.task.value.ScheduleJobReq;@Controller@RequestMapping( "/taskController" )public class TaskController extends BaseController{    private static Logger log = LoggerFactory.getLogger( TaskController.class );    @Resource( name = "quartzJobService" )    private QuartzJobService quartzJobService;    @Resource( name = "JobMethod" )    private JobMethod jobMethod;    @RequestMapping( "/list" )    @Log( "任务列表" )    public String listJob( @ModelAttribute("job") ScheduleJobReq jobReq, Model model, HttpServletRequest request )    {        PaginationBean
pb = quartzJobService.getJobsByPage( jobReq ); try { pb.setUrl( HttpUtils.getRequestInfo( request, true ) ); } catch ( Exception e ) { log.error( "get request url error", e ); } model.addAttribute( "pb", pb ); return("task/taskList"); } /** * 立即执行定时任务 * @param job 任务实体 * @param model * @return */ @ResponseBody @RequestMapping( value = "/executeJob", produces = "application/json;charset=utf-8" ) @Log( "立即执行任务" ) public ResponseEntity
> executeJob( ScheduleJob job, Model model ) { jobMethod.runJobNow( job ); return(new ResponseEntity
> ( new HashMap
(), HttpStatus.OK ) ); } /** * 跳转到添加定时任务的页面 * @param model * 储存结果的实体 */ @RequestMapping( value = "/addJob", method = RequestMethod.GET ) @Log( "初始化添加表单" ) public String addForm( Model model ) { model.addAttribute( "job", new ScheduleJob() ); return("task/addJob"); } /** * 添加定时任务记录 * @param job 任务实体 */ @RequestMapping( value = "/addJob", method = RequestMethod.POST ) @Log( "新增操作员" ) public String addUser( @ModelAttribute("job") ScheduleJob job, RedirectAttributes ra, Model model, HttpServletRequest request ) { SimpleDateFormat format = new SimpleDateFormat( AppConstant.DATE_FORMAT_YYYYMMDDHHMMSS ); job.setCreateTime( format.format( new Date() ) ); quartzJobService.inserJob( job ); ra.addFlashAttribute( "actionResult", new SuccessActionResult() ); return("redirect:/taskController/list.do"); } /** * 初始化修改表单 * @param jobId * @return 跳转地址 */ @RequestMapping( value = "/updateJob", method = RequestMethod.GET ) @Log( "初始化修改表单" ) public String updateForm( @RequestParam("id") Integer jobId, Model model, HttpServletRequest request ) { ScheduleJob job = quartzJobService.getScheduleJobById( jobId ); model.addAttribute( "job", job ); return("task/updateJob"); } /** * 修改定时任务记录信息 * @param job 待修改的操作员实体 * @param model 封装处理结果的实体 * @param request 请求对象 * @return 跳转地址 */ @RequestMapping( value = "/updateJob", method = RequestMethod.POST ) @Log( "修改定时任务" ) public String updateJob( @ModelAttribute ScheduleJob job, RedirectAttributes ra, Model model, HttpServletRequest request ) { SimpleDateFormat format = new SimpleDateFormat( AppConstant.DATE_FORMAT_YYYYMMDDHHMMSS ); job.setUpdateTime( format.format( new Date() ) ); quartzJobService.updateJob( job ); ra.addFlashAttribute( "actionResult", new SuccessActionResult() ); return("redirect:/taskController/list.do"); } /** * 删除一条定时任务记录信息 * @return */ @RequestMapping( value = "/deleteJob" ) @Log( "删除任务" ) public String deleteJob( @RequestParam("id") int jobId, RedirectAttributes ra ) { quartzJobService.deleteJob( jobId ); ra.addFlashAttribute( "actionResult", new SuccessActionResult() ); return("redirect:/taskController/list.do"); } /** * 校验执行任务的表达式是否正确 * @param expression * @return */ @ResponseBody @RequestMapping( value = "/checkExp", produces = "application/json;charset=utf-8" ) @Log( "校验任务表达式" ) public ResponseEntity
> checkExpression( String expression ) { Map
map = new HashMap
(); map.put( AppConstant.SYSTEM_JSON_CODE, AppConstant.SYSTEM_JSON_ERROR ); if ( jobMethod.checkCron( expression ) ) { map.put( AppConstant.SYSTEM_JSON_CODE, AppConstant.SYSTEM_JSON_SUCCESS ); } return(new ResponseEntity
> ( map, HttpStatus.OK ) ); } /** * 某个定时任务下的所有执行记录信息列表 * @param jobReq * @return */ @RequestMapping( "/itemJob" ) @Log( "任务执行信息列表" ) public String executeJobList( @ModelAttribute("job") ScheduleJobReq jobReq, int jobId, Model model, HttpServletRequest request ) { PaginationBean
pb = quartzJobService.getJobItemsByPage( jobId, jobReq ); try { pb.setUrl( HttpUtils.getRequestInfo( request, true ) ); } catch ( Exception e ) { log.error( "get request url error", e ); } model.addAttribute( "pb", pb ); model.addAttribute( "jobId", jobId ); return("task/taskItemList"); }}

 

四、编写任务运行入口,即JobMethod.java

package com.zealer.cps.task.manage;import java.util.List;import javax.annotation.Resource;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.quartz.CronScheduleBuilder;import org.quartz.CronTrigger;import org.quartz.JobBuilder;import org.quartz.JobDetail;import org.quartz.JobKey;import org.quartz.Scheduler;import org.quartz.SchedulerException;import org.quartz.TriggerBuilder;import org.quartz.TriggerKey;import org.springframework.stereotype.Component;import com.zealer.cps.task.QuartzJobFactory;import com.zealer.cps.task.service.QuartzJobService;import com.zealer.cps.task.value.ScheduleJob;/** * 提供Job任务相关的方法 * @author xiaohe */@Component( "JobMethod" )public class JobMethod{    @Resource( name = "schedulerFactoryBean" )    private Scheduler scheduler;    @Resource( name = "quartzJobService" )    private QuartzJobService quartzJobService;    private static Log log = LogFactory.getLog( JobMethod.class );    /**     * 任务框架初始化方法     * @throws     */    public void init()    {        /* 从数据库获得所有的任务信息记录 */        List
jobList = quartzJobService.getAllJobs(); if ( jobList != null && !jobList.isEmpty() ) { for ( ScheduleJob scheduleJob : jobList ) { /* 判断任务状态,是否为执行状态 */ TriggerKey triggerKey = TriggerKey.triggerKey( scheduleJob .getJobName(), scheduleJob.getJobGroup() ); CronTrigger trigger; try { trigger = (CronTrigger) scheduler.getTrigger( triggerKey ); if ( null == trigger ) { JobDetail jobDetail = JobBuilder.newJob( QuartzJobFactory.class ).withIdentity( scheduleJob.getJobName(), scheduleJob.getJobGroup() ).build(); jobDetail.getJobDataMap().put( "scheduleJob", scheduleJob ); CronScheduleBuilder scheduleBuilder = CronScheduleBuilder .cronSchedule( scheduleJob.getCronExpression() ); trigger = TriggerBuilder.newTrigger().withIdentity( scheduleJob.getJobName(), scheduleJob.getJobGroup() ).withSchedule( scheduleBuilder ).build(); scheduler.scheduleJob( jobDetail, trigger ); }else { /* Trigger已存在,那么更新相应的定时设置 */ CronScheduleBuilder scheduleBuilder = CronScheduleBuilder .cronSchedule( scheduleJob.getCronExpression() ); /* 按新的cronExpression表达式重新构建trigger */ trigger = trigger.getTriggerBuilder().withIdentity( triggerKey ).withSchedule( scheduleBuilder ) .build(); /* 按新的trigger重新设置job执行 */ scheduler.rescheduleJob( triggerKey, trigger ); } } catch ( SchedulerException e ) { log.error( "Task init failed.", e ); } } } } /** * 暂停一个job * * @param scheduleJob * @throws SchedulerException */ public void pauseJob( ScheduleJob scheduleJob ) { JobKey jobKey = JobKey.jobKey( scheduleJob.getJobName(), scheduleJob.getJobGroup() ); try { scheduler.pauseJob( jobKey ); } catch ( SchedulerException e ) { log.error( "Task pause failed.", e ); } } /** * 恢复一个job * * @param scheduleJob * @throws SchedulerException */ public void resumeJob( ScheduleJob scheduleJob ) { JobKey jobKey = JobKey.jobKey( scheduleJob.getJobName(), scheduleJob.getJobGroup() ); try { scheduler.resumeJob( jobKey ); } catch ( SchedulerException e ) { log.error( "Task resume failed.", e ); } } /** * 删除一个job * * @param scheduleJob * @throws SchedulerException */ public void deleteJob( ScheduleJob scheduleJob ) { JobKey jobKey = JobKey.jobKey( scheduleJob.getJobName(), scheduleJob.getJobGroup() ); try { scheduler.deleteJob( jobKey ); } catch ( SchedulerException e ) { log.error( "Task delete failed.", e ); } } /** * 立即执行job * * @param scheduleJob * @throws SchedulerException */ public void runJobNow( ScheduleJob scheduleJob ) { JobKey jobKey = JobKey.jobKey( scheduleJob.getJobName(), scheduleJob.getJobGroup() ); try { scheduler.triggerJob( jobKey ); } catch ( SchedulerException e ) { log.error( "Task run failed.", e ); } } /** * 更新job时间表达式 * * @param scheduleJob * @throws SchedulerException */ public void updateJobCron( ScheduleJob scheduleJob ) throws SchedulerException { TriggerKey triggerKey = TriggerKey.triggerKey( scheduleJob.getJobName(), scheduleJob.getJobGroup() ); /* 获取trigger,即在spring配置文件中定义的 bean id="schedulerFactoryBean" */ CronTrigger trigger = (CronTrigger) scheduler.getTrigger( triggerKey ); /* 表达式调度构建器 */ CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule( scheduleJob .getCronExpression() ); /*按新的cronExpression表达式重新构建trigger */ trigger = trigger.getTriggerBuilder().withIdentity( triggerKey ) .withSchedule( scheduleBuilder ).build(); /*按新的trigger重新设置job执行 */ scheduler.rescheduleJob( triggerKey, trigger ); }/** * 判断表达式是否可用 * @param cron * @return * @throws */ public boolean checkCron( String cron ) { try { CronScheduleBuilder.cronSchedule( cron ); } catch ( Exception e ) { return(false); } return(true); }}

 

 

五、编写业务层类QuartzJobService.java

package com.zealer.cps.task.service;import java.util.HashMap;import java.util.List;import java.util.Map;import javax.annotation.Resource;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Propagation;import org.springframework.transaction.annotation.Transactional;import com.zealer.cps.base.dao.BaseDaoInterface;import com.zealer.cps.base.model.vo.PaginationBean;import com.zealer.cps.task.value.ScheduleJob;import com.zealer.cps.task.value.ScheduleJobItem;import com.zealer.cps.task.value.ScheduleJobReq;@Service( "quartzJobService" )public class QuartzJobService{    public static final String    JOB_LIST    = "quartzJob.jobsList";    public static final String    JOB_SELECT_BYID = "quartzJob.selectById";    public static final String    JOB_INSERT    = "quartzJob.addJob";    public static final String    JOB_UPDATE    = "quartzJob.updateJob";    public static final String    JOB_DELETE    = "quartzJob.deleteJob";    public static final String    JOB_LIST_PAGE    = "quartzJob.jobListPage";    public static final String    JOBITEM_LIST_PAGE    = "jobItem.selectListPageByMap";    public static final String    JOBITEM_INSERT        = "jobItem.insertJobItem";    public static final String    JOBITEM_SELETE_BYID    = "jobItem.selectByPrimaryKey";    @Resource( name = "mybatisBaseDao" )    private BaseDaoInterface baseDao;    /**     * 获取所有的定时任务记录信息     * @return     */    public List
getAllJobs() { return(this.baseDao.queryForList( JOB_LIST, null ) ); } /** * 根据id获取任务记录 * @param id * @return */ public ScheduleJob getScheduleJobById( int id ) { return(this.baseDao.query( JOB_SELECT_BYID, id ) ); } /** * 插入一条定时任务记录 * @param job */ public void inserJob( ScheduleJob job ) { this.baseDao.insertData( JOB_INSERT, job ); } /** * 更新一条定时任务记录 * @param job */ public void updateJob( ScheduleJob job ) { this.baseDao.updateData( JOB_UPDATE, job ); } /** * 删除一条定时任务记录 * @param job */ public void deleteJob( int id ) { this.baseDao.deleteData( JOB_DELETE, id ); } /** * 分页获取定时任务记录信息 * @return */ public PaginationBean
getJobsByPage( ScheduleJobReq jobReq ) { PaginationBean
pb = new PaginationBean
( jobReq.getCurrent(), 0, jobReq.getPageSize() ); Map
map = new HashMap
(); map.put( "page", pb ); return(this.baseDao.queryForListPageByMap( JOB_LIST_PAGE, map ) ); }/** * 分页获取定时任务执行记录信息 * @return */ public PaginationBean
getJobItemsByPage( Integer jobId, ScheduleJobReq jobReq ) { PaginationBean
pb = new PaginationBean
( jobReq.getCurrent(), 0, jobReq.getPageSize() ); Map
map = new HashMap
(); map.put( "jobId", jobId ); map.put( "page", pb ); return(this.baseDao.queryForListPageByMap( JOBITEM_LIST_PAGE, map ) ); } /** * 插入一条定时任务执行记录信息 * @param jobItem */ @Transactional( propagation = Propagation.REQUIRED ) public void inserJobItem( ScheduleJobItem jobItem ) { this.baseDao.insertData( JOBITEM_INSERT, jobItem ); } /** * 根据ID获取一条定时任务执行记录信息 * @param id * @return */ public ScheduleJobItem getScheduleJobItemById( int id ) { return(this.baseDao.query( JOBITEM_SELETE_BYID, id ) ); }}

六、编写sql映射xml文件QuartzJob.xml

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})
delete from task_detail where job_id = #{jobId}
update task_detail
job_name = #{jobName},
job_group = #{jobGroup},
job_status = #{jobStatus},
cron_expression = #{cronExpression},
bean_class = #{beanClass},
execute_method = #{executeMethod},
update_time = #{updateTime},
job_desc = #{jobDesc},
where job_id = #{jobId}

 

 

七、修改和列表页面

updateJob.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><%@ include file="../common/common_tags.jsp" %>
修改定时任务
系统管理 >任务管理>修改任务

 

taskList.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><%@ include file="../common/common_tags.jsp" %>
任务管理>任务列表
任务管理>任务列表
全选 任务名称 任务分组 任务描述 创建时间 更新时间 任务表达式 执行类 执行方法 操作
${job.jobName} ${job.jobGroup} ${job.jobDesc} ${job.createTime} ${job.updateTime} ${job.cronExpression} ${job.beanClass} ${job.executeMethod} 详细 

 

到这里,我们的spring3 整合quartz 2的定时任务功能终于是告一段落了,对常用的一些功能进行了实现,相信可以满足一般项目的需求了。

每一个你不满意的当下,都有一个你不曾努力的过去

 

http://www.cnblogs.com/zishengY/p/7065665.html

 

你可能感兴趣的文章
Java开发GUI之选择列表
查看>>
一、分布式商城架构逻辑图
查看>>
find命令详解
查看>>
2018年的“核心期刊陷阱”已开启,你知道吗?2018年的“核心期刊陷阱”已开启,你知道吗?...
查看>>
rsync+shell脚本完成自动化备份
查看>>
如何衡量机器人用激光雷达的实用性和可靠性
查看>>
机器人是如何完成避障的?机器人避障解决方案解读
查看>>
利用思维导图软件绘制鱼骨图怎样做
查看>>
mac os 安装maven
查看>>
结构体数组存放学生信息并排序输出
查看>>
UI设计师有什么实用价值?
查看>>
默认路由与静态的配置
查看>>
通过错误堆栈信息和源码分析错误来源
查看>>
C和C++ 读写文件速度问题
查看>>
layer.mobile 弹出框插件(2.0版)
查看>>
IDC服务品质协议范本留存
查看>>
在 overlay 中运行容器 - 每天5分钟玩转 Docker 容器技术(51)
查看>>
ks.cfg 文件,参数讲解
查看>>
前端MVC框架 EmberJS总结
查看>>
LVS
查看>>