定時任務-quartz的使用,實現可頁面化管理

定時任務-quartz的使用,實現可頁面化管理
使用spring+quartz實現定時任務的頁面化管理。主要特色:
1.時間表達式等信息配置在數據庫中,從而實現頁面化管理。
2.能夠手動執行或者中止單個任務,也可使一個任務加入或者移出自動運行列表。

下面開始介紹用法,在這以前先說明框架的版本。spring3.2.4+quartz1.6.0
一.配置文件
只須要在spring的配置文件中加入:
<bean id="scheduler"  class="org.springframework.scheduling.quartz.SchedulerFactoryBean">  
	</bean>
	<bean id="jobManager"  class="com.temobi.quartz.JobManager">  
	</bean>

說明:scheduler對象是spring管理定時任務的對象。
jobManager是咱們自定義加載定時任務列表的對象,此對象加載全部任務列表後,將他們加入到自動運行列表。
二.jobManager代碼:
public class JobManager implements InitializingBean  {
	private static final Log log = LogFactory.getLog(JobManager.class);
	@Autowired
	TaskJobService taskJobService;
	@Autowired
	QuartzManager quartzManager;
	@Override
	public void afterPropertiesSet() throws Exception {
		loadAllJob();
	}
	private void loadAllJob(){
		List<TaskJob> list =taskJobService.getTaskList();
		quartzManager.enableCronSchedule(list);
	}
	
}


說明:
1.實現spring中InitializingBean接口,並覆蓋afterPropertiesSet方法,則該方法會在應用啓動的時候並且其餘servlet執行完成以後執行,此處用來加載全部定時任務,並加入定時任務自動運行列表。
2.quartzManager是咱們自定義的定時任務管理類,用來實現咱們文章開頭說的功能。
三.QuartzManager代碼
@Controller
public class QuartzManager {
	@Autowired
	Scheduler scheduler;
	
	private static final Log log = LogFactory.getLog(QuartzManager.class);
	public void enableCronSchedule(List<TaskJob> list) {
		for(TaskJob task : list){
			SchedulingJob job = new SchedulingJob();
			job.setJobId(task.getId());
			job.setJobName(task.getJobName());
			//job.setMemos(task.getNote());
			job.setCronExpression(task.getJobCronExpression());
			try{
			String  className=	task.getJobClass().trim();
				Class clazz = Class.forName(className);
				job.setStateFulljobExecuteClass(clazz);
			}catch(Exception e){
				e.printStackTrace();
				continue;
			}
			JobDataMap paramsMap = new JobDataMap();
			paramsMap.put("jobName", task.getJobName());

			if(task.getParamsKey1()!=null && task.getParamsValue1()!=null){
				paramsMap.put(task.getParamsKey1(), task.getParamsValue1());
			}
			if(task.getParamsKey2()!=null && task.getParamsValue2()!=null){
				paramsMap.put(task.getParamsKey2(), task.getParamsValue2());
			}
			if(task.getParamsKey3()!=null && task.getParamsValue3()!=null){
				paramsMap.put(task.getParamsKey3(), task.getParamsValue3());
			}
			enableCronSchedule(job, paramsMap, true);
			
			log.info("系統結束初始化任務:"+task.getId()+":"+task.getJobName()+":"+task.getJobId());
		}
	}
	/**
	 * 啓動一個自定義的job
	 * 
	 * @param schedulingJob
	 *            自定義的job
	 * @param paramsMap
	 *            傳遞給job執行的數據
	 * @param isStateFull
	 *            是不是一個同步定時任務,true:同步,false:異步
	 * @return 成功則返回true,不然返回false
	 */
	public boolean enableCronSchedule(SchedulingJob schedulingJob, JobDataMap paramsMap, boolean isStateFull) {
		if (schedulingJob == null) {
			return false;
		}
		try {
			//scheduler = (Scheduler) ApplicationHelper.getBean("scheduler");
			CronTrigger trigger = (CronTrigger) scheduler.getTrigger(schedulingJob.getTriggerName(),
					schedulingJob.getJobGroup());
			if (null == trigger) {// 若是不存在該trigger則建立一個
				JobDetail jobDetail = null;
				if (isStateFull) {
					jobDetail = new JobDetail(schedulingJob.getJobId(), schedulingJob.getJobGroup(),
							schedulingJob.getStateFulljobExecuteClass());
				} else {
					jobDetail = new JobDetail(schedulingJob.getJobId(), schedulingJob.getJobGroup(),
							schedulingJob.getJobExecuteClass());
				}
				jobDetail.setJobDataMap(paramsMap);
				trigger = new CronTrigger(schedulingJob.getTriggerName(), schedulingJob.getJobGroup(),
						schedulingJob.getCronExpression());
				scheduler.scheduleJob(jobDetail, trigger);
			} else {
				// Trigger已存在,那麼更新相應的定時設置
				trigger.setCronExpression(schedulingJob.getCronExpression());
				scheduler.rescheduleJob(trigger.getName(), trigger.getGroup(), trigger);
			}
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	/**
	 * 禁用一個job
	 * 
	 * @param jobId
	 *            須要被禁用的job的ID
	 * @param jobGroupId
	 *            須要被警用的jobGroupId
	 * @return 成功則返回true,不然返回false
	 */
	public boolean disableSchedule(String jobId) {
		if (jobId.equals("")) {
			return false;
		}
		try {
			String jobGroupId="DEFAULT";
			Trigger trigger = getJobTrigger(jobId, jobGroupId);
			if (null != trigger) {
				scheduler.deleteJob(jobId, jobGroupId);
			}
		} catch (SchedulerException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	/**
	 * 獲得job的詳細信息
	 * 
	 * @param jobId
	 *            job的ID
	 * @param jobGroupId
	 *            job的組ID
	 * @return job的詳細信息,若是job不存在則返回null
	 */
	public JobDetail getJobDetail(String jobId, String jobGroupId) {
		if (jobId.equals("") || jobGroupId.equals("") || null == jobId || jobGroupId == null) {
			return null;
		}
		try {
			return scheduler.getJobDetail(jobId, jobGroupId);
		} catch (SchedulerException e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 獲得job對應的Trigger
	 * 
	 * @param jobId
	 *            job的ID
	 * @param jobGroupId
	 *            job的組ID
	 * @return job的Trigger,若是Trigger不存在則返回null
	 */
	public Trigger getJobTrigger(String jobId, String jobGroupId) {
		if (jobId.equals("") || jobGroupId.equals("") || null == jobId || jobGroupId == null) {
			return null;
		}
		try {
			return scheduler.getTrigger(jobId + "Trigger", jobGroupId);
		} catch (SchedulerException e) {
			e.printStackTrace();
			return null;
		}
	}

}


說明:
1.主要方法有三個,啓動一個任務,禁用一個任務,啓動多個任務。啓動即加入自動運行列表,禁用即移出自動運行列表。
2.TaskJob是一個任務對象,和數據庫表結構相對應,後面給出數據庫設計。
3.程序中有相似,
paramsMap.put(task.getParamsKey1(), task.getParamsValue1());
這樣的代碼,意思是假如你:若是你在數據庫的ParamsKey1值爲"username",ParamsValue1的值爲"zhangsang".那麼你在具體的job中給定變量名爲"username"的變量並給出set/get方法,就能夠獲得值"zhangsang",此功能適用於給定時任務配置固定參數,而且參數名字隨便你定。咱們這裏給了三個備用的,你也能夠擴展,步驟就是數據庫加一個字段,在上面的程序中paramsMap放入這個字段,固然你也能夠不用參數。你數據庫沒有配置任何值,表示該定時任務沒有固定參數。
4.SchedulingJob是一個定時任務執行參數的bean。即 將Taskjob對象的值通過處理轉換成SchedulingJob對象,而後用SchedulingJob對象的值調用定時任務的API。
SchedulingJob對象主要作的事就是,TriggerName和JobGroup分別給出默認值。根據className生成StateFulljobExecuteClass的Class對象。
四。SchedulingJob代碼:
public class SchedulingJob {
	public static final int JS_ENABLED = 0; // 任務啓用狀態
    public static final int JS_DISABLED = 1; // 任務禁用狀態
    public static final int JS_DELETE = 2; // 任務已刪除狀態

    private String jobId; // 任務的Id,通常爲所定義Bean的ID
    private String jobName; // 任務的描述
    private String jobGroup; // 任務所屬組的名稱
    private int jobStatus; // 任務的狀態,0:啓用;1:禁用;2:已刪除
    private String cronExpression; // 定時任務運行時間表達式
    private String memos; // 任務描述
    private Class<?> stateFulljobExecuteClass;//同步的執行類,須要從StatefulMethodInvokingJob繼承
    private Class<?> jobExecuteClass;//異步的執行類,須要從MethodInvokingJob繼承
      /**
       * 獲得該job的Trigger名字
       * @return
       */
     public String getTriggerName() {
            return this.getJobId() + "Trigger";
     }
	public String getJobId() {
		return jobId;
	}
	public void setJobId(String jobId) {
		this.jobId = jobId;
	}
	public String getJobName() {
		return jobName;
	}
	public void setJobName(String jobName) {
		this.jobName = jobName;
	}
	public String getJobGroup() {
		if(jobGroup==null){
			jobGroup = Scheduler.DEFAULT_GROUP;
		}
		return jobGroup;
	}
	public void setJobGroup(String jobGroup) {
		this.jobGroup = jobGroup;
	}
	public int getJobStatus() {
		return jobStatus;
	}
	public void setJobStatus(int jobStatus) {
		this.jobStatus = jobStatus;
	}
	public String getCronExpression() {
		return cronExpression;
	}
	public void setCronExpression(String cronExpression) {
		this.cronExpression = cronExpression;
	}
	public String getMemos() {
		return memos;
	}
	public void setMemos(String memos) {
		this.memos = memos;
	}
	public Class<?> getStateFulljobExecuteClass() {
		return stateFulljobExecuteClass;
	}
	public void setStateFulljobExecuteClass(Class<?> stateFulljobExecuteClass) {
		this.stateFulljobExecuteClass = stateFulljobExecuteClass;
	}
	public Class<?> getJobExecuteClass() {
		return jobExecuteClass;
	}
	public void setJobExecuteClass(Class<?> jobExecuteClass) {
		this.jobExecuteClass = jobExecuteClass;
	}
	public static int getJS_ENABLED() {
		return JS_ENABLED;
	}
	public static int getJS_DISABLED() {
		return JS_DISABLED;
	}
	public static int getJS_DELETE() {
		return JS_DELETE;
	}

}

五。具體JOB實現
只要繼承QuartzJobBean類,覆蓋executeInternal方法便可。在job中可能經過get方法的方式獲得jobDetail對象中JobDataMap(詳見QuartzManager類)中同名參數值。示例代碼。
@Controller
public class ContentJob extends QuartzJobBean{
	@Autowired
	TaskJobService taskJobService;
	private String  beginDate;
	private String  endDate;
	
	/**
	 * 手動執行任務
	 * @param request
	 */
	@RequestMapping("/contentJobManual.do")
	public void manual(HttpServletRequest request) {
		String startDate=request.getParameter("startDate");
		String endDate=request.getParameter("endDate");
		TaskJobService taskJobService = (TaskJobService) ApplicationHelper.getBean("taskJobService");
		Map<String, String> param = new HashMap<String, String>();
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
		String today=sdf.format(new Date());
		if(StringUtils.isEmpty(startDate)){
			param.put("beginDate", today); 
		}else{
			param.put("beginDate", startDate); 
		}
		if(StringUtils.isEmpty(endDate)){
			param.put("endDate", today); 
		}else{
			param.put("endDate", endDate); 
		}
		taskJobService.callStatisticContent(param);
	}
	
	@Override
	public void executeInternal(JobExecutionContext context) {
		TaskJobService taskJobService = (TaskJobService) ApplicationHelper.getBean("taskJobService");
		Map<String, String> param = new HashMap<String, String>();
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
		String today=sdf.format(new Date());
		if(StringUtils.isEmpty(beginDate)){
			param.put("beginDate", today); 
		}else{
			param.put("beginDate", beginDate); 
		}
		if(StringUtils.isEmpty(endDate)){
			param.put("endDate", today); 
		}else{
			param.put("endDate", endDate); 
		}
		taskJobService.callStatisticContent(param);
	}
	
	public String getBeginDate() {
		return beginDate;
	}

	public void setBeginDate(String beginDate) {
		this.beginDate = beginDate;
	}

	public String getEndDate() {
		return endDate;
	}
	public void setEndDate(String endDate) {
		this.endDate = endDate;
	}

六。手動執行一個任務。能夠將該job類聲明成一個@Controller。另外寫一個方法如上例中的manual方法。
擴展:目前還不能將自動運行的方法和手動執行的方法(即executeInternal方法和manual方法)寫成一個。由於自動運行的方法不是一個action類,它不在web環境中,是經過反射實現的。若是把executeInternal這個方法強行配置成具備web功能的方法(即類上面加@Controller ,方法上面加@RequestMapping("/contentJobManual.do"))也是不行的,由於該方法沒有HttpServletRequest對象,獲取不了參數。除非你的定時任務沒有參數。固然你也不能修改該方法的參數類型,由於他是覆蓋QuartzJobBean的方法。
七。數據庫設計。
ID	VARCHAR2(60)	N				
JOB_CLASS	VARCHAR2(255)	N			
JOB_NAME	VARCHAR2(60)	N			
JOB_CRON_EXPRESSION	VARCHAR2(60)	N		
JOB_SERVICE_BEAN	VARCHAR2(60)	Y			
PARAMS_KEY1	VARCHAR2(60)	Y			
PARAMS_VALUE1	VARCHAR2(60)	Y			
PARAMS_KEY2	VARCHAR2(60)	Y			
PARAMS_VALUE2	VARCHAR2(60)	Y			
PARAMS_KEY3	VARCHAR2(60)	Y			
PARAMS_VALUE3	VARCHAR2(60)	Y			
NOTE	VARCHAR2(255)	Y			
JOB_STATUS	VARCHAR2(1)	Y			
UPDATETIME	DATE	Y			
JOB_AUTORUN	VARCHAR2(1)	Y
JOB_GROUP	VARCHAR2(60)	Y

說明:JOB_STATUS表示是否有效任務,JOB_AUTORUN表示是否自動運行,JOB_SERVICE_BEAN表示手動執行的請求URL,JOB_CLASS表示JOB類的全路徑,JOB_GROUP表示任務屬於哪一個組,方便對任務的分組管理(批量啓動,禁止等),區別於quartz的API所要求的同名參數,其實也能夠把這個值傳給API。其它字段比較好理解。該表對應的bean是taskjob。
八。頁面管理。
主要功能是將一個任務加入或者移出自動運行隊列(經過quartzManager對象)。和任務的增刪查改。示例代碼以下:
@Controller
public class TaskJobAction{
	private static final Log log = LogFactory.getLog(TaskJobAction.class);
	@Autowired
	TaskJobService taskJobService;
	@Autowired
	QuartzManager quartzManager;
	
	@RequestMapping("/enableTask.do")
	public void enableTask(HttpServletRequest request, HttpServletResponse response) throws IOException {
		String parameterStr="";
		parameterStr = IOUtils.toString(request.getInputStream(), InputConstant.CHAR_SET);
		parameterStr = StringUtils.trim(parameterStr);
		parameterStr =URLDecoder.decode(parameterStr,"utf-8");
		Map<String, String> p = JsonUtil.getParameterMap(parameterStr);
		String id=p.get("id");
		if(!StringUtils.isEmpty(id)){
			TaskJob task=taskJobService.getTaskById(id);
			List<TaskJob> list=new ArrayList<TaskJob>();
			list.add(task);
			quartzManager.enableCronSchedule(list);
			
			task.setJobEnabled("Y");
			taskJobService.update(task);//將任務設置成自動運行狀態
		}
			
	}
	@RequestMapping("/disableTask.do")
	public void disableTask(HttpServletRequest request, HttpServletResponse response) throws IOException {
		String parameterStr="";
		parameterStr = IOUtils.toString(request.getInputStream(), InputConstant.CHAR_SET);
		parameterStr = StringUtils.trim(parameterStr);
		parameterStr =URLDecoder.decode(parameterStr,"utf-8");
		Map<String, String> p = JsonUtil.getParameterMap(parameterStr);
		String id=p.get("id");
		if(!StringUtils.isEmpty(id)){
			TaskJob task=taskJobService.getTaskById(id);
			quartzManager.disableSchedule(task.getJobId());
			
			task.setJobEnabled("N");
			taskJobService.update(task);//將任務設置成非運行狀態
		}
			
	}
	@RequestMapping("/add.do")
	public void add(HttpServletRequest request, HttpServletResponse response) throws IOException {
		String parameterStr="";
			parameterStr = IOUtils.toString(request.getInputStream(), InputConstant.CHAR_SET);
			parameterStr = StringUtils.trim(parameterStr);
			Map<String, String> p = JsonUtil.getParameterMap(parameterStr);
			String jobjson=p.get("jobjson");
			jobjson=URLDecoder.decode(jobjson,"utf-8");
			TaskJob task=JsonUtil.toObject(jobjson, TaskJob.class);
			String jobName=URLDecoder.decode(task.getJobName(),"utf-8");
			task.setJobName(jobName);
			if(!StringUtils.isEmpty(jobjson)){
				taskJobService.insert(task);
			}
			
	}
	
	@RequestMapping("/update.do")
	public void update(HttpServletRequest request, HttpServletResponse response) throws IOException {
		String parameterStr="";
			parameterStr = IOUtils.toString(request.getInputStream(), InputConstant.CHAR_SET);
			parameterStr = StringUtils.trim(parameterStr);
			Map<String, String> p = JsonUtil.getParameterMap(parameterStr);
			String jobjson=p.get("jobjson");
			jobjson=URLDecoder.decode(jobjson,"utf-8");
			TaskJob task=JsonUtil.toObject(jobjson, TaskJob.class);
			String jobName=URLDecoder.decode(task.getJobName(),"utf-8");
			task.setJobName(jobName);
			if(!StringUtils.isEmpty(jobjson)){
				taskJobService.update(task);
			}
			
	}
	
	@RequestMapping("/delete.do")
	public void delete(HttpServletRequest request, HttpServletResponse response) throws IOException {
		String parameterStr="";
			parameterStr = IOUtils.toString(request.getInputStream(), InputConstant.CHAR_SET);
			parameterStr = StringUtils.trim(parameterStr);
			parameterStr =URLDecoder.decode(parameterStr,"utf-8");
			Map<String, String> p = JsonUtil.getParameterMap(parameterStr);
			String idStr=p.get("idStr");
			if(!StringUtils.isEmpty(idStr)){
				taskJobService.delete(idStr);
			}
			
	}
	@ResponseBody
	@RequestMapping("/taskList.do")
	public RecordResultBean list(HttpServletRequest request, HttpServletResponse response,@RequestParam("pageSize") int pageSize,
			@RequestParam("startIndex") int startIndex) throws IOException {
		int pageNum=startIndex/pageSize+1;
		String startDate=request.getParameter("startDate");
		String endDate=request.getParameter("endDate");
		String jobName=request.getParameter("jobName");
		if (!StringUtils.isEmpty(jobName)) {
			jobName=URLDecoder.decode(jobName, "UTF-8");
			jobName=URLDecoder.decode(jobName, "UTF-8");
		}
		RecordResultBean resultBean = new RecordResultBean();
		try {
			
			Pager pager = new Pager(pageNum, pageSize);
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("jobName",jobName);
			pager.setKeys(map);
			pager = taskJobService.findPage(pager);
			if (pager == null || pager.getTotalCount() == 0) {
				resultBean.setResult(false);

			} else {
				resultBean.setResult(true);
				resultBean.setBean(pager);
			}
			
		}catch(Exception ex) {
			log.warn(JDKStackTrace.getJDKStrack(ex));
		}
		
		return resultBean;
	}
相關文章
相關標籤/搜索