基于quartz的动态任务

    xiaoxiao2024-11-25  15

    quartz是一个提供定时任务的框架。任务可以直接配置在配置文件之中或者数据库里,这种无法修改的任务可以叫做静态任务,而这次写的是怎么创建动态任务,可以在项目运行中对定时任务进行创建、修改、删除等操作。 我这里是基于spring框架搭建的quartz系统。spring配置文件中配置了SchedulerFactoryBean工厂类,用于生成Scheduler对象。

    <bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" lazy-init="false"> <property name="dataSource"><!--数据库数据源,这里的任务是配置在数据库中的--> <ref bean="qrtzDataSource"/> </property> <property name="autoStartup" value="true"/> <!--开发人员本机此处默认为false--> <property name="startupDelay" value="60" /> <property name="applicationContextSchedulerContextKey" value="applicationContext"/> <property name="configLocation" value="classpath:/spring/quartz.properties"/> </bean>

    表结构都是quartz项目提供的,我用的mysql,选取对应文件即可。

    开始coding 1、首先定义一个我们需要的job的信息类

    public class QuartzJobBean implements Serializable { private static final long serialVersionUID = 8426499555496553217L; public static final String CONCURRENT_IS = "1"; public static final String CONCURRENT_NOT = "0"; public static final String STATUS_NONE = "NONE"; public static final String STATUS_NORMAL = "NORMAL"; public static final String STATUS_PAUSED = "PAUSED"; public static final String STATUS_COMPLETE = "COMPLETE"; public static final String STATUS_ERROR = "ERROR"; public static final String STATUS_BLOCKED = "BLOCKED"; /** 任务id */ private String jobId; /** 任务名称 */ private String jobName; /** 任务分组,任务名称+组名称应该是唯一的 */ private String jobGroup; /** 任务初始状态 0禁用 1启用 2删除*/ private String jobStatus; /** 任务是否有状态(并发) */ private String isConcurrent = "1"; /** 任务运行时间表达式 */ private String cronExpression; /** 任务描述 */ private String description; /** 任务调用类在spring中注册的bean id,如果spingId不为空,则按springId查找 */ private String springId; /** 任务调用类名,包名+类名,通过类反射调用 ,如果spingId为空,则按jobClass查找 */ private String jobClass; /** 任务调用的方法名 */ private String methodName; /** 启动时间 */ private Date startTime; /** 前一次运行时间 */ private Date previousTime; /** 下次运行时间 */ private Date nextTime; //getter、setter方法

    2、接下来是核心任务操作类

    @Component public class QuartzJobManage { private static final Logger logger = LoggerFactory.getLogger(QuartzJobManage.class); /** * 添加任务 * * @param scheduleJob */ public void addJob(QuartzJobBean scheduleJob) throws CustomerBizException { try { if (scheduleJob == null || !QuartzJobBean.STATUS_NORMAL.equals(scheduleJob.getJobStatus())) throw new CustomerBizException("添加的任务不能为null并且任务的初始状态必须是[STATUS_NORMAL]"); if (!TaskUtils.isValidExpression(scheduleJob.getCronExpression())) throw new CustomerBizException("任务名称[" + scheduleJob.getJobName() + "] 任务分组[" + scheduleJob.getJobGroup() + "]的时间表达式错误:" + scheduleJob.getCronExpression()); //SpringContextUtil.getBean("schedulerFactoryBean");就是封装的这个applicationContext.getBean(name);这句代码里面有关于spring IOC的一个机制,如果你实现了spring的FactoryBean<T>接口,那你通过applicationContext.getBean(name)返回的将是getObjectType()方法返回的对象,类型为T,详情可参见spring源码 Scheduler scheduler = (Scheduler) SpringContextUtil.getBean("schedulerFactoryBean"); final TriggerKey triggerKey = TriggerKey.triggerKey(scheduleJob.getJobName(), scheduleJob.getJobGroup()); Trigger trigger = scheduler.getTrigger(triggerKey); if (null == trigger){ //这是QuartzJobBean类中定义的真正要执行的任务类 Class<? extends Job> clazz = (Class<? extends Job>) Class.forName(scheduleJob.getJobClass()); final JobDetail jobDetail = JobBuilder.newJob(clazz).withIdentity(scheduleJob.getJobName(), scheduleJob.getJobGroup()).build(); jobDetail.getJobDataMap().put("scheduleJob", scheduleJob); final CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression()); trigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withSchedule(scheduleBuilder).build(); scheduler.scheduleJob(jobDetail, trigger); } else { // trigger已存在,则更新相应的定时设置 final CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression()); trigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withSchedule(scheduleBuilder).build(); scheduler.rescheduleJob(triggerKey, trigger); } } catch (SchedulerException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } /** 暂停任务 * @param scheduleJob * @return */ public void pauseJob(QuartzJobBean scheduleJob){ try { Scheduler scheduler = (Scheduler) SpringContextUtil.getBean("schedulerFactoryBean"); final JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup()); scheduler.pauseJob(jobKey); } catch (SchedulerException e) { logger.error("任务暂停失败:", e); } } /** * 恢复任务 * @param scheduleJob * @return */ public void resumeJob(QuartzJobBean scheduleJob) { try { Scheduler scheduler = (Scheduler) SpringContextUtil.getBean("schedulerFactoryBean"); final JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup()); scheduler.resumeJob(jobKey); } catch (SchedulerException e) { logger.error("任务恢复失败:", e); } } /** * 删除任务 */ public void deleteJob(QuartzJobBean scheduleJob){ try { Scheduler scheduler = (Scheduler) SpringContextUtil.getBean("schedulerFactoryBean"); final JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup()); scheduler.deleteJob(jobKey); } catch (SchedulerException e) { logger.error("任务名称[" + scheduleJob.getJobName() + "] 分组[" + scheduleJob.getJobGroup() + "] 删除失败!", e); } } /** * 获取单个任务 * @param jobName * @param jobGroup * @return * @throws SchedulerException */ public QuartzJobBean findJob(String jobName, String jobGroup) { try { QuartzJobBean job = null; Scheduler scheduler = (Scheduler) SpringContextUtil.getBean("schedulerFactoryBean"); TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup); CronTrigger trigger = (CronTrigger)scheduler.getTrigger(triggerKey); JobKey jobKey = JobKey.jobKey(jobName, jobGroup); JobDetail jobDetail = scheduler.getJobDetail(jobKey); if (trigger != null && jobDetail != null) { QuartzJobBean jobExist = (QuartzJobBean)jobDetail.getJobDataMap().get("scheduleJob"); job = new QuartzJobBean(); job.setJobName(jobName); job.setJobGroup(jobGroup); job.setDescription("触发器:" + trigger.getKey()); job.setNextTime(trigger.getNextFireTime()); //下次触发时间 job.setPreviousTime(trigger.getPreviousFireTime());//上次触发时间 job.setDescription(jobExist.getDescription()); job.setJobClass(jobExist.getJobClass()); job.setMethodName(jobExist.getMethodName()); 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); } } return job; } catch (Exception e) { logger.error("任务获取失败:", e); } return null; } }

    3、任务执行我用的quartz的Job类,通过集成spring的QuartzJobBean类,他是一个实现了Job接口,完成了任务执行模板(模板模式)的抽象类,我们继承他实现一些自己的逻辑和规则。BaseJob 类也是一个模板,run()方法的实现就是要执行的任务。

    @Component public abstract class BaseJob extends QuartzJobBean{ private static final Logger logger = LoggerFactory.getLogger(BaseJob.class); /** * 供实现类运行 * @param context 任务执行上下文 * @throws JobExecutionException 任务执行时异常 */ protected abstract void run(JobExecutionContext context) throws JobExecutionException; /** * @param context 任务执行上下文 * @throws JobExecutionException 任务执行时异常 */ protected void executeInternal(JobExecutionContext context) throws JobExecutionException { try { run(context); } catch (Exception e) { logger.error(e.toString()); } finally { } } }

    4、任务实现类,举例

    public class OrderPayTask extends BaseJob { @Override protected void run(JobExecutionContext context) throws JobExecutionException { //自己的任务实现 } }

    5、任务工具类

    public class TaskUtils { private static final Logger logger = LoggerFactory.getLogger(TaskUtils.class); /** * 判断cron时间表达式正确性 * @param cronExpression * @return */ public static boolean isValidExpression(String cronExpression){ CronTriggerImpl trigger = new CronTriggerImpl(); try { trigger.setCronExpression(cronExpression); final Date date = trigger.computeFirstFireTime(null); return date != null && date.after(new Date()); } catch (ParseException e) { logger.error("时间表达式:" + cronExpression + "错误"); } return false; } }

    6、成功之后主要表里的数据 qrtz_job_details qrtz_job_details qrtz_triggers

    就此完结!

    转载请注明原文地址: https://ju.6miu.com/read-1294009.html
    最新回复(0)