摘要:在项目的管理功能中,对定时任务的管理有时会很常见。但一般定时任务配置都在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 ('', '测试手动设置任务', '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
<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
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<ScheduleJob> 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<Map<String, Object> > executeJob( ScheduleJob job, Model model )
{
jobMethod.runJobNow( job );
return(new ResponseEntity<Map<String, Object> > ( new HashMap<String, Object>(), 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<Map<String, Object> > checkExpression( String expression )
{
Map<String, Object> map = new HashMap<String, Object>();
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<String, Object> > ( map, HttpStatus.OK ) );
} /**
* 某个定时任务下的所有执行记录信息列表
* @param jobReq
* @return
*/
@RequestMapping( "/itemJob" )
@Log( "任务执行信息列表" )
public String executeJobList( @ModelAttribute("job") ScheduleJobReq jobReq, int jobId,
Model model, HttpServletRequest request )
{
PaginationBean<ScheduleJobItem> 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<ScheduleJob> 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<ScheduleJob> 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<ScheduleJob> getJobsByPage( ScheduleJobReq jobReq )
{
PaginationBean<ScheduleJob> pb = new PaginationBean<ScheduleJob>( jobReq.getCurrent(), 0, jobReq.getPageSize() );
Map<String, Object> map = new HashMap<String, Object>();
map.put( "page", pb );
return(this.baseDao.queryForListPageByMap( JOB_LIST_PAGE, map ) );
} /**
* 分页获取定时任务执行记录信息
* @return
*/
public PaginationBean<ScheduleJobItem> getJobItemsByPage( Integer jobId, ScheduleJobReq jobReq )
{
PaginationBean<ScheduleJobItem> pb = new PaginationBean<ScheduleJobItem>( jobReq.getCurrent(), 0, jobReq.getPageSize() );
Map<String, Object> map = new HashMap<String, Object>();
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
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="quartzJob">
<resultMap id="jobsResultMap" type="com.lutongnet.cps.task.value.ScheduleJob">
<result column="job_id" property="jobId" />
<result column="job_name" property="jobName" />
<result column="job_group" property="jobGroup" />
<result column="job_status" property="jobStatus" />
<result column="cron_expression" property="cronExpression" />
<result column="bean_class" property="beanClass" />
<result column="execute_method" property="executeMethod" />
<result column="create_time" property="createTime" />
<result column="update_time" property="updateTime" />
<result column="job_desc" property="jobDesc" />
</resultMap>
<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>
<delete id="deleteJob" parameterType="com.lutongnet.cps.task.value.ScheduleJob">delete from task_detail where job_id = #{jobId}</delete>
<update id="updateJob" parameterType="com.lutongnet.cps.task.value.ScheduleJob">update task_detail
<set>
<if test="jobName != null">job_name = #{jobName},</if>
<if test="jobGroup != null">job_group = #{jobGroup},</if>
<if test="jobStatus != null">job_status = #{jobStatus},</if>
<if test="cronExpression != null">cron_expression = #{cronExpression},</if>
<if test="beanClass != null">bean_class = #{beanClass},</if>
<if test="executeMethod != null">execute_method = #{executeMethod},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="jobDesc != null">job_desc = #{jobDesc},</if>
</set>where job_id = #{jobId}</update>
<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
<if test="createTime != null">and create_time = #{createTime}</if>
<if test="updateTime == null">and update_time = #{updateTime}</if>
<if test="beanClass != null">and bean_class = #{beanClass}</if>
<if test="executeMethod == null">and execute_method = #{executeMethod}</if>
<if test="jobStatus != null">and business_code = #{propertyGroups}</if>
<if test="jobName == null">and create_time = #{createTime}</if></select>
<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>
</mapper>
七、修改和列表页面
updateJob.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ include file="../common/common_tags.jsp" %>
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>修改定时任务</title>
</head>
<body>
<div id="accordion" class="accordion">
<div class="accordion-group">
<div class="accordion-heading">
<div class="title">系统管理 >任务管理>修改任务</div>
</div>
<div id="addAccordion" class="accordion-body in">
<div class="accordion-inner" style="border: 0px solid red;">
<form:form action="${path}/taskController/updateJob.do" method="post" modelAttribute="job" cssClass="form-horizontal">
<form:hidden path="jobId"/>
<form:hidden path="createTime"/>
<div class="control-group">
<label class="control-label" for="jobName"><span class="help-inline input_msg_style">*</span>任务名称</label>
<div class="controls">
<form:input path="jobName"/>
<span style="color:red" class="help-inline"></span>
</div>
</div> <div class="control-group">
<label class="control-label" for="jobGroup"><span class="help-inline input_msg_style">*</span>任务分组</label>
<div class="controls">
<form:input path="jobGroup"/>
<span style="color:red" class="help-inline"></span>
</div>
</div>
<div class="control-group">
<label class="control-label"><span class="help-inline input_msg_style">*</span>任务表达式</label>
<div class="controls">
<form:input path="cronExpression"/>
<span style="color:red" class="help-inline"></span>
</div>
</div>
<div class="control-group">
<label class="control-label"><span class="help-inline input_msg_style">*</span>任务执行类</label>
<div class="controls">
<form:input path="beanClass"/>
<span style="color:red" class="help-inline"></span>
</div>
</div>
<div class="control-group">
<label class="control-label"><span class="help-inline input_msg_style">*</span>执行方法</label>
<div class="controls">
<form:input path="executeMethod"/>
<span style="color:red" class="help-inline"></span>
</div>
</div>
<div class="control-group">
<label class="control-label" for="jobDesc">任务描述</label>
<div class="controls">
<form:textarea path="jobDesc" rows="3" cols="20"/>
<span style="color:red" class="help-inline"></span>
</div>
</div>
<div class="form-actions">
<button class="lt_sys_commit" type="submit"
onmouseover="this.className='lt_sys_commit2'" onmouseout="this.className='lt_sys_commit'"> </button>
<button id="btn_back" class="lt_sys_back" type="button"
onmouseover="this.className='lt_sys_back2'" onmouseout="this.className='lt_sys_back'"> </button>
</div>
</form:form>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="<w:path/>resources/js/pc.js"></script>
<script type="text/javascript">
$('#job').validate({
rules:{
jobName:{
required:true,
maxlength:50
},
jobGroup:{
required:true,
maxlength:50
},
cronExpression: {
required:true,
maxlength:200
},
beanClass: {
required:true,
maxlength:300
},
executeMethod: {
required:true,
maxlength:100
},
remark:{
maxlength:400,
}
},
messages:{
jobName:{
required:"请输入任务名称",
maxlength:"最长为50个字符",
},
jobGroup:{
required:"请输入任务名称",
maxlength:"最长为50个字符",
},
cronExpression:{
required:"请输入执行表达式",
maxlength:'最长为200个字符',
},
beanClass:{
required:"请输入任务执行类路径",
maxlength:'最长为300个字符',
},
executeMethod:{
required:"请输入执行任务的方法",
maxlength:'最长为100个字符',
},
remark:{
maxlength:"长度不能超过400个字符",
}
},
onfocusout: function(element) {
$(element).valid();
},
submitHandler: function(form){
var exp = $("#cronExpression").val();
$.post('${path}/taskController/checkExp.do',{'expression':exp},function(data)
{
if(data.code==0){
form.submit();
}else{
showSimpleMessage("输入的表达式不正确,请重新输入!");
$("#cronExpression").focus();
}
}); },
errorElement: 'span',
errorPlacement: function(error, element) {
error.appendTo(element.next());
}
}); $('#btn_back').click(function(){
window.location.href = '${path}/taskController/list.do';
})
</script>
</body>
</html>
taskList.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ include file="../common/common_tags.jsp" %>
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>任务管理>任务列表</title> </head>
<body>
<div id="accordion" class="accordion">
<div class="accordion-group">
<div class="accordion-heading">
<div class="title">任务管理>任务列表</div>
</div>
<div id="addAccordion" class="accordion-body in">
<div class="accordion-inner">
<div style="border: 0px solid red; height: 33px;">
<form:form action="${path}/taskController/list.do" method="post" modelAttribute="job" cssClass="form-inline"></form:form>
<lt:img menuName="任务列表" moduleName="运营管理"></lt:img>
</div>
<table class="table table-hover table-condensed">
<thead>
<tr>
<th width="4%"><input id="checkAll" name="checkAll" type="checkbox" style="margin-top: 0px;">全选</th>
<th>任务名称</th>
<th>任务分组</th>
<th>任务描述</th>
<th>创建时间</th>
<th>更新时间</th>
<th>任务表达式</th>
<th>执行类</th>
<th>执行方法</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<c:forEach items="${pb.dataList}" var="job" varStatus="status">
<tr>
<td><input name="checkItem" type="checkbox" value="${job.jobId}" style="margin-top: 0px;"></td>
<td>${job.jobName}</td>
<td>${job.jobGroup}</td>
<td>${job.jobDesc}</td>
<td>${job.createTime}</td>
<td>${job.updateTime}</td>
<td>${job.cronExpression}</td>
<td>${job.beanClass}</td>
<td>${job.executeMethod}</td>
<td>
<img src="${path}/resources/img/zengjian.png">
<a href="${path}/taskController/itemJob.do?jobId=${job.jobId}" >详细</a>
<lt:img menuName="任务列表" moduleName="运营管理" privilegeName="执行定时任务" clickName="立即执行"
clickMethod="executeJob('${job.jobName}','${job.jobGroup}','${job.jobId}');"></lt:img>
</td>
</tr>
</c:forEach>
<tr>
<td colspan="10" form-id="job" class="paginationPanel"><ltPage:page pageBean="${pb}" /></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<script type="text/javascript"> function executeJob(name,group,id){
$.ajax({
type: "POST",
url: "${path}/taskController/executeJob.do",
data: "jobName="+name+"&jobGroup="+group+"&jobId"+id,
success:function(data){
showSimpleMessage("定时任务已执行,执行结果请查看详情!");
}
});
} </script>
</body>
</html>
到这里,我们的spring3 整合quartz 2的定时任务功能终于是告一段落了,对常用的一些功能进行了实现,相信可以满足一般项目的需求了。