Quartz实现动态定时任务案例

1.需求场景

实现动态定时任务。通过修改cron表达式,实时更新任务执行时间。

2.环境

quartz-2.1.7 Spring 3.2 Mybatis3.2

3.解决方法

(1)配置quartz文件

# 配置任务信息
#============================================================================
org.quartz.scheduler.instanceName: quartzScheduler
org.quartz.scheduler.instanceId = AUTO
org.quartz.scheduler.rmi.export: false
org.quartz.scheduler.rmi.proxy: false
org.quartz.scheduler.wrapJobExecutionInUserTransaction: false
#============================================================================
#配置线程池
#============================================================================
org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount: 2
org.quartz.threadPool.threadPriority: 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true
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.StdJDBCDelegate
org.quartz.jobStore.useProperties:true

#============================================================================
#非集群模式
#============================================================================
org.quartz.jobStore.isClustered = false  
#配置表的前缀
org.quartz.jobStore.tablePrefix:QRTZ_

#============================================================================
# 配置数据源
#============================================================================
org.quartz.dataSource.qzDS.driver:com.mysql.jdbc.Driver
org.quartz.dataSource.qzDS.URL:jdbc:mysql://127.0.0.1:3306/task
org.quartz.dataSource.qzDS.user:root
org.quartz.dataSource.qzDS.password:123456
#(由于quartz默认是使用c3p0连接池,本例没有使用,故自定义dbcp连接池实现)
org.quartz.dataSource.qzDS.connectionProvider.class:com.task.util.DBCPConnectionProvider

(2)使用dbcp提供连接池

package com.task.util;

import java.sql.Connection;
import java.sql.SQLException;

import org.apache.commons.dbcp.BasicDataSource;
import org.quartz.SchedulerException;
import org.quartz.utils.ConnectionProvider;

public class DBCPConnectionProvider implements ConnectionProvider {
	private BasicDataSource datasource;
	// JDBC驱动
	public String driver;
	// JDBC连接串
	public String URL;
	// 数据库用户名
	public String user;
	// 数据库用户密码
	public String password;

	public void initialize() throws SQLException,
			SchedulerException {
		if (URL == null) {
			throw new SQLException(
					"DBPool could not be created: DB URL cannot be null");
		}

		if (driver == null) {
			throw new SQLException("DBPool '" + URL
					+ "' could not be created: "
					+ "DB driver class name cannot be null!");
		}
		 
		datasource = new BasicDataSource();
		datasource.setDriverClassName(driver);
		datasource.setUrl(URL);
		datasource.setUsername(user);
		datasource.setPassword(password);
		datasource.setMaxActive(50);
		datasource.setMinIdle(1);
		datasource.setMaxWait(5000);
		datasource.setValidationQuery("SELECT 1");
		datasource.setTestOnBorrow(false);
		datasource.setTestOnReturn(false);
		datasource.setTimeBetweenEvictionRunsMillis(1800000);
	}

	@Override
	public Connection getConnection() throws SQLException {
		return datasource.getConnection();
	}

	public void shutdown() throws SQLException {
		datasource.close();
	}

	public BasicDataSource getDatasource() {
		return datasource;
	}

	public void setDatasource(BasicDataSource datasource) {
		this.datasource = datasource;
	}

	public String getDriver() {
		return driver;
	}

	public void setDriver(String driver) {
		this.driver = driver;
	}

	public String getURL() {
		return URL;
	}

	public void setURL(String uRL) {
		URL = uRL;
	}

	public String getUser() {
		return user;
	}

	public void setUser(String user) {
		this.user = user;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}
}

(3)Quartz与Spring集成Job自动注入Spring容器托管对象

package com.task.job;

import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.scheduling.quartz.AdaptableJobFactory;

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;
	}
}

(4)spring.xml配置

 <!-- 定时任务配置 -->
     <bean id="jobFactory" class="com.task.job.JobFactory"></bean>  
 <bean name="quartzScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" >
        <property name="dataSource" ref ="dataSource" />       
        <property name="applicationContextSchedulerContextKey" value="applicationContextKey"/>
        <property name="configLocation" value="classpath:quartz.properties"/>
        <property name="jobFactory" ref="jobFactory"></property>			
    </bean>

(5)定义job

@Component
public class AutoJob  implements Job {
	
	@Autowired
	private ToolService toolService;
	@Override
	public void execute(JobExecutionContext ctx) throws JobExecutionException {
		//获得参数对象
		JobDataMap jmap = ctx.getJobDetail().getJobDataMap();
		//获取配置id
		String id =  jmap.getString("jobName");
		//查询配置信息 并执行 查询。
		toolService.runTask(Integer.parseInt(id));
	}

(6)任务增删改查操作

package com.task.serviceImpl.task;

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.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.task.service.task.QuartzService;

@Service("quartzService")
public class QuartzServiceImpl implements QuartzService {

	@Autowired
	private Scheduler quartzScheduler;

	@Override
	public void addJob(String jobName, String jobGroupName, String triggerName,
			String triggerGroupName, Class cls, String cron) {
		try {
			// 获取调度器
			Scheduler sched = quartzScheduler;
			// 创建一项作业
			JobDetail job = JobBuilder.newJob(cls)
					.usingJobData("jobName", jobName)
					.withIdentity(jobName, jobGroupName).build();
			// 创建一个触发器
			CronTrigger trigger = TriggerBuilder.newTrigger()
					.withIdentity(triggerName, triggerGroupName)
					.withSchedule(CronScheduleBuilder.cronSchedule(cron))
					.build();
			// 告诉调度器使用该触发器来安排作业
			sched.scheduleJob(job, trigger);
			// 启动
			if (!sched.isShutdown()) {
				sched.start();
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 修改定时器任务信息
	 */
	@Override
	public boolean modifyJobTime(String oldjobName, String oldjobGroup,
			String oldtriggerName, String oldtriggerGroup, String jobName,
			String jobGroup, String triggerName, String triggerGroup,
			String cron) {
		try {
			Scheduler sched = quartzScheduler;
			CronTrigger trigger = (CronTrigger) sched.getTrigger(TriggerKey
					.triggerKey(oldtriggerName, oldtriggerGroup));
			if (trigger == null) {
				return false;
			}

			JobKey jobKey = JobKey.jobKey(oldjobName, oldjobGroup);
			TriggerKey triggerKey = TriggerKey.triggerKey(oldtriggerName,
					oldtriggerGroup);

			JobDetail job = sched.getJobDetail(jobKey);
			Class jobClass = job.getJobClass();
			// 停止触发器
			sched.pauseTrigger(triggerKey);
			// 移除触发器
			sched.unscheduleJob(triggerKey);
			// 删除任务
			sched.deleteJob(jobKey);

			addJob(jobName, jobGroup, triggerName, triggerGroup, jobClass, cron);

			return true;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}

	}

	@Override
	public void modifyJobTime(String triggerName, String triggerGroupName,
			String time) {
		try {
		TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
        CronTrigger trigger = (CronTrigger) quartzScheduler.getTrigger(triggerKey);  
        if (trigger == null) {  
            return;  
        }  
        String oldTime = trigger.getCronExpression();  
        if (!oldTime.equalsIgnoreCase(time)) { 
            /** 方式一 :调用 rescheduleJob 开始 */
            // 触发器  
            TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
            // 触发器名,触发器组  
            triggerBuilder.withIdentity(triggerName, triggerGroupName);
            triggerBuilder.startNow();
            // 触发器时间设定  
            triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(time));
            // 创建Trigger对象
            trigger = (CronTrigger) triggerBuilder.build();
            // 方式一 :修改一个任务的触发时间
            quartzScheduler.rescheduleJob(triggerKey, trigger);
   
        }  
		 } catch (Exception e) {  
	            throw new RuntimeException(e);  
	    }  
		
		
	}
	
	

	@Override
	public void removeJob(String jobName, String jobGroupName,
			String triggerName, String triggerGroupName) {
		try {
			Scheduler sched = quartzScheduler;
			// 停止触发器
			sched.pauseTrigger(TriggerKey.triggerKey(triggerName,
					triggerGroupName));
			// 移除触发器
			sched.unscheduleJob(TriggerKey.triggerKey(triggerName,
					triggerGroupName));
			// 删除任务
			sched.deleteJob(JobKey.jobKey(jobName, jobGroupName));
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	public void startSchedule() {
		try {
			Scheduler sched = quartzScheduler;
			sched.start();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	public void shutdownSchedule() {
		try {
			Scheduler sched = quartzScheduler;
			if (!sched.isShutdown()) {
				sched.shutdown();
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	public void pauseJob(String jobName, String jobGroupName) {
		try {
			quartzScheduler.pauseJob(JobKey.jobKey(jobName, jobGroupName));
		} catch (SchedulerException e) {
			e.printStackTrace();
		}

	}

	@Override
	public void resumeJob(String jobName, String jobGroupName) {
		try {
			quartzScheduler.resumeJob(JobKey.jobKey(jobName, jobGroupName));
		} catch (SchedulerException e) {
			e.printStackTrace();
		}
	}



public interface QuartzService {
	 
	public void addJob(String jobName, String jobGroupName, String triggerName,
			String triggerGroupName, Class cls, String cron);
	 
	public boolean modifyJobTime(String oldjobName, String oldjobGroup,
			String oldtriggerName, String oldtriggerGroup, String jobName,
			String jobGroup, String triggerName, String triggerGroup,
			String cron);

	public void modifyJobTime(String triggerName, String triggerGroupName,
			String cron);
 
	public void pauseJob(String jobName, String jobGroupName);
	 
	public void resumeJob(String jobName, String jobGroupName);

	 
	public void removeJob(String jobName, String jobGroupName,
			String triggerName, String triggerGroupName);
	 
	public void startSchedule();
	 
	public void shutdownSchedule();

}



@Controller
public class QuartzAction {

	@Autowired
	private Scheduler quartzScheduler;

	@Autowired
	private QuartzService quartzService;

	/**
	 * 定时列表页
	 * 
	 * @return
	 * @throws SchedulerException
	 */
	@RequestMapping(value = "/listJob")
	public String listJob(HttpServletRequest request,
			HttpServletResponse response) throws SchedulerException {
		List<JobEntity> jobInfos = this.getSchedulerJobInfo();
		request.setAttribute("jobInfos", jobInfos);
		return "listjob";
	}

	/**
	 * 跳转到新增
	 * 
	 * @return
	 * @throws SchedulerException
	 * @throws ClassNotFoundException
	 */
	@RequestMapping(value = "/toAdd")
	public String toAdd(HttpServletRequest request, HttpServletResponse response)
			throws SchedulerException {
		return "addjob";
	}

	/**
	 * 新增job
	 * 
	 * @return
	 * @throws SchedulerException
	 * @throws ClassNotFoundException
	 */
	@RequestMapping(value = "/add", method = RequestMethod.POST)
	public String add(HttpServletRequest request, HttpServletResponse response)
			throws SchedulerException, ClassNotFoundException {
		String jobName = request.getParameter("jobName");
		String jobGroupName = request.getParameter("jobGroupName");
		String triggerName = request.getParameter("triggerName");
		String triggerGroupName = request.getParameter("triggerGroupName");
		String clazz = request.getParameter("clazz");
		Class<?> cls = Class.forName(clazz);
		String cron = request.getParameter("cron");
		quartzService.addJob(jobName, jobGroupName, triggerName,
				triggerGroupName, cls, cron);
		request.setAttribute("message", "添加任务成功!");
		request.setAttribute("opName", "添加任务!");
		return "message";
	}

	/**
	 * 跳转到编辑
	 * 
	 * @return
	 * @throws SchedulerException
	 * @throws ClassNotFoundException
	 */
	@RequestMapping(value = "/toEdit")
	public String toEdit(HttpServletRequest request,
			HttpServletResponse response) throws SchedulerException {

		String jobName = request.getParameter("jobName");
		String jobGroup = request.getParameter("jobGroup");

		JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
		JobDetail jd = quartzScheduler.getJobDetail(jobKey);
		@SuppressWarnings("unchecked")
		List<CronTrigger> triggers = (List<CronTrigger>) quartzScheduler
				.getTriggersOfJob(jobKey);
		CronTrigger trigger = triggers.get(0);
		TriggerKey triggerKey = trigger.getKey();
		String cron = trigger.getCronExpression();
		Map<String, String> pd = new HashMap<String, String>();
		pd.put("jobName", jobKey.getName());
		pd.put("jobGroup", jobKey.getGroup());
		pd.put("triggerName", triggerKey.getName());
		pd.put("triggerGroupName", triggerKey.getGroup());
		pd.put("cron", cron);
		pd.put("clazz", jd.getJobClass().getCanonicalName());

		request.setAttribute("pd", pd);
		request.setAttribute("msg", "edit");

		return "editjob";
	}

	
	 
	 public void modifyJobTime(String triggerName, String triggerGroupName, String cron) {  
	        try {  
	            TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
	            CronTrigger trigger = (CronTrigger) quartzScheduler.getTrigger(triggerKey);  
	            if (trigger == null) {  
	                return;  
	            }  
	            String oldTime = trigger.getCronExpression();  
	            if (!oldTime.equalsIgnoreCase(cron)) { 
	                TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
	                triggerBuilder.withIdentity(triggerName, triggerGroupName);
	                triggerBuilder.startNow();
	                triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
	                trigger = (CronTrigger) triggerBuilder.build();
	                quartzScheduler.rescheduleJob(triggerKey, trigger);
	       
	            }  
	        } catch (Exception e) {  
	            throw new RuntimeException(e);  
	        }  
	    }  

	
	/**
	 * 编辑job
	 * 
	 * @return
	 * @throws SchedulerException
	 * @throws ClassNotFoundException
	 */
	@RequestMapping(value = "/edit", method = RequestMethod.POST)
	public String edit(HttpServletRequest request, HttpServletResponse response)
			throws SchedulerException, ClassNotFoundException {
		String jobName = request.getParameter("jobName");
		String jobGroupName = request.getParameter("jobGroupName");
		String triggerName = request.getParameter("triggerName");
		String triggerGroupName = request.getParameter("triggerGroupName");
		String clazz = request.getParameter("clazz");
		@SuppressWarnings("unused")
		Class<?> cls = Class.forName(clazz);
		String cron = request.getParameter("cron");

		String oldjobName = request.getParameter("oldjobName");
		String oldjobGroup = request.getParameter("oldjobGroup");
		String oldtriggerName = request.getParameter("oldtriggerName");
		String oldtriggerGroup = request.getParameter("oldtriggerGroup");

		boolean result = quartzService.modifyJobTime(oldjobName, oldjobGroup,
				oldtriggerName, oldtriggerGroup, jobName, jobGroupName,
				triggerName, triggerGroupName, cron);
		if (result) {
			request.setAttribute("message", "修改任务成功!");
		} else {
			request.setAttribute("message", "修改任务失败!");
		}
		request.setAttribute("opName", "更新任务!");
		return "quartz/message";
	}

	@RequestMapping(value = "/pauseJob", method = RequestMethod.POST)
	@ResponseBody
	public String pauseJob(@RequestParam("jobName") String jobName,
			@RequestParam("jobGroupName") String jobGroupName) {
		JSONObject json = new JSONObject();

		if (StringUtils.isEmpty(jobName) || StringUtils.isEmpty(jobGroupName)) {
			json.put("status", "wrong");
		} else {
			quartzService.pauseJob(jobName, jobGroupName);
			json.put("status", "success");
		}

		return json.toString();
	}

	@RequestMapping(value = "/resumeJob", method = RequestMethod.POST)
	@ResponseBody
	public String resumeJob(@RequestParam("jobName") String jobName,
			@RequestParam("jobGroupName") String jobGroupName) {
		JSONObject json = new JSONObject();

		if (StringUtils.isEmpty(jobName) || StringUtils.isEmpty(jobGroupName)) {
			json.put("status", "wrong");
		} else {
			quartzService.resumeJob(jobName, jobGroupName);
			json.put("status", "success");
		}

		return json.toString();
	}

	@RequestMapping(value = "/deleteJob", method = RequestMethod.POST)
	@ResponseBody
	public String deleteJob(@RequestParam("jobName") String jobName,
			@RequestParam("jobGroupName") String jobGroupName,
			@RequestParam("triggerName") String triggerName,
			@RequestParam("triggerGroupName") String triggerGroupName) {
		JSONObject json = new JSONObject();

		if (StringUtils.isEmpty(jobName) || StringUtils.isEmpty(jobGroupName)
				|| StringUtils.isEmpty(triggerName)
				|| StringUtils.isEmpty(triggerGroupName)) {
			json.put("status", "wrong");
		} else {
			quartzService.removeJob(jobName, jobGroupName, triggerName,
					triggerGroupName);
			json.put("status", "success");
		}

		return json.toString();
	}

	private List<JobEntity> getSchedulerJobInfo() throws SchedulerException {
		List<JobEntity> jobInfos = new ArrayList<JobEntity>();
		List<String> triggerGroupNames = quartzScheduler.getTriggerGroupNames();
		for (String triggerGroupName : triggerGroupNames) {
			Set<TriggerKey> triggerKeySet = quartzScheduler.getTriggerKeys(GroupMatcher.triggerGroupEquals(triggerGroupName));
			for (TriggerKey triggerKey : triggerKeySet) {
				Trigger t = quartzScheduler.getTrigger(triggerKey);
				if (t instanceof CronTrigger) {
					CronTrigger trigger = (CronTrigger) t;
					JobKey jobKey = trigger.getJobKey();
					JobDetail jd = quartzScheduler.getJobDetail(jobKey);
					
					JobEntity jobInfo = new JobEntity();
					jobInfo.setJobName(jobKey.getName());
					jobInfo.setJobGroup(jobKey.getGroup());
					jobInfo.setTriggerName(triggerKey.getName());
					jobInfo.setTriggerGroupName(triggerKey.getGroup());
					jobInfo.setCronExpr(trigger.getCronExpression());
					jobInfo.setNextFireTime(trigger.getNextFireTime());
					jobInfo.setPreviousFireTime(trigger.getPreviousFireTime());
					jobInfo.setStartTime(trigger.getStartTime());
					jobInfo.setEndTime(trigger.getEndTime());
					jobInfo.setJobClass(jd.getJobClass().getCanonicalName());
					// jobInfo.setDuration(Long.parseLong(jd.getDescription()));
					Trigger.TriggerState triggerState = quartzScheduler.getTriggerState(trigger.getKey());
					jobInfo.setJobStatus(triggerState.toString());// NONE无,
																	// NORMAL正常,
																	// PAUSED暂停,
																	// COMPLETE完成,
																	// ERROR错误,
																	// BLOCKED阻塞
					JobDataMap map = quartzScheduler.getJobDetail(jobKey).getJobDataMap();
					if (null != map && map.size() != 0) {
						//jobInfo.setCount(Integer.parseInt((String) map.get("count")));
						//jobInfo.setJobDataMap(map);
					} else {
						jobInfo.setJobDataMap(new JobDataMap());
					}
					jobInfos.add(jobInfo);
				}
			}
		}
		return jobInfos;
	}

}


}

参考链接:

https://blog.csdn.net/lkl_csdn/article/details/73613033 (quartz 原理到应用)

https://blog.csdn.net/u010377605/article/details/77801896/ (quartz动态定时任务)

https://blog.csdn.net/qq_38974131/article/details/77801615 (quartz 集成 spring+springmvc+jpa)

https://www.cnblogs.com/davidwang456/p/4205237.html (quartz 原理分析)

https://blog.csdn.net/zhouhua0104/article/details/46560555 (Quartz+Spring 实现任务监控)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值