---每一個你不滿意的當下,都有一個你不曾努力的過去---
摘要:在項目的管理功能中,對定時任務的管理有時會很常見。但一般定時任務配置都在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
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的定時任務功能終於是告一段落了,對常用的一些功能進行了實現,相信可以滿足一般項目的需求了。
http://www.cnblogs.com/zishengY/p/7065665.html