首页 > 其他分享 >Quartz实战:基于Quartz实现定时任务的动态调度,实现定时任务的增删改查

Quartz实战:基于Quartz实现定时任务的动态调度,实现定时任务的增删改查

时间:2023-07-30 10:05:37浏览次数:46  
标签:Exception Quartz String 改查 任务 job new 定时 throws



文章目录

  • 一、Quartz基础
  • 二、使用Quartz实现定时任务的动态调度
  • 1、使用Quartz-jobStore 持久化
  • 2、前端页面实现效果图
  • 3、自定义job表
  • 4、增删改查Controller
  • 5、Quartz工具类
  • 6、测试任务类
  • 7、springboot启动初始化定时任务
  • 8、自定义JobFactory,使Task注册为Bean
  • 9、省略的内容
  • 10、总结


一、Quartz基础

Quartz使用文档,使用Quartz实现动态任务,Spring集成Quartz,Quartz集群部署,Quartz源码分析

二、使用Quartz实现定时任务的动态调度

1、使用Quartz-jobStore 持久化

Quartz使用文档,使用Quartz实现动态任务,Spring集成Quartz,Quartz集群部署,Quartz源码分析

2、前端页面实现效果图

Quartz实战:基于Quartz实现定时任务的动态调度,实现定时任务的增删改查_Data

3、自定义job表

CREATE database quartz;

CREATE TABLE `sys_job` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `job_name` varchar(512) NOT NULL COMMENT '任务名称',
  `job_group` varchar(512) NOT NULL COMMENT '任务组名',
  `job_cron` varchar(512) NOT NULL COMMENT '时间表达式',
  `job_class_path` varchar(1024) NOT NULL COMMENT '类路径,全类型',
  `job_data_map` varchar(1024) DEFAULT NULL COMMENT '传递map参数',
  `job_status` int(2) NOT NULL COMMENT '状态:1启用 0停用',
  `job_describe` varchar(1024) DEFAULT NULL COMMENT '任务功能描述',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=utf8;

-- 插入3条数据,3个任务
-- 注意第三条,是一个发送邮件的任务,需要改成你自己的QQ和授权码。不知道什么是授权码的自己百度。
INSERT INTO `sys_job` (`id`, `job_name`, `job_group`, `job_cron`, `job_class_path`, `job_data_map`, `job_status`, `job_describe`) VALUES (22, 'test', 'test', '*/20 * * * * ?', 'com.demo.task.TestTask1', NULL, 1, 'a job a');
INSERT INTO `sys_job` (`id`, `job_name`, `job_group`, `job_cron`, `job_class_path`, `job_data_map`, `job_status`, `job_describe`) VALUES (23, 'test2', 'test', '*/30 * * * * ?', 'com.demo.task.TestTask2', NULL, 1, 'another job');
INSERT INTO `sys_job` (`id`, `job_name`, `job_group`, `job_cron`, `job_class_path`, `job_data_map`, `job_status`, `job_describe`) VALUES (24, 'test3', 'mail', '*/10 * * * * ?', 'com.demo.task.TestTask3', '{\"data\":{\"loginAccount\":\"改成你的QQ邮箱\",\"loginAuthCode\":\"改成你的邮箱授权码\",\"sender\":\"改成你的QQ邮箱\",\"emailContent\":\"    你好。\",\"emailContentType\":\"text/html;charset=utf-8\",\"emailSubject\":\"十万火急\",\"recipients\":\"改成你要的收件人邮箱,可以有多个,英文逗号隔开\"}}', 1, 'fdsafdfds');

-- 清空表的脚本
DELETE FROM QRTZ_BLOB_TRIGGERS;
DELETE FROM QRTZ_CALENDARS;
DELETE FROM QRTZ_CRON_TRIGGERS;
DELETE FROM QRTZ_FIRED_TRIGGERS;
DELETE FROM QRTZ_LOCKS;
DELETE FROM QRTZ_PAUSED_TRIGGER_GRPS;
DELETE FROM QRTZ_SCHEDULER_STATE;
DELETE FROM QRTZ_SIMPLE_TRIGGERS;
DELETE FROM QRTZ_SIMPROP_TRIGGERS;
DELETE FROM QRTZ_TRIGGERS;
DELETE FROM QRTZ_JOB_DETAILS;
COMMIT;

4、增删改查Controller

@Controller()
@RequestMapping("/job")
public class JobController {
	private final Logger logger = LoggerFactory.getLogger(this.getClass());

	@Autowired
	private ISysJobService sysJobService;

	/**
	 * 打开列表页
	 * @return
	 */
	@RequestMapping("/jobList")
	public String jobList() {
		return "jobListPage";
	}

	/**
	 * 打开详情界面
	 * @param id
	 * @param model
	 * @return
	 */
	@RequestMapping("/toDetail")
	public String toDetail(Integer id, Model model) {
		SysJob job = sysJobService.selectByPrimaryKey(id);
		model.addAttribute("job",job);
		return "jobDetail";
	}

	/**
	 * 打开修改界面
	 * @param id
	 * @param model
	 * @return
	 */
	@RequestMapping("/toUpdate")
	public String toUpdate(Integer id, Model model) {
		SysJob job = sysJobService.selectByPrimaryKey(id);
		model.addAttribute("job",job);
		return "jobUpdate";
	}

	/**
	 * 打开新增界面
	 * @return
	 */
	@RequestMapping("/toJob")
	public String toJob (){
		return "jobAdd";
	}

	/**
	 * 查询任务列表(带分页)
	 * 
	 * @return
	 */
	@RequestMapping(value = "/queryList", method = RequestMethod.GET)
	@ResponseBody
	public LayuiData queryJobList(HttpServletRequest request, HttpServletResponse response) {
		String idStr = request.getParameter("id");
		String jobName = request.getParameter("jobName");
		String jobGroup = request.getParameter("jobGroup");
		String jobCron = request.getParameter("jobCron");
		String jobClassPath = request.getParameter("jobClassPath");
		String jobDescribe = request.getParameter("jobDescribe");

		HashMap<String, String> map = new HashMap<String, String>();
		if (StringUtils.isNotBlank(idStr)) {
			map.put("id", idStr);
		}
		if (StringUtils.isNotBlank(jobName)) {
			map.put("jobName", jobName);
		}
		if (StringUtils.isNotBlank(jobGroup)) {
			map.put("jobGroup", jobGroup);
		}
		if (StringUtils.isNotBlank(jobCron)) {
			map.put("jobCron", jobCron);
		}
		if (StringUtils.isNotBlank(jobClassPath)) {
			map.put("jobClassPath", jobClassPath);
		}
		if (StringUtils.isNotBlank(jobDescribe)) {
			map.put("jobDescribe", jobDescribe);
		}

		int page = Integer.parseInt(request.getParameter("page"));
		int limit = Integer.parseInt(request.getParameter("limit"));
		if(page>=1){
			page = (page-1)*limit;
		}
		LayuiData layuiData = new LayuiData();

		try {
			List<SysJob> jobList = sysJobService.querySysJobList(map);
			int count = sysJobService.getJobCount();
			layuiData.setCode(0);
			layuiData.setCount(count);
			layuiData.setMsg("数据请求成功");
			layuiData.setData(jobList);
			return layuiData;
		} catch (Exception e) {
			throw new BizException("查询任务列表异常:" + e.getMessage());
		}
	}

	/**
	 * 添加定时任务
	 *
	 * @throws Exception
	 */
	@PostMapping(value = "/addJob")
	@ResponseBody
	@Transactional
	public int addjob(HttpServletRequest request, HttpServletResponse response) throws Exception {
        logger.info("添加任务开始... ...");
		int num =0;
		String jobName = request.getParameter("jobName");
		String jobClassPath= request.getParameter("jobClassPath");
		String jobGroup= request.getParameter("jobGroup");
		String jobCron= request.getParameter("jobCron");
		String jobDescribe= request.getParameter("jobDescribe");
		String jobDataMap= request.getParameter("jobDataMap");
		
		if (StringUtils.isBlank(jobName)) {
			throw new BizException("任务名称不能为空");
		}
		if (StringUtils.isBlank(jobGroup)) {
			throw new BizException("任务组别不能为空");
		}
		if (StringUtils.isBlank(jobCron)) {
			throw new BizException("Cron表达式不能为空");
		}
		if (StringUtils.isBlank(jobClassPath)) {
			throw new BizException("任务类路径不能为空");
		}
		
		// 参数不为空时校验格式
		if(StringUtils.isNotBlank(jobDataMap)){
			try {
				JSONObject.parseObject(jobDataMap);
			} catch (Exception e) {
				throw new BizException("参数JSON格式错误");
			}
		}
		
		// 已存在校验
		SysJob queryBean = new SysJob();
		queryBean.setJobName(jobName);
		SysJob result = sysJobService.selectByBean(queryBean);
		if (null != result) {
			throw new BizException("任务名为" + jobName + "的任务已存在!");
		}

		SysJob bean = new SysJob();
		bean.setJobName(jobName);
		bean.setJobClassPath(jobClassPath);
		bean.setJobGroup(jobGroup);
		bean.setJobCron(jobCron);
		bean.setJobDescribe(jobDescribe);
		bean.setJobDataMap(jobDataMap);
		bean.setJobStatus(Constant.JOB_STATE.YES);
		try {
			num = sysJobService.insertSelective(bean);
		} catch (Exception e) {
			throw new BizException("新增定时任务失败");
		}
		
		SchedulerUtil.addJob(jobClassPath,jobName, jobGroup, jobCron,jobDataMap);
		return num;
	}
	
	/**
	 * 变更定时任务执行状态
	 * @return
	 * @throws Exception
	 */
	@GetMapping(value = "/changeState")
	@ResponseBody
	public int changeState(@RequestParam(value = "id") String idStr)throws Exception{
        logger.info("变更定时任务状态开始... ...");
		if (StringUtils.isBlank(idStr)) {
			throw new BizException("任务ID不能为空");
		}
		int id = Integer.parseInt(idStr);

		// 校验
		SysJob queryBean = new SysJob();
		queryBean.setId(id);
		SysJob result = sysJobService.selectByBean(queryBean);
		if (null == result) {
			throw new BizException("任务ID为" + id + "的任务不存在!");
		}
		
		SysJob updateBean = new SysJob();
		updateBean.setId(id);
		//如果是现在是启用,则停用
		if(Constant.JOB_STATE.YES == result.getJobStatus()){
			updateBean.setJobStatus(Constant.JOB_STATE.NO);
			//SchedulerUtil.jobPause(result.getJobName(), result.getJobGroup());
		  Boolean b=SchedulerUtil.isResume(result.getJobName(), result.getJobGroup());
		  if (b) {
			  SchedulerUtil.jobdelete(result.getJobName(), result.getJobGroup());
		  }
		}
		
		//如果现在是停用,则启用
		if(Constant.JOB_STATE.NO == result.getJobStatus()){
			updateBean.setJobStatus(Constant.JOB_STATE.YES);
			//SchedulerUtil.jobresume(result.getJobName(), result.getJobGroup());
			 Boolean b=SchedulerUtil.isResume(result.getJobName(), result.getJobGroup());
			 //存在则激活,不存在则添加
			  if (b) {
				  SchedulerUtil.jobresume(result.getJobName(), result.getJobGroup());
			  }else {
				  SchedulerUtil.addJob(result.getJobClassPath(),result.getJobName(), result.getJobGroup(), result.getJobCron(),result.getJobDataMap());
			}
		}
		
		try {
			sysJobService.updateByPrimaryKeySelective(updateBean);
		} catch (Exception e) {
			throw new BizException("更新数据库的定时任务信息异常!");
		}
		// 1表示成功
		return 1;
		
	}

	/**
	 * 删除一个任务
	 *
	 * @throws Exception
	 */
	@PostMapping(value = "/deleteJob")
	@ResponseBody
	public int deletejob(@RequestParam(value = "id") String idStr) throws Exception {
        logger.info("删除定时任务状态开始... ...");
		int num =0;
		if (StringUtils.isBlank(idStr)) {
			throw new BizException("任务ID不能为空");
		}
		int id = Integer.parseInt(idStr);
		
		// 存在性校验
		SysJob queryBean = new SysJob();
		queryBean.setId(id);
		SysJob result = sysJobService.selectByBean(queryBean);
		if (null == result) {
			throw new BizException("任务ID为" + idStr + "的任务不存在!");
		}
		
		try {
			num = sysJobService.deleteByPrimaryKey(id);
		} catch (Exception e) {
			throw new BizException("从数据库删除定时任务时发生异常!");
		}
		
		SchedulerUtil.jobdelete(result.getJobName(), result.getJobGroup());
		return num;
	}

	/**
	 * 修改定时表达式
	 */
	@RequestMapping("/reSchedulejob")
	@ResponseBody
	public int updateByBean(HttpServletRequest request, HttpServletResponse response) throws Exception {
        logger.info("修改定时任务信息开始... ...");
		int num =0;
		String jobCron = request.getParameter("jobCron");
		String jobDescribe = request.getParameter("jobDescribe");
		String idStr = request.getParameter("id");
		int id = Integer.parseInt(idStr);
		// 数据非空校验
		if (!StringUtils.isNotBlank(idStr)) {
			throw new BizException("任务ID不能为空");
		}
		SysJob result = sysJobService.selectByPrimaryKey(id);
		// 数据不存在
		if (null == result) {
			throw new BizException("根据任务ID[" + id + "]未查到相应的任务记录");
		}
		SysJob bean = new SysJob();
		bean.setId(id);
		bean.setJobCron(jobCron);
		bean.setJobDescribe(jobDescribe);
		try {
			num = sysJobService.updateByPrimaryKeySelective(bean);
		} catch (Exception e) {
			throw new BizException("变更任务表达式异常:" + e.getMessage());
		}
		//只有任务状态为启用,才开始运行
		// 如果先启动再手工插入数据,此处会报空指针异常
		if( result.getJobStatus() ==Constant.JOB_STATE.YES ){
			SchedulerUtil.jobReschedule(result.getJobName(), result.getJobGroup(),jobCron);
		}
		
		// 返回成功
		return num;
	}

	/**
	 * 展示任务调度管理页
	 * 
	 * @param request
	 * @param rep
	 * @return
	 */
	@RequestMapping(value = "/jobPage", method = RequestMethod.GET)
	public String getJobPage(HttpServletRequest request, HttpServletResponse rep) {
		return "job/job_info";
	}
}

5、Quartz工具类

/**
 * Quartz工具类
 */
public class SchedulerUtil {
	private static Logger logger = LoggerFactory.getLogger(SchedulerUtil.class);

	/**
	 * 新增定时任务
	 * @param jobClassName 类路径
	 * @param jobName 任务名称
	 * @param jobGroupName 组别
	 * @param cronExpression Cron表达式
	 * @param jobDataMap 需要传递的参数
	 * @throws Exception
	 */
	public static void addJob(String jobClassName,String jobName, String jobGroupName, String cronExpression,String jobDataMap) throws Exception {
		// 通过SchedulerFactory获取一个调度器实例
		SchedulerFactory sf = new StdSchedulerFactory();
		Scheduler scheduler = sf.getScheduler();
		// 启动调度器
		scheduler.start();
		// 构建job信息
		JobDetail jobDetail = JobBuilder.newJob(getClass(jobClassName).getClass())
				.withIdentity(jobName, jobGroupName).build();
		// JobDataMap用于传递任务运行时的参数,比如定时发送邮件,可以用json形式存储收件人等等信息
		if (StringUtils.isNotEmpty(jobDataMap)) {
			JSONObject jb = JSONObject.parseObject(jobDataMap);
			Map<String, Object> dataMap =(Map<String, Object>) jb.get("data");
			for (Map.Entry<String, Object> m:dataMap.entrySet()) {
				jobDetail.getJobDataMap().put(m.getKey(),m.getValue());
			}
		}
		// 表达式调度构建器(即任务执行的时间)
		CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
		// 按新的cronExpression表达式构建一个新的trigger
		CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroupName)
				.withSchedule(scheduleBuilder).startNow().build();
		try {
			scheduler.scheduleJob(jobDetail, trigger);
		} catch (SchedulerException e) {
			logger.info("创建定时任务失败" + e);
			throw new Exception("创建定时任务失败");
		}
	}
	
	/**
	 * 停用一个定时任务
	 * @param jobName 任务名称
	 * @param jobGroupName 组别
	 * @throws Exception
	 */
	public static void jobPause(String jobName, String jobGroupName) throws Exception {
		// 通过SchedulerFactory获取一个调度器实例
		SchedulerFactory sf = new StdSchedulerFactory();
		Scheduler scheduler = sf.getScheduler();
		scheduler.pauseJob(JobKey.jobKey(jobName, jobGroupName));
	}
	
	/**
	 * 启用一个定时任务
	 * @param jobName 任务名称
	 * @param jobGroupName 组别
	 * @throws Exception
	 */
	public static void jobresume(String jobName, String jobGroupName) throws Exception {
		// 通过SchedulerFactory获取一个调度器实例
		SchedulerFactory sf = new StdSchedulerFactory();
		Scheduler scheduler = sf.getScheduler();
		scheduler.resumeJob(JobKey.jobKey(jobName, jobGroupName));
	}
	
	/**
	 * 删除一个定时任务
	 * @param jobName 任务名称
	 * @param jobGroupName 组别
	 * @throws Exception
	 */
	public static void jobdelete(String jobName, String jobGroupName) throws Exception {
		// 通过SchedulerFactory获取一个调度器实例
		SchedulerFactory sf = new StdSchedulerFactory();
		Scheduler scheduler = sf.getScheduler();
		scheduler.pauseTrigger(TriggerKey.triggerKey(jobName, jobGroupName));
		scheduler.unscheduleJob(TriggerKey.triggerKey(jobName, jobGroupName));
		scheduler.deleteJob(JobKey.jobKey(jobName, jobGroupName));
	}
	
	/**
	 * 更新定时任务表达式
	 * @param jobName 任务名称
	 * @param jobGroupName 组别
	 * @param cronExpression Cron表达式
	 * @throws Exception
	 */
	public static void jobReschedule(String jobName, String jobGroupName, String cronExpression) throws Exception {
		try {
			SchedulerFactory schedulerFactory = new StdSchedulerFactory();
			Scheduler scheduler = schedulerFactory.getScheduler();
			TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroupName);
			// 表达式调度构建器
			CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
			CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
			// 按新的cronExpression表达式重新构建trigger
			trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).startNow().build();
			// 按新的trigger重新设置job执行
			scheduler.rescheduleJob(triggerKey, trigger);
		} catch (SchedulerException e) {
			System.out.println("更新定时任务失败" + e);
			throw new Exception("更新定时任务失败");
		}
	}
	
	/**
	 * 检查Job是否存在
	 * @throws Exception
	 */
	public static Boolean isResume(String jobName, String jobGroupName) throws Exception {
		SchedulerFactory sf = new StdSchedulerFactory();
		Scheduler scheduler = sf.getScheduler();
		TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroupName);
		Boolean state = scheduler.checkExists(triggerKey);
	     
		return state;
	}

	/**
	 * 暂停所有任务
	 * @throws Exception
	 */
	public static void pauseAlljob() throws Exception {
		SchedulerFactory sf = new StdSchedulerFactory();
		Scheduler scheduler = sf.getScheduler();
		scheduler.pauseAll();
	}

	/**
	 * 唤醒所有任务
	 * @throws Exception
	 */
	public static void resumeAlljob() throws Exception {
		SchedulerFactory sf = new StdSchedulerFactory();
		Scheduler sched = sf.getScheduler();
		sched.resumeAll();
	}

	/**
	 * 获取Job实例
	 * @param classname
	 * @return
	 * @throws Exception
	 */
	public static BaseJob getClass(String classname) throws Exception {
		try {
			Class<?> c = Class.forName(classname);
			return (BaseJob) c.newInstance();
		} catch (Exception e) {
			throw new Exception("类["+classname+"]不存在!");
		}
		
	}

}

6、测试任务类

@DisallowConcurrentExecution
public class TestTask1 implements BaseJob {

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println(Thread.currentThread().getName() + " " +sdf.format(date) + " Task1: ----hello1----");
    }
}
public class TestTask2 implements BaseJob {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println(Thread.currentThread().getName() + " " +sdf.format(date) + " Task2: ----hello2----");
    }
}
public class TestTask3 implements BaseJob {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private ISysJobService sysJobService;

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        logger.info("开始执行任务3... ...");
        HashMap<String,String> map = new HashMap<String,String>();
        map.put("jobGroup", "mail");
        map.put("jobStatus", "1");
        List<SysJob> jobList= sysJobService.querySysJobList(map);

        if( null == jobList || jobList.size() ==0){
            logger.info("没有状态为可用的发送邮件任务... ...");
        }

        for (SysJob sysJob:jobList) {
                logger.info("开始发送邮件... ...");
        }
    }
}

7、springboot启动初始化定时任务

/**
 * 这个类用于启动SpringBoot时,加载作业。run方法会自动执行。
 *
 * 另外可以使用 ApplicationRunner
 *
 */
public class InitStartSchedule implements CommandLineRunner {
	private final Logger logger = LoggerFactory.getLogger(this.getClass());
	
	@Autowired
	private ISysJobService sysJobService;
	@Autowired
	private MyJobFactory myJobFactory;
	
	@Override
	public void run(String... args) throws Exception {
		/**
		 * 用于程序启动时加载定时任务,并执行已启动的定时任务(只会执行一次,在程序启动完执行)
		 */
		
		//查询job状态为启用的
		HashMap<String,String> map = new HashMap<String,String>();
		map.put("jobStatus", "1");
		List<SysJob> jobList= sysJobService.querySysJobList(map);
		if( null == jobList || jobList.size() ==0){
			logger.info("系统启动,没有需要执行的任务... ...");
		}
		// 通过SchedulerFactory获取一个调度器实例
		SchedulerFactory sf = new StdSchedulerFactory();
		Scheduler scheduler = sf.getScheduler();
		// 如果不设置JobFactory,Service注入到Job会报空指针
		scheduler.setJobFactory(myJobFactory);
		// 启动调度器
		scheduler.start();

		for (SysJob sysJob:jobList) {
			String jobClassName=sysJob.getJobName();
			String jobGroupName=sysJob.getJobGroup();
			//构建job信息
			JobDetail jobDetail = JobBuilder.newJob(getClass(sysJob.getJobClassPath()).getClass()).withIdentity(jobClassName, jobGroupName).build();
			if (StringUtils.isNotEmpty(sysJob.getJobDataMap())) {
				JSONObject jb = JSONObject.parseObject(sysJob.getJobDataMap());
				Map<String, Object> dataMap = (Map<String, Object>)jb.get("data");
				for (Map.Entry<String, Object> m:dataMap.entrySet()) {
					jobDetail.getJobDataMap().put(m.getKey(),m.getValue());
				}
			}
			//表达式调度构建器(即任务执行的时间)
	        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(sysJob.getJobCron());
	        //按新的cronExpression表达式构建一个新的trigger
	        CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobClassName, jobGroupName)
	            .withSchedule(scheduleBuilder).startNow().build();
	        // 任务不存在的时候才添加
	        if( !scheduler.checkExists(jobDetail.getKey()) ){
		        try {
		        	scheduler.scheduleJob(jobDetail, trigger);
		        } catch (SchedulerException e) {
		        	logger.info("\n创建定时任务失败"+e);
		            throw new Exception("创建定时任务失败");
		        }
	        }
		}
	}
	
	public static BaseJob getClass(String classname) throws Exception
	{
		Class<?>  c= Class.forName(classname);
		return (BaseJob)c.newInstance();
	}
}

8、自定义JobFactory,使Task注册为Bean

/**
 *
 * 将Spring的对象注入到Quartz Job 1
 */
public class AdaptableJobFactory implements JobFactory {
	@Override
	public Job newJob(TriggerFiredBundle bundle, Scheduler arg1) throws SchedulerException {
		 return newJob(bundle);
	}

	 public Job newJob(TriggerFiredBundle bundle) throws SchedulerException {
	        try {
	        	// 返回Job实例
	            Object jobObject = createJobInstance(bundle);
	            return adaptJob(jobObject);
	        }
	        catch (Exception ex) {
	            throw new SchedulerException("Job instantiation failed", ex);
	        }
	    }

	    // 通过反射的方式创建实例
	    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
	        Method getJobDetail = bundle.getClass().getMethod("getJobDetail");
	        Object jobDetail = ReflectionUtils.invokeMethod(getJobDetail, bundle);
	        Method getJobClass = jobDetail.getClass().getMethod("getJobClass");
	        Class jobClass = (Class) ReflectionUtils.invokeMethod(getJobClass, jobDetail);
	        return jobClass.newInstance();
	    }

	    protected Job adaptJob(Object jobObject) throws Exception {
	        if (jobObject instanceof Job) {
	            return (Job) jobObject;
	        }
	        else if (jobObject instanceof Runnable) {
	            return new DelegatingJob((Runnable) jobObject);
	        }
	        else {
	            throw new IllegalArgumentException("Unable to execute job class [" + jobObject.getClass().getName() +
	                    "]: only [org.quartz.Job] and [java.lang.Runnable] supported.");
	        }
	    }
}
/**
 *
 * 将Spring的对象注入到Quartz Job 2
 */
@Component
public class MyJobFactory extends AdaptableJobFactory {
    @Autowired
    private AutowireCapableBeanFactory capableBeanFactory;

    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
        //调用父类的方法
        Object jobInstance = super.createJobInstance(bundle);
        // 使我们的JOB注入到Spring容器
        capableBeanFactory.autowireBean(jobInstance);

        return jobInstance;
    }
}

9、省略的内容

此处省略了SysJob实体类,以及Mapper等对数据库的操作。

10、总结

本文只是大致实现一个基于Quartz实现定时任务的动态调度,具体细节还有很多未完善的。自己实现一个任务调度器的话,非常麻烦细节很多。
实现任务调度,推荐使用xxl-job分布式任务调度,或者Elastic-job。

如果需求实在是想要动态的创建任务,修改任务,那么目前为止我还没有更好的办法,只能参考该文章了。


标签:Exception,Quartz,String,改查,任务,job,new,定时,throws
From: https://blog.51cto.com/u_13540373/6898590

相关文章

  • C# system.Threading.Timer和system.Timers中的定时器
    它们都可以用于在指定时间间隔后执行代码。然而,它们在实现和用法上有一些差异。System.Threading.Timer:System.Threading.Timer是基于线程的定时器,它属于System.Threading命名空间。它使用ThreadPool线程来执行定时操作。以下是关于System.Threading.Timer的一些重要特......
  • STM32定时器输出PWM脉冲
    一、什么是PWM脉冲?PWM(PulseWidthModulation)脉冲宽度调制,通常应用于惯性系统中,(不是不能即停的设备,因为如果设备不具有关心,那么运动是断断续续的,不具有连续性),通过脉宽调节输出不同的波形作用域受控对象。二、PWM中三个重要的参数1.频率=1/Ts;这个很好理解,就是在单位时间内......
  • .NET6中配置Hangfire定时任务
    1.安装Nuget包Hangfire.CoreHangfire.SqlServer          --sqlserver数据库SqlServer需要配置其中一个包Microsoft.Data.SqlClientsystem.data.sqlclient Hangfire.As......
  • 代码随想录算法训练营第三天| LeetCode 203.移除链表元素(同时也对整个单链表进行增删
    203.移除链表元素      题目链接/文章讲解/视频讲解::https://programmercarl.com/0203.%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8%E5%85%83%E7%B4%A0.html    卡哥题目建议:本题最关键是要理解虚拟头结点的使用技巧,这个对链表题目很重要。   做题思路:   ......
  • 数据结构之带头节点的单链表增删改查操作实现
     单链表的定义什么是单链表   单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。   单链表的各个数据元素在物理上可以是离散存放的,每个结点除了存放数据元素外,还要存储指向下一个节点的指针。而顺序表是连续存放的,每个结点中只......
  • Quartz任务调度快速入门
    了解Quartz体系结构Quartz对任务调度的领域问题进行了高度的抽象,提出了调度器、任务和触发器这3个核心的概念,并在org.quartz通过接口和类对重要的这些核心概念进行描述:●Job:是一个接口,只有一个方法voidexecute(JobExecutionContextcontext),开发者实现该接口定义运行任务,JobExe......
  • xxl-job 定时任务的调研及学习
    xxl-job定时任务官网xxl-jobspringboot整合资料参考一、xxl-job简介xxl-job是一个开源的分布式定时任务框架,它可以与其他微服务组件一起构成微服务集群。它的调度中心(xxl-job)和执行器(自己的springboot项目中有@XxlJob("定时任务名称")的方法)是相互分离,分开部署的,两者通......
  • linux 定时任务清理数据
    1、查找及删除文件的命令find对应目录-mtime+天数-name"文件名"-execrm-rf{}\;应用命令为:find/fastdfs/storage/store/data/-mtime+10-name"*.*"-execrm-rf{}\;2、编辑脚本vi/fastdfs/storage/deleteScratchFile.sh内如如下:(删除30天前的文件。) ......
  • ORM对数据的增删改查,动静态网页,Django创建表关系,Django框架的请求生命周期流程图
    通过结合前端页面实现ORM对数据的增删改查#我让你写一个页面,就是把数据库中的数据以表格的形式展示出来,然后在每一行的后面加两个按钮,分别是修改、删除的按钮#表格的展示页面'''思考修改功能的逻辑:'''1、确定修改哪条记录,怎么确定?通过主键id确定唯一一条记录2、点击......
  • Java定时弹窗提示与展示图片
    自顶向下介绍,首先是定时弹窗功能,可以用Java自带的ScheduledExecutorService库完成函数调用。packagehealthReminder;importjava.util.concurrent.Executors;importjava.util.concurrent.ScheduledExecutorService;importjava.util.concurrent.TimeUnit;publicclassT......