java自带定时任务可以解决部分问题但是当我们要动态执行定时任务时,quartz可以帮助我们有效解决这类型问题
代码亲测可用
springmvc中配置注入调度器scheduler,调用定时任务
<!-- quart -->
<!-- 调度类,如果lazy-init="false"容器启动时候回执行调度程序 -->
<bean id="scheduler" lazy-init="false" autowire="no" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"></bean>
<!-- 用来设置触发时间的,startJobs方法启动调度容器,然后按照上面的触发器,每个1s执行一次myjob2.dosomething()方法 -->
<bean id="quartzManager" class="cn.com.sinosoft.controller.QuartzManager" lazy-init="true" init-method="startJobs">
<!-- 注入对象,管理定时任务,还有在类型要用set get方法,否则会报异常 -->
<property name="scheduler" ref="scheduler" ></property>
</bean>
代码逻辑
quartzManager的调用方式,
QuartzManager qm = new QuartzManager();//newquartzManager对象
qm.addJob(votes.getName(), "group"+votes.getName(), "trigger"+votes.getName(), "triggerGroup"+votes.getName(),
VoteJob.class,CronDateUtils.getCron(sdf.parse(votes.getEnd_time())),sdf.parse(votes.getOpen_time()), sdf.parse(votes.getEnd_time()),sdf.parse(votes.getOpen_time_join()),sdf.parse(votes.getEnd_time_join()),votes.getId());//直接调用给指定方法就ok
QuartzManager 直接copy即可,根据业务需要修改每个方法的传递参数(笔者该方法使用的是cronSchedule调度器,按照日历的格式,定期执行定时任务)
import java.text.SimpleDateFormat;
import java.util.Date;
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.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.matchers.EverythingMatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import cn.com.sinosoft.lisener.MyJobListener;
import cn.com.sinosoft.service.FxActivityService;
public class QuartzManager {
Logger logger = LoggerFactory.getLogger(this.getClass());
private Scheduler scheduler;
@Autowired
private FxActivityService fxActivityService;
//新增定时任务
@SuppressWarnings({ "unchecked", "rawtypes" })
public void addJob(String jobName,String jobGroupName,String triggerName,String triggerGroupName,Class jobClass,String cron, Date open_time, Date end_time, Date open_time_join, Date end_time_join, String id) {
//该方法中除了String jobName,String jobGroupName,String triggerName,String triggerGroupName,Class jobClass,String cron 固定以外其他参数可以删除,可以新增
//注意 Class jobClass 即为自己下边继承JOB接口的实体类
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//设置任务的开始时间
Date startDate = open_time;
//设置任务的结束时间
Date endDate = end_time;
System.out.println("结束时间:"+endDate);
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
//指定要运行的任务,设置人物名,任务组名
JobDetail jobDetail= JobBuilder.newJob(jobClass).
withIdentity(jobName, jobGroupName).
usingJobData("open_time",sdf.format(open_time)).//将参数存入jondetail中传递到voteJob中,借助 JobDataMap map = context.getJobDetail().getJobDataMap();*取出
usingJobData("end_time",sdf.format(end_time)).
usingJobData("open_time_join",sdf.format(open_time_join)).
usingJobData("end_time_join",sdf.format(end_time_join)).
usingJobData("id",id).
build();
//配置触发器
//1新建一个触发器构造类
TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
//2设置触发器名,触发器组名
triggerBuilder.withIdentity(triggerName, triggerGroupName);
//也可以在这里携带参数,方法与jobdetail中相同
//设置任务立即执行
//triggerBuilder.startNow();
//设置任务开始时间
triggerBuilder.startAt(startDate);
//设置任务结束时间
triggerBuilder.endAt(endDate);
//3设置触发器时间规则
triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
//4触发器构造类创建trigger对象
CronTrigger trigger = (CronTrigger) triggerBuilder.build();
//上边创建好的任务和构造器注入到调度器
scheduler.scheduleJob(jobDetail, trigger);
//全局监听
scheduler.getListenerManager().addJobListener(new MyJobListener(),EverythingMatcher.allJobs());
//局部监听
//scheduler.getListenerManager().addJobListener(new MyJobListener(),KeyMatcher.keyEquals(JobKey.jobKey(jobName, jobGroupName)));
//启动调度器
if(!scheduler.isShutdown()) {
scheduler.start();
}
//挂起定时任务
//scheduler.standby();
} catch (Exception e) {
e.printStackTrace();
}
}
//修改定时任务cron表达式
public void modifyJobTime (String jobName,String jobGroupName,String triggerName,String triggerGroupName,String cron, Date open_time, Date end_time, Date open_time_join, Date end_time_join) {
//该方法中除了String jobName,String jobGroupName,String triggerName,String triggerGroupName,String cron固定以外其他参数可以删除
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//设置任务的开始时间
Date startDate = open_time;
//设置任务的结束时间
Date endDate = end_time;
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
TriggerKey triggerKey = TriggerKey.triggerKey(triggerName,triggerGroupName);
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
logger.info("定时任务组名:"+trigger);
if(trigger == null) {
logger.info("trigger为空:"+trigger);
return;
}
String oldTime = trigger.getCronExpression();
if(!oldTime.equalsIgnoreCase(cron)) {
TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
triggerBuilder.withIdentity(triggerName,triggerGroupName).
usingJobData("open_time",sdf.format(open_time)).
usingJobData("end_time",sdf.format(end_time)).
usingJobData("open_time_join",sdf.format(open_time_join)).
usingJobData("end_time_join",sdf.format(end_time_join));
//triggerBuilder.startNow();
triggerBuilder.startAt(open_time);
triggerBuilder.endAt(end_time);
triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
trigger = (CronTrigger) triggerBuilder.build();
scheduler.rescheduleJob(triggerKey, trigger);
}
} catch (Exception e) {
e.printStackTrace();
}
}
//删除定时任务
public void removeJob(String jobName,String jobGroupName,
String triggerName,String triggerGroupName) {
try {
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
TriggerKey triggerKey = TriggerKey.triggerKey(triggerName,triggerGroupName);
scheduler.pauseTrigger(triggerKey);//停止定时任务
scheduler.unscheduleJob(triggerKey);//移除定时人体五
scheduler.deleteJob(JobKey.jobKey(jobName
, jobGroupName));//删除任务
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//启动所有定时任务
public void startJob() {
try {
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.start();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//关闭所有定时任务
public void shutdownJobs() {
try {
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
if(!scheduler.isShutdown()) {
/**
* true等待所有job结束后关闭,false直接关闭不等待所有job结束
* scheduler.shutdown(true);
* scheduler.shutdown(false);
*/
scheduler.shutdown();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//得到所有定时任务
public Scheduler getScheduler() {
return scheduler;
}
//写入定时任务
public void setScheduler(Scheduler scheduler) {
this.scheduler = scheduler;
}
}
Vote工作类,将定时任务需要执行的代码放到这里,交给quartz管理到时间可以自动执行,
import java.text.SimpleDateFormat;
import java.util.Date;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;
import org.quartz.TriggerKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import cn.com.sinosoft.service.FxActivityService;
public class VoteJob implements Job {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private FxActivityService fxActivityService;
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
/**
* 新增活动,加入到quartz中管理,定期执行,判断活动时间是否超期限,如果超过期限则修改活动状态
*/
logger.info("新增定时任务Vote");
try {
// 获取时间范围
//对应quartzManager中传递过来的数据
JobDataMap map = context.getJobDetail().getJobDataMap();*
String open_time = (String) map.get("open_time");
String end_time = (String) map.get("end_time");
String open_time_join = (String) map.get("open_time_join");
String end_time_join = (String) map.get("end_time_join");
String id = (String) map.get("id");
// 将字符串转换为date
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date open_times = sdf.parse(open_time);
Date end_times = sdf.parse(end_time);
Date open_time_joins = sdf.parse(open_time_join);
Date end_time_joins = sdf.parse(end_time_join);
Date nowtime = new Date();
sdf.format(nowtime);
//比较date大小,如果前端大于后边返回值为1,前边小于后边返回-1,相等返回0
int compareTo = nowtime.compareTo(end_times);
//当前时间等于结束时间,修改活动状态为无效
JobKey jobKey = context.getJobDetail().getKey();
logger.info("工作任务名称:"+jobKey.getName());
logger.info("工作组名称:"+jobKey.getGroup());
logger.info("任务类名称(全路径):"+context.getJobDetail().getJobClass().getName());
logger.info("任务类名称:"+context.getJobDetail().getJobClass().getSimpleName());
TriggerKey triggerKey = context.getTrigger().getKey();
logger.info("触发器任务名称:"+triggerKey.getName());
logger.info("触发器组名称:"+triggerKey.getGroup());
if(compareTo == 1) {
logger.info("到期自动结束定时任务");
//修改活动状态为无效
int u = fxActivityService.updateActivityStates(id);
if(u==1) {
logger.info("修改任务状态成功");
}
}
//比较开始和结束时间的大小判断活动是否有效
} catch (Exception e) {
logger.info("VoteJob逻辑异常");
e.printStackTrace();
}
}
}
注意:一个job可以对应多个trigger 但是一个trigger只能对应一个job
工具类
data和cron格式转换
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 该类提供Quartz的cron表达式与Date之间的转换
* Created by zhangzh on 2016/8/2.
*/
public class CronDateUtils {
private static final String CRON_DATE_FORMAT = "ss mm HH dd MM ? yyyy";
private static Logger logger = LoggerFactory.getLogger(CronDateUtils.class);
/***
*
* @param date 时间
* @return cron类型的日期
*/
public static String getCron(final Date date){
SimpleDateFormat sdf = new SimpleDateFormat(CRON_DATE_FORMAT);
String formatTimeStr = "";
if (date != null) {
formatTimeStr = sdf.format(date);
}
return formatTimeStr;
}
/***
*
* @param cron Quartz cron的类型的日期
* @return Date日期
*/
public static Date getDate(final String cron) {
if(cron == null) {
return null;
}
SimpleDateFormat sdf = new SimpleDateFormat(CRON_DATE_FORMAT);
Date date = null;
try {
date = sdf.parse(cron);
} catch (ParseException e) {
logger.info("cron的类型的日期格式转换异常");
return null;// 此处缺少异常处理,自己根据需要添加
}
return date; }}
进阶
初始化时候通过监听启动quartz
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import cn.com.sinosoft.controller.QuartzManager;
import cn.com.sinosoft.po.Vote;
import cn.com.sinosoft.quartz.job.VoteJob;
import cn.com.sinosoft.service.FxActivityService;
import cn.com.sinosoft.service.VoteService;
import cn.com.sinosoft.util.CronDateUtils;
@Component
public class IniterListener implements ApplicationListener<ContextRefreshedEvent>{
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private FxActivityService fxActivityService;
@Autowired
private VoteService voteService;
@Override
public void onApplicationEvent(ContextRefreshedEvent arg0) {
logger.info("bean容器初始化完成之后执行");
try {
//查询数据库中所有的活动,判断活动的有效状态,超期的置为无效,
//Vote vote = new Vote();
List<Vote> v = voteService.selectAllVoteForUsers();
for(Vote votes : v) {
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//当前系统时间
Date d = sdf.parse(sdf.format(date));
//Date open = sdf.parse(votes.getOpen_time());
Date end = sdf.parse(votes.getEnd_time());
//当前时间大于等于结束时间
int i = d.compareTo(end);
if(i==1||i==0) {
//修改当前活动状态置为无效
int j = fxActivityService.updateActivityStates(votes.getId());
if(j==1) {
logger.info("修改活动状态成功");
}else {
logger.info("修改活动状态失败,失败的活动名称为:"+votes.getId()+"名称:"+votes.getName());
}
}
//截止时间大于当前时间,同时活动状态为有效
if(i==-1&&votes.getStatus().equals("0")) {
logger.info("添加活动到qz:活动名称为:"+votes.getName());
//有效活动添加到qz中执行
QuartzManager qm = new QuartzManager();
qm.addJob(votes.getName(), "group"+votes.getName(), "trigger"+votes.getName(), "triggerGroup"+votes.getName(),
VoteJob.class,CronDateUtils.getCron(sdf.parse(votes.getEnd_time())),sdf.parse(votes.getOpen_time()), sdf.parse(votes.getEnd_time()),sdf.parse(votes.getOpen_time_join()),sdf.parse(votes.getEnd_time_join()),votes.getId());
}else {
logger.info("无效活动名称为:"+votes.getName());
}
}
//未超期的活动注入到qz中动态加载
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
在springmvc.xml中注入监听
<context:component-scan base-package="cn.com.sinosoft.controller"></context:component-scan>
<!-- 初始化完成之后执行监听 bean中为监听器路径 -->
<bean class="cn.com.sinosoft.lisener.IniterListener"/>
拓展
### 类似java定时任务,固定时间间隔执行定时任务,使用simpleScheduler调度器来执行
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;
import org.quartz.JobListener;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.matchers.EverythingMatcher;
import org.quartz.impl.matchers.KeyMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import com.sun.net.ssl.KeyManager;
import cn.com.sinosoft.lisener.MyJobListener;
public class QuartzManagerSimple {
private static SchedulerFactory schedulerFactory = new StdSchedulerFactory();
/**
* @Description: 添加一个定时任务
*
* @param jobName 任务名
* @param jobGroupName 任务组名
* @param triggerName 触发器名
* @param triggerGroupName 触发器组名
* @param jobClass 任务
* @param cron 时间设置,参考quartz说明文档
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public void addJob(String jobName, String jobGroupName,
String triggerName, String triggerGroupName, Class jobClass, String cron) {
try {
//调度器,从工厂中获取调度实例,默认new stschedulerFactory()
Scheduler sched = StdSchedulerFactory.getDefaultScheduler();
//sched.setJobFactory(myJobFactory);
// 任务名,任务组,任务执行类
JobDetail jobDetail= JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).usingJobData("message","测试jobdateMap").build();
//logger.info("名称:"+ jobDetail.getKey().getName());
//logger.info("组名称:"+ jobDetail.getKey().getGroup());
//logger.info("任务类:"+ jobDetail.getKey().getClass());
// 触发器
TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
// 触发器名,触发器组
triggerBuilder.withIdentity(triggerName, triggerGroupName).usingJobData("triggerMessage","trigger中传递的参数");
triggerBuilder.startNow();//马上启动
// 触发器时间设定
//triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
triggerBuilder.withSchedule(SimpleScheduleBuilder.simpleSchedule().repeatSecondlyForever(5).withRepeatCount(3));//5s重复执行,执行三次
// 创建Trigger对象
//CronTrigger trigger = (CronTrigger) triggerBuilder.build();
Trigger trigger = triggerBuilder.build();
// 调度容器设置JobDetail和Trigger
sched.scheduleJob(jobDetail, trigger);
//每次新建任务之后设置监听属性
//全局监听
//sched.getListenerManager().addJobListener(new MyJobListener(),EverythingMatcher.allJobs());
//局部监听
//sched.getListenerManager().addJobListener(new MyJobListener(),KeyMatcher.keyEquals(JobKey.jobKey(jobName, jobGroupName)));
// 启动
if (!sched.isShutdown()) {
sched.start();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* @Description: 修改一个任务的触发时间
*
* @param jobName
* @param jobGroupName
* @param triggerName 触发器名
* @param triggerGroupName 触发器组名
* @param cron 时间设置,参考quartz说明文档
*/
public void modifyJobTime(String jobName,
String jobGroupName, String triggerName, String triggerGroupName, String cron) {
try {
Scheduler sched = schedulerFactory.getScheduler();
//sched.setJobFactory(myJobFactory);
TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerKey);
if (trigger == null) {
return;
}
String oldTime = trigger.getCronExpression();
if (!oldTime.equalsIgnoreCase(cron)) {
/** 方式一 :调用 rescheduleJob 开始 */
// 触发器
TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
// 触发器名,触发器组
triggerBuilder.withIdentity(triggerName, triggerGroupName);
triggerBuilder.startNow();
// 触发器时间设定
triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
// 创建Trigger对象
trigger = (CronTrigger) triggerBuilder.build();
// 方式一 :修改一个任务的触发时间
sched.rescheduleJob(triggerKey, trigger);
/** 方式一 :调用 rescheduleJob 结束 */
/** 方式二:先删除,然后在创建一个新的Job */
//JobDetail jobDetail = sched.getJobDetail(JobKey.jobKey(jobName, jobGroupName));
//Class<? extends Job> jobClass = jobDetail.getJobClass();
//removeJob(jobName, jobGroupName, triggerName, triggerGroupName);
//addJob(jobName, jobGroupName, triggerName, triggerGroupName, jobClass, cron);
/** 方式二 :先删除,然后在创建一个新的Job */
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* @Description: 移除一个任务
*
* @param jobName
* @param jobGroupName
* @param triggerName
* @param triggerGroupName
*/
public void removeJob(String jobName, String jobGroupName,
String triggerName, String triggerGroupName) {
try {
Scheduler sched = schedulerFactory.getScheduler();
TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
sched.pauseTrigger(triggerKey);// 停止触发器
sched.unscheduleJob(triggerKey);// 移除触发器
sched.deleteJob(JobKey.jobKey(jobName, jobGroupName));// 删除任务
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* @Description:启动所有定时任务
*/
public void startJobs() {
try {
Scheduler sched = schedulerFactory.getScheduler();
sched.start();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* @Description:关闭所有定时任务
*/
public void shutdownJobs() {
try {
Scheduler sched = schedulerFactory.getScheduler();
if (!sched.isShutdown()) {
sched.shutdown();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}