Spring下quartz调度持久化实战

终于有时间写博客了,这次详细记录下Spring 3.X中quartz框架如何持久化调度任务相关知识点,按照目录编排。

1.介绍

1.1quartz概述

Quartz包含三个抽象概念,调度器(谁管理),任务(干什么),触发器(什么时候干).其中几个名词大致介绍下:
@1:Job:接口,实现接口方法定义任务
@2:JobDetail:关联Job实现类和Schedular的类,其构造函数,指定Job实现类,任务在Schedular中的组名和Job名称
@3:Trigger:触发器类,描述触发事件,包含简单的时间规则和复杂的时间规则,SimpleTrigger和CronTrigger
@4:Schedular:Quartz容器,包含Trigger和JobDetail,大致结构如图



1.2持久化12张表

12张表:


pdm结构



具体的pdm,文章最后将会以附件形式上传。


2.持久化配置

quartz.xml:
<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
	
	<!-- quartz持久化存储 -->
	<bean id="quartzScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
		<property name="dataSource">  
			<ref bean="dataSource"/>  
		</property>
		<property name="applicationContextSchedulerContextKey"  value="applicationContextKey" />
		<property name="configLocation" value="classpath:/quartz/quartz.properties"/>
	</bean>
	
	<!--记录调度日志服务 -->
	<bean id="simpleService" class="com.ai.sm.quartz.job.SimpleService"> 
    </bean> 
	
	<!-- 任务详情 -->
	<bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailBean">
		<property name="jobClass">
			<value>com.ai.sm.quartz.job.MyQuartzJobBean</value>
		</property>
		<property name="jobDataAsMap">
			<map>
				<entry key="simpleService">
					<ref bean="simpleService"/>
				</entry>
			</map>
		</property>
	</bean>	
	
	<!-- 封装调度服务 -->
	<bean id="schedulerService" class="com.ai.sm.quartz.smo.SchedulerServiceImpl"> 
    	<property name="scheduler">
			<ref bean="quartzScheduler" />
		</property>
		<property name="jobDetail">
			<ref bean="jobDetail" />
		</property>
    </bean> 
</beans>
1.工厂模式,建立一个SchedulerFactoryBean的实例,其中需要指定dataSource,configLocation,其中最重要的就是引入了quartz.properties这样一个配置文件。
2.定义一个simpleService,主要是记录任务调度日志。
3.定义JobDetailBean的实例,需要指定jobClass,调度任务处理类,这里我需要记录日志,所以property是simpleService。
4.封装一个服务schedulerService,对外提供任务的创建,销毁,启动,停用等API。

quartz.properties:
#============================================================================
# Configure Main Scheduler Properties 
#============================================================================
org.quartz.scheduler.instanceName = DefaultQuartzScheduler
org.quartz.scheduler.rmi.export = false
org.quartz.scheduler.rmi.proxy = false
org.quartz.scheduler.wrapJobExecutionInUserTransaction = false

#============================================================================
# Configure ThreadPool   配置数据库连接池
#============================================================================
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool  
org.quartz.threadPool.threadCount = 10
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true

#============================================================================
# Configure JobStore  配置做业存储方式
#============================================================================
#相当于扫描频率,如果系统基于秒级,应培植成1000,quartz默认为分级(60000-分钟级别)
org.quartz.jobStore.misfireThreshold = 60000
#org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore

#在这里自己控制事务
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.HSQLDBDelegate
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate   
#org.quartz.jobStore.useProperties = true
org.quartz.jobStore.tablePrefix = QRTZ_  
org.quartz.jobStore.isClustered = false  
org.quartz.jobStore.maxMisfiresToHandleAtATime=1 

3.任务调度对外API

该API主要是提供任务创建,销毁,启用,停用,并对启用/体用过程记录日志。
simpleService:
package com.ai.sm.quartz.job;

import java.io.Serializable;


/**
 * 记录调度日志信息 
 * @author Administrator
 * @see [相关类/方法](可选)
 * @since [产品/模块版本] (可选)
 */
public class SimpleService implements Serializable{
	
	private static final long serialVersionUID = 122323233244334343L;
	
	private TaskSMO taskSMO = null;

	public TaskSMO getTaskSMO() {
		if (taskSMO == null) {
			taskSMO = (TaskSMO) SpringBeanInvoker.getBean("task.taskSMO");
		}
		return taskSMO;
	}

	/**
	 * 
	 * 功能描述: 主要处理调度日志
	 * 〈功能详细描述〉
	 *
	 * @param triggerName
	 * @see [相关类/方法](可选)
	 * @since [产品/模块版本](可选)
	 */
	public void vsopMethod(String triggerName){
		//这里执行定时调度业务
		TriggersExecLogModel triggersExecLog =new TriggersExecLogModel();
		TriggersClassRelModel triggersClassRel = new TriggersClassRelModel();
		triggersClassRel.setRelId(Long.valueOf(triggerName));
		List list =this.getTaskSMO().queryTriggersClassRel(triggersClassRel);
		triggersExecLog.setTriggerName(triggerName);
		triggersExecLog.setStartDt(new Date());	
		HttpURLConnection http_conn = null;
		Long logId= new Long(0);
		if(list.size()>0){
			triggersClassRel=(TriggersClassRelModel)list.get(0);
			triggersExecLog.setJobName(triggersClassRel.getTriggerName());
			try{
				if(triggersClassRel.getClassType()==3){
					if(triggersClassRel.getClassPara().startsWith("http")){
						 logId=this.taskSMO.queryCountLogId();
						 URL http_url = new URL(triggersClassRel.getClassPara());   
						 http_conn = (HttpURLConnection) http_url.openConnection();
				         http_conn.setDoOutput(true);
				         http_conn.setRequestMethod("POST");//传输用post方式
				         http_conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
				         http_conn.connect();
				         DataOutputStream out = new DataOutputStream(http_conn.getOutputStream());
				         
				         String str_buf = new String();
				         
					     str_buf="jobId="+logId;
				        
				         out.writeBytes(str_buf);
				         out.flush();
				         out.close();
				         int code = http_conn.getResponseCode();
					}else{
						JobMethodType.javaMethod(triggersClassRel.getClassPara());
					}
				}
				if(triggersClassRel.getClassType()==2){
					this.getTaskSMO().queryCall(triggersClassRel.getClassPara());
				}
				triggersExecLog.setLogId(logId);
				triggersExecLog.setEndDt(new Date());
				triggersExecLog.setStateCd("2");
				triggersExecLog.setRelClass(triggersClassRel.getClassPara());
				triggersExecLog.setCreateDt(new Date());
				triggersExecLog.setRemarks("调用成功");
				this.getTaskSMO().insertTriggersExecLog(triggersExecLog);
			}catch(Exception e){
				e.printStackTrace();
				logId=this.taskSMO.queryCountLogId();
				triggersExecLog.setLogId(logId);
				triggersExecLog.setEndDt(new Date());
				triggersExecLog.setStateCd("3");
				triggersExecLog.setCreateDt(new Date());
				triggersExecLog.setRemarks(MsgHandleUtil.getSubStr(MsgHandleUtil.getExceptionString(e), 300));
				this.getTaskSMO().insertTriggersExecLog(triggersExecLog);
			}finally{
			      if(http_conn!=null)
			    	  http_conn.disconnect();
			}
		}
	}
}

MyQuartzJobBean:
public class MyQuartzJobBean extends QuartzJobBean {

	private SimpleService simpleService;
	
	public void setSimpleService(SimpleService simpleService) {
		this.simpleService = simpleService;
	}

	@Override
	protected void executeInternal(JobExecutionContext jobexecutioncontext)  {
		Trigger trigger = jobexecutioncontext.getTrigger();
		String triggerName = trigger.getName();		
		simpleService.vsopMethod(triggerName);
	}

}


SchedulerServiceImpl:
package com.ai.sm.quartz.smo;


import java.text.ParseException;
import java.util.Date;
import java.util.Map;
import java.util.UUID;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.commons.lang.time.DateUtils;

import org.quartz.CronExpression;
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleTrigger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;


@Service("schedulerService")
public class SchedulerServiceImpl implements SchedulerService {

	private Scheduler scheduler;
	private JobDetail jobDetail;
	@Autowired
	public void setJobDetail(@Qualifier("jobDetail") JobDetail jobDetail) {
		this.jobDetail = jobDetail;
	}

	@Autowired
	public void setScheduler(@Qualifier("quartzScheduler") Scheduler scheduler) {
		this.scheduler = scheduler;
	}


	public void schedule(String cronExpression) {
		schedule("", cronExpression);
	}

	
	public void schedule(String name, String cronExpression) {
		schedule( name,  cronExpression,Scheduler.DEFAULT_GROUP);
	}
	
	
	public void schedule(String name, String cronExpression,String group) {
		try {
			schedule(name, new CronExpression(cronExpression),group);
		} catch (ParseException e) {
			throw new RuntimeException(e);
		}
	}

	
	public void schedule(CronExpression cronExpression) {
		schedule(null, cronExpression);
	}

	
	public void schedule(String name, CronExpression cronExpression) {
		schedule( name,  cronExpression,Scheduler.DEFAULT_GROUP) ;
	}
	
	
	public void schedule(String name, CronExpression cronExpression,String group) {
		if (name == null || name.trim().equals("")) {
			name = UUID.randomUUID().toString();
		}

		try {
			scheduler.addJob(jobDetail, true);

			CronTrigger cronTrigger = new CronTrigger(name, group, jobDetail.getName(),
					Scheduler.DEFAULT_GROUP);
			cronTrigger.setCronExpression(cronExpression);
			scheduler.scheduleJob(cronTrigger);
			scheduler.rescheduleJob(cronTrigger.getName(), cronTrigger.getGroup(), cronTrigger);
			
		} catch (SchedulerException e) {
			throw new RuntimeException(e);
		}
	}

	public void schedule(Map<String,String> map) {
		
		String temp = null;
		SimpleTrigger simpleTrigger = new SimpleTrigger();
		
		simpleTrigger.setJobName(jobDetail.getName());		
		simpleTrigger.setJobGroup(Scheduler.DEFAULT_GROUP);		
		simpleTrigger.setRepeatInterval(1000L);
		
		temp = map.get("triggerName");		
		if (StringUtils.isEmpty(StringUtils.trim(temp)) ){
			temp = UUID.randomUUID().toString();
		}else{
			temp +="&"+UUID.randomUUID().toString();
		}
		simpleTrigger.setName(temp);
		
		temp = map.get("triggerGroup");
		if(StringUtils.isEmpty(temp)){
			temp = Scheduler.DEFAULT_GROUP;
		}
		simpleTrigger.setGroup(temp);
		
		temp = map.get("startTime");
		if(StringUtils.isNotEmpty(temp)){
			simpleTrigger.setStartTime(this.parseDate(temp));
		}
		
		temp = map.get("endTime");
		if(StringUtils.isNotEmpty(temp)){
			simpleTrigger.setEndTime(this.parseDate(temp));
		}
		
		temp = map.get("repeatCount");
		if(StringUtils.isNotEmpty(temp) && NumberUtils.toInt(temp) > 0){
			simpleTrigger.setRepeatCount(NumberUtils.toInt(temp));
		}
		
		temp = map.get("repeatInterval");
		if(StringUtils.isNotEmpty(temp) && NumberUtils.toLong(temp) > 0){
			simpleTrigger.setRepeatInterval(NumberUtils.toLong(temp)*1000);
		}

		try {
			scheduler.addJob(jobDetail, true);
		
			scheduler.scheduleJob(simpleTrigger);
			scheduler.rescheduleJob(simpleTrigger.getName(), simpleTrigger.getGroup(), simpleTrigger);
		} catch (SchedulerException e) {
			throw new RuntimeException(e);
		}
	}
	
	
	public void pauseTrigger(String triggerName,String group){		
		try {
			scheduler.pauseTrigger(triggerName, group);
		} catch (SchedulerException e) {
			throw new RuntimeException(e);
		}
	}
	
	
	public void resumeTrigger(String triggerName,String group){		
		try {
			//Trigger trigger = scheduler.getTrigger(triggerName, group);
			
			scheduler.resumeTrigger(triggerName, group);
		} catch (SchedulerException e) {
			throw new RuntimeException(e);
		}
	}
	
	
	public boolean removeTrigdger(String triggerName,String group){		
		try {
			scheduler.pauseTrigger(triggerName, group);
			return scheduler.unscheduleJob(triggerName, group);
		} catch (SchedulerException e) {
			throw new RuntimeException(e);
		}
	}
	
	private Date parseDate(String time){
		try {
			return DateUtils.parseDate(time, new String[]{"yyyy-MM-dd HH:mm"});
		} catch (ParseException e) {			
			throw new RuntimeException(e);
		}
	}
}


附件是相关pdm结构,地址http://download.csdn.net/detail/weiweiai123456/9092107




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值