您的位置:首页 > 编程语言 > Java开发

Spring下quartz调度持久化实战

2015-09-09 15:16 393 查看
终于有时间写博客了,这次详细记录下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,大致结构如图



[/code]

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: