一、ScheduleJob实体类介绍
public class ScheduleJob implements Serializable
{
public static String STATUS_RUNNING = "1";
public static final String STATUS_NOT_RUNNING = "0";
public static final String CONCURRENT_IS = "1";
public static final String CONCURRENT_NOT = "0";
/**
* 自己定义的组名与类名
*/
public static final String EXAM_NAME = "EXAM_NAME";
public static final String EXAM_GROUP = "EXAM_GROUP";
private Long jobId;
private Date createTime;
private Date endTime;
private Date updateTime;
/**
* 任务名称 必须
*/
private String jobName;
/**
* 任务分组 必须
*/
private String jobGroup;
/**
* 任务状态 是否启动任务
*/
private String jobStatus;
/**
* cron表达式 必须
*/
private String cronExpression;
/**
* 描述
*/
private String description;
/**
* 任务执行时调用哪个类的方法 包名+类名
*/
private String beanClass;
/**
* 任务是否有状态
*/
private String isConcurrent;
/**
* spring bean 指定springId方式可不指定beanClass
*/
private String springId;
/**
* 任务调用的方法名
*/
private String methodName;
}
二、简单的demo
//在线考试动态任务实例
ScheduleJob scheduleJob = new ScheduleJob();
scheduleJob.setJobId(1L);
scheduleJob.setJobName(QuartzManager.getExamName());
scheduleJob.setJobGroup(QuartzManager.getExamGroup());
scheduleJob.setJobStatus(ScheduleJob.STATUS_RUNNING);
//设定定时器调用的方法路径,一般调用Service中的方法 此实例调用answerResultService中的updateTimer方法
scheduleJob.setSpringId("answerResultService");
scheduleJob.setMethodName("updateTimer");
scheduleJob.setIsConcurrent(ScheduleJob.CONCURRENT_IS);
scheduleJob.setCreateTime(new Date());
int limittime = examina.getLimittime();
Date endTime = DateUtils.getAboutSecond(scheduleJob.getCreateTime(),limittime);
scheduleJob.setEndTime(endTime);
/**
* 参数设置非必须,视定时器调用的函数是否需要传参而定,Object数组传参适用于各种类型的参数
*/
HashMap map = new HashMap();
Class[] cArg = new Class[]{String.class};
Object[] objects = new Object[]{answerResult.getId()};
map.put("clazz", cArg);
map.put("values", objects);
quartzManager.addTriggerJob(scheduleJob,map);
三、动态管理定时器
/**
* 添加一个定时器
* @param job
* @param map
* @throws SchedulerException
*/
public void addTriggerJob(ScheduleJob job,Map map) throws SchedulerException
{
if (job == null || !ScheduleJob.STATUS_RUNNING.equals(job.getJobStatus()))
{
return;
}
Scheduler scheduler = SpringUtils.getBean(SchedulerFactoryBean.class).getScheduler();
TriggerKey triggerKey = TriggerKey.triggerKey(job.getJobName(),job.getJobGroup());
//此定时器于创建日期立即执行,在规定时间结束,期间1s执行一次
SimpleTrigger simpleTrigger =
(SimpleTrigger) TriggerBuilder.newTrigger().
withIdentity(job.getJobName(),job.getJobGroup()).
startAt(job.getCreateTime()).endAt(job.getEndTime()).
withSchedule(SimpleScheduleBuilder.simpleSchedule().
withIntervalInSeconds(1).repeatForever()).build();
//此定时器在规定时间执行,切执行一次
//SimpleTrigger simpleTrigger =
(SimpleTrigger) TriggerBuilder.newTrigger().
withIdentity(job.getJobName(), job.getJobGroup()).
startAt(startTime).build();
//此定时器在规定时间执行,期间以规定的时间间隔执行一次或数次,无结束日期,在定时任务删除时结束
//SimpleTrigger simpleTrigger =
(SimpleTrigger)TriggerBuilder.newTrigger().
withIdentity(job.getJobName(),job.getJobGroup()).
startAt(startTime).
withSchedule(SimpleScheduleBuilder.simpleSchedule() .
withIntervalInHours(space).repeatForever()).build();
Class clazz = ScheduleJob.CONCURRENT_IS.equals(job.getIsConcurrent())
? QuartzJobFactory.class: QuartzJobFactoryDisallowConcurrentExecution.class;
JobDetail jobDetail = JobBuilder.newJob(clazz).withIdentity(job.getJobName(),
job.getJobGroup()).build();
jobDetail.getJobDataMap().put("scheduleJob", job);
jobDetail.getJobDataMap().put("map", map);
Date date = scheduler.scheduleJob(jobDetail,simpleTrigger );
System.out.println(jobDetail.getKey() + " will run at: " + date + " and repeat: "+ simpleTrigger.getRepeatCount()
+ " times, every " + simpleTrigger.getRepeatInterval() / 1000L + " seconds");
}
/**
* 获取所有计划中的任务列表
*
* @return
* @throws SchedulerException
*/
public List<ScheduleJob> getAllJob() throws SchedulerException
{
Scheduler scheduler = SpringUtils.getBean(SchedulerFactoryBean.class).getScheduler();
GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
List<ScheduleJob> jobList = new ArrayList<ScheduleJob>();
for (JobKey jobKey : jobKeys)
{
List<? extends Trigger> triggers = scheduler
.getTriggersOfJob(jobKey);
for (Trigger trigger : triggers)
{
ScheduleJob job = new ScheduleJob();
job.setJobName(jobKey.getName());
job.setJobGroup(jobKey.getGroup());
job.setDescription("触发器:" + trigger.getKey());
Trigger.TriggerState triggerState = scheduler
.getTriggerState(trigger.getKey());
job.setJobStatus(triggerState.name());
if (trigger instanceof CronTrigger)
{
CronTrigger cronTrigger = (CronTrigger) trigger;
String cronExpression = cronTrigger.getCronExpression();
job.setCronExpression(cronExpression);
}
jobList.add(job);
}
}
return jobList;
}
/**
* 所有正在运行的job
*
* @return
* @throws SchedulerException
*/
public List<ScheduleJob> getRunningJob() throws SchedulerException
{
Scheduler scheduler = SpringUtils.getBean(SchedulerFactoryBean.class).getScheduler();
List<JobExecutionContext> executingJobs = scheduler
.getCurrentlyExecutingJobs();
List<ScheduleJob> jobList = new ArrayList<ScheduleJob>(
executingJobs.size());
for (JobExecutionContext executingJob : executingJobs)
{
ScheduleJob job = new ScheduleJob();
JobDetail jobDetail = executingJob.getJobDetail();
JobKey jobKey = jobDetail.getKey();
Trigger trigger = executingJob.getTrigger();
job.setJobName(jobKey.getName());
job.setJobGroup(jobKey.getGroup());
job.setDescription("触发器:" + trigger.getKey());
Trigger.TriggerState triggerState = scheduler
.getTriggerState(trigger.getKey());
job.setJobStatus(triggerState.name());
if (trigger instanceof CronTrigger)
{
CronTrigger cronTrigger = (CronTrigger) trigger;
String cronExpression = cronTrigger.getCronExpression();
job.setCronExpression(cronExpression);
}
jobList.add(job);
}
return jobList;
}
/**
* 暂停一个job
*
* @param scheduleJob
* @throws SchedulerException
*/
public void pauseJob(ScheduleJob scheduleJob) throws SchedulerException
{
Scheduler scheduler = SpringUtils.getBean(SchedulerFactoryBean.class).getScheduler();
JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(),scheduleJob.getJobGroup());
scheduler.pauseJob(jobKey);
}
/**
* 恢复一个job
*
* @param scheduleJob
* @throws SchedulerException
*/
public void resumeJob(ScheduleJob scheduleJob) throws SchedulerException
{
Scheduler scheduler = SpringUtils.getBean(SchedulerFactoryBean.class).getScheduler();
JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(),scheduleJob.getJobGroup());
scheduler.resumeJob(jobKey);
}
/**
* 删除一个job
*
* @param scheduleJob
* @throws SchedulerException
*/
public void deleteJob(String jobName, String jobGroup) throws SchedulerException
{
Scheduler scheduler = SpringUtils.getBean(SchedulerFactoryBean.class).getScheduler();
JobKey jobKey = JobKey.jobKey(jobName,
jobGroup);
scheduler.deleteJob(jobKey);
}
/**
* 立即执行job
*
* @param scheduleJob
* @throws SchedulerException
*/
public void runAJobNow(ScheduleJob scheduleJob) throws SchedulerException
{
Scheduler scheduler = SpringUtils.getBean(SchedulerFactoryBean.class).getScheduler();
JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(),
scheduleJob.getJobGroup());
scheduler.triggerJob(jobKey);
}
四、定时器执行流程
/**
* 计划任务执行处 无状态 并发执行
* @author zdw
* 有状态,添加@DisallowConcurrentExecution注解进行取消并发
*/
public class QuartzJobFactory implements Job
{
@Override
public void execute(JobExecutionContext context) throws JobExecutionException
{
ScheduleJob scheduleJob = (ScheduleJob) context.getMergedJobDataMap().get("scheduleJob");
TaskUtils.invokMethod(scheduleJob,context);
}
}
/**
* 通过反射调用scheduleJob中定义的方法
*
* @param scheduleJob
*/
public static void invokMethod(ScheduleJob scheduleJob,JobExecutionContext context) {
Object object = null;
Class clazz = null;
//springId不为空先按springId查找bean
if (StringUtils.isNotEmpty(scheduleJob.getSpringId())) {
object = SpringUtils.getBean(scheduleJob.getSpringId());
} else if (StringUtils.isNotEmpty(scheduleJob.getBeanClass())) {
try {
clazz = Class.forName(scheduleJob.getBeanClass());
object = clazz.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}
if (object == null) {
log.error("任务名称 = [" + scheduleJob.getJobName() + "]---------------未启动成功,请检查是否配置正确!!!");
return;
}
clazz = object.getClass();
Method method = null;
JobDataMap jdm = context.getMergedJobDataMap();
HashMap map = (HashMap) jdm.get("map");
if(map != null || map.size() != 0){
Class[] cArg = (Class[]) map.get("clazz");
Object[] values = (Object[]) map.get("values");
try {
method = clazz.getDeclaredMethod(scheduleJob.getMethodName(),cArg);
} catch (NoSuchMethodException e) {
log.error("任务名称 = [" + scheduleJob.getJobName() + "]---------------未启动成功,方法名设置错误!!!");
} catch (SecurityException e) {
e.printStackTrace();
}
if (method != null) {
try {
method.invoke(object,values);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
} else{
try {
method = clazz.getDeclaredMethod(scheduleJob.getMethodName());
} catch (NoSuchMethodException e) {
log.error("任务名称 = [" + scheduleJob.getJobName() + "]---------------未启动成功,方法名设置错误!!!");
} catch (SecurityException e) {
e.printStackTrace();
}
if (method != null) {
try {
method.invoke(object);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
五、配置相关
pom.xml
<!-- quartz -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.2.2</version>
</dependency>
applicationContext-quartz-cron-local.xml
<description>Quartz的本地Cron式执行任务配置</description>
<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" >
<!-- Job接受applicationContext的成员变量名 -->
<property name="applicationContextSchedulerContextKey" value="applicationContext" />
</bean>
applicationContext-quartz-timer-cluster.xml
<description>Quartz的定时集群任务配置</description>
<!-- Quartz集群Schduler -->
<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" >
<!-- Triggers集成 -->
<property name="triggers">
<list>
</list>
</property>
<!-- quartz配置文件路径, 指向cluster配置 -->
<property name="configLocation" value="classpath:schedule/quartz-cluster.properties" />
<!-- 启动时延期2秒开始任务 -->
<property name="startupDelay" value="30" />
<!-- 保存Job数据到数据库所需的数据源 -->
<property name="dataSource" ref="quartzDataSource" />
<!-- Job接受applicationContext的成员变量名 -->
<property name="applicationContextSchedulerContextKey" value="applicationContext" />
</bean>
<!-- Job的可配置属性,在job中通过applicationContext动态获取 -->
<util:map id="timerJobConfig">
<entry key="nodeName" value="${server.node_name}" />
</util:map>