本人小白,最近工作遇到要实现动态Job的小功能,于是自行百度学习整理了下quartz在spring中的整合,写的不对不好之处,可以直接指出。
首先准备一个普通的spring-mvc maven工程作为基础,我们在这上添加定时任务功能
开始
使用jar包
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>1.8.5</version>
</dependency>
配置文件中加配置
此处让job可以获取spring容器中的实例,还有bean生成方式也可以用注解,可自行选择
<bean id="jobFactory" class="cn.zzm.test.job.JobFactory"></bean>
<bean id="schedulerFactoryBeanForStatusCheck" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="jobFactory" ref="jobFactory"></property>
</bean>
<bean id="quartzManagerForStatusCheck" class="cn.zzm.test.job.QuartzManagerForStatusCheck"></bean>
相关class
public class JobFactory extends AdaptableJobFactory{
@Autowired
private AutowireCapableBeanFactory capableBeanFactory;
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
//调用父类的方法
Object jobInstance = super.createJobInstance(bundle);
//进行注入
capableBeanFactory.autowireBean(jobInstance);
return jobInstance;
}
}
下面是主要代码
public class QuartzManagerForStatusCheck
{
@Autowired
@Qualifier("schedulerFactoryBeanForStatusCheck")
private SchedulerFactoryBean schedulerFactoryBean;
private String JOB_GROUP_NAME = "STATUS_CHECK";
private String TRIGGER_GROUP_NAME = "STATUS_CHECK_Trigger";
/**
* @Description: 添加一个定时任务,使用默认的任务组名,触发器名,触发器组名
*
* @param jobName 任务名
* @param cls 任务
* @param time 时间设置,参考quartz说明文档
*
*/
public void addJob(String jobName, Class<?> cls, String time)
{
System.setProperty("org.terracotta.quartz.skipUpdateCheck","true");
try
{
Scheduler sched = schedulerFactoryBean.getScheduler();
JobDetail jobDetail = new JobDetail(jobName, JOB_GROUP_NAME, cls);// 任务名,任务组,任务执行类(见下面类)
// 触发器
CronTrigger trigger = new CronTrigger(jobName, TRIGGER_GROUP_NAME);// 触发器名,触发器组
trigger.setCronExpression(time);// 触发器时间设定
// 5分钟后重新启动
//trigger.setStartTime(new Date(new Date().getTime() + 5000 * 60));
sched.scheduleJob(jobDetail, trigger);
// 启动
if (!sched.isShutdown())
{
sched.start();
}
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
/**
* @Description: 添加一个定时任务
*
* @param jobName 任务名
* @param jobGroupName 任务组名
* @param triggerName 触发器名
* @param triggerGroupName 触发器组名
* @param jobClass 任务
* @param time 时间设置,参考quartz说明文档
*
*/
public void addJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName,
Class<?> jobClass, String time)
{
try
{
Scheduler sched = schedulerFactoryBean.getScheduler();
JobDetail jobDetail = new JobDetail(jobName, jobGroupName, jobClass);// 任务名,任务组,任务执行类
// 触发器
CronTrigger trigger = new CronTrigger(triggerName, triggerGroupName);// 触发器名,触发器组
trigger.setCronExpression(time);// 触发器时间设定
sched.scheduleJob(jobDetail, trigger);
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
/**
* @Description: 修改一个任务的触发时间(使用默认的任务组名,触发器名,触发器组名)
*
* @param jobName
* @param time
*
*/
public void modifyJobTime(String jobName, String time)
{
try
{
Scheduler sched = schedulerFactoryBean.getScheduler();
CronTrigger trigger = (CronTrigger)sched.getTrigger(jobName, TRIGGER_GROUP_NAME);
if (trigger == null)
{
return;
}
String oldTime = trigger.getCronExpression();
if (!oldTime.equalsIgnoreCase(time))
{
JobDetail jobDetail = sched.getJobDetail(jobName, JOB_GROUP_NAME);
Class<?> objJobClass = jobDetail.getJobClass();
removeJob(jobName);
addJob(jobName, objJobClass, time);
}
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
/**
* @Description: 修改一个任务的触发时间
*
* @param triggerName
* @param triggerGroupName
* @param time
*
*
*/
public void modifyJobTime(String triggerName, String triggerGroupName, String time)
{
try
{
Scheduler sched = schedulerFactoryBean.getScheduler();
CronTrigger trigger = (CronTrigger)sched.getTrigger(triggerName, triggerGroupName);
if (trigger == null)
{
return;
}
String oldTime = trigger.getCronExpression();
if (!oldTime.equalsIgnoreCase(time))
{
CronTrigger ct = (CronTrigger)trigger;
// 修改时间
ct.setCronExpression(time);
// 重启触发器
sched.resumeTrigger(triggerName, triggerGroupName);
}
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
/**
* @Description: 移除一个任务(使用默认的任务组名,触发器名,触发器组名)
*
* @param jobName
*
*
*/
public void removeJob(String jobName)
{
try
{
Scheduler sched = schedulerFactoryBean.getScheduler();
sched.pauseTrigger(jobName, TRIGGER_GROUP_NAME);// 停止触发器
sched.unscheduleJob(jobName, TRIGGER_GROUP_NAME);// 移除触发器
sched.deleteJob(jobName, JOB_GROUP_NAME);// 删除任务
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
/**
* @Description:启动所有定时任务
*
*
*
*/
public void startJobs()
{
try
{
Scheduler sched = schedulerFactoryBean.getScheduler();
sched.start();
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
/**
* @Description:关闭所有定时任务
*
*
*
*/
public void shutdownJobs()
{
try
{
Scheduler sched = schedulerFactoryBean.getScheduler();
if (!sched.isShutdown())
{
sched.shutdown();
}
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
public List<Map<String,Object>> queryAllJobs(){
List<Map<String,Object>> jobs = new ArrayList<Map<String,Object>>();
try{
Scheduler scheduler = schedulerFactoryBean.getScheduler();
for (String groupName : scheduler.getJobGroupNames()) {
for (String jobName : scheduler.getJobNames(groupName)) {
Map<String,Object> job = new HashMap<String,Object>();
Trigger[] triggers = scheduler.getTriggersOfJob(jobName,groupName);
Date nextFireTime = triggers[0].getNextFireTime();
System.out.println("[jobName] : " + jobName + " [groupName] : "
+ groupName + " - " + nextFireTime);
job.put("jobName", jobName);
job.put("groupName", groupName);
job.put("nextFireTime", nextFireTime);
jobs.add(job);
}
}
return jobs;
}catch(Exception e){
throw new RuntimeException(e);
}
}
}
自己写个类实现Job接口就可以作为定时任务传入上面类的add方法就可以执行。
如下Job可以注入spring bean (该Job是远程执行linux命名查看对应机器程序是否正常,不正常的发邮件,整合远程执行命令和发邮件,稍后再写。。。)
public class StatusCheckJob implements Job{
Logger logger = LoggerFactory.getLogger(StatusCheckJob.class);
@Autowired
private StatusCheckService statusCheckService;
@Autowired
private MailForStatusCheck mailForStatusCheck;
@Override
public void execute(JobExecutionContext context)
throws JobExecutionException {
logger.info("开始运行服务状态检查Job。。。");
List<ShipIp> ships = statusCheckService.queryAllShipIp();
logger.debug("查询船只ip",ships);
List<String> all = new ArrayList<String>();
for(ShipIp ship : ships){
try{
List<String> r = statusCheckService.checkStatus(ship);
all.addAll(r);
}catch(Exception e){
logger.error("",e);
}
}
if(all.size()>0){//有异常
logger.info("存在异常开始发送邮件。。。。。。。。。。。。。。。。。。。。");
List<String> receivers= statusCheckService.queryAllReceiver();
mailForStatusCheck.sendMail(all.toString(),"船端进程异常邮件",receivers);
logger.info("邮件发送完毕。。。。。。。。。。。。。。。。。。。。。。。。。");
}
logger.info("服务状态检查Job结束。。。");
}
}
自己写个接口,测试下
@ResponseBody
@RequestMapping("addJobs")
public String addJobs(String jobName,String time){
try{
String[] t = time.split(":");
//String jobTime = "0 "+t[1]+" "+t[0]+" * * ?";
quartzManagerForStatusCheck.addJob(jobName, StatusCheckJob.class, "0 0/3 * * * ?");//从0分0秒 3分钟执行一次 这边直接注入工具类了
}catch(Exception e){
logger.error("job:"+jobName+"添加失败",e);
return "-1";
}
return "1";
}
搞定,本人撸代码没多久,写的很丑,记下学到的东西,相互学习。