003-spring结合java类调用quartz
一、利弊
针对001 中设置,不方便程序中动态添加任务,只能使用配置进行配置任务,
适用于已知固定时刻需要执行的任务。
针对002中设置,不方便结合调用spring注入的实体
使用于程序内部新增添的任务
二、结合spring以及动态添加任务
1.编写ApplicationContext对象注入类
@Component public class SpringContextUtil implements ApplicationContextAware { // Spring应用上下文环境 private static ApplicationContext applicationContext; /** * 实现ApplicationContextAware接口的回调方法。设置上下文环境 * * @param applicationContext */ @Override public void setApplicationContext(ApplicationContext applicationContext) { SpringContextUtil.applicationContext = applicationContext; } /** * @return ApplicationContext */ public static ApplicationContext getApplicationContext() { return applicationContext; } /** * 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型. */ @SuppressWarnings("unchecked") public static <T> T getBean(String name) { checkApplicationContext(); if (applicationContext.containsBean(name)) { return (T) applicationContext.getBean(name); } return null; } /** * 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型. */ @SuppressWarnings("unchecked") public static <T> T getBean(Class<T> clazz) { checkApplicationContext(); return (T) applicationContext.getBean(clazz); } private static void checkApplicationContext() { if (applicationContext == null){ throw new IllegalStateException("applicaitonContext未注入,请在applicationContext.xml中定义SpringContextUtil"); } } /** * 同步方法注册bean到ApplicationContext中 * * @param beanName * @param clazz * @param original bean的属性值 */ public static synchronized void setBean(String beanName, Class<?> clazz,Map<String,Object> original) { checkApplicationContext(); DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory(); if(beanFactory.containsBean(beanName)){ return; } //BeanDefinition beanDefinition = new RootBeanDefinition(clazz); GenericBeanDefinition definition = new GenericBeanDefinition(); //类class definition.setBeanClass(clazz); //属性赋值 definition.setPropertyValues(new MutablePropertyValues(original)); //注册到spring上下文 beanFactory.registerBeanDefinition(beanName, definition); } /** * 删除spring中管理的bean * @param beanName */ public static void removeBean(String beanName){ ApplicationContext ctx = SpringContextUtil.getApplicationContext(); DefaultListableBeanFactory acf = (DefaultListableBeanFactory) ctx.getAutowireCapableBeanFactory(); if(acf.containsBean(beanName)) { acf.removeBeanDefinition(beanName); } } /** * 根据bean的id来查找对象 * * @param id * @return */ public static <T> T getBeanById(String id) { return (T) applicationContext.getBean(id); } }
2.spring,xml配置
<bean id="spring" class="com.trace.common.quartz.SpringContextUtil" />
3.编写Job接口工厂
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.注入Job工厂,以及quartz调度工厂
<bean id="jobFactory" class="com.jd.ofc.trace.common.quartz.JobFactory"></bean> <bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="jobFactory" ref="jobFactory"></property> </bean>
5.java帮助类
public class TaskJobUtil { private static final Logger logger = LoggerFactory.getLogger(TaskJobUtil.class); private TaskJobUtil() { } /** * 添加任务 * * @param job 要调用的job类 * @param jobName job名称 * @param cronExpression 任务触发时间表达式 * @param param 需要用到的参数,可在job类中的context获得 */ public static void addJob(Job job, String jobName, String cronExpression, Map param) { Scheduler scheduler = null; try { removeJob(jobName, job.getClass().getCanonicalName() + "Group");//删除原任务 scheduler= (StdScheduler)SpringContextUtil.getBean("schedulerFactoryBean"); JobDetail jobDetail = getJobDetail(job, jobName, param); String jobGroup = jobDetail.getGroup(); CronTrigger cronTrigger = getCronTrigger(job, jobName, jobGroup, cronExpression); scheduler.scheduleJob(jobDetail, cronTrigger); logger.info("添加任务:" + jobName); startScheduler(); } catch (SchedulerException e) { logger.error("", e); } } /** * 对外停止任务调度器方法 */ public static void stopJob() { shutdownScheduler(); } /** * 启动调度器 */ protected static void startScheduler() { Scheduler scheduler = null; try { scheduler= (StdScheduler)SpringContextUtil.getBean("schedulerFactoryBean"); //如果调度器未启动,启动调度器 if (scheduler != null && !scheduler.isStarted()) { scheduler.start(); } } catch (SchedulerException e) { logger.error("", e); } } /** * 关闭调度器,关闭后任务也都清除 */ protected static void shutdownScheduler() { Scheduler scheduler = null; try { scheduler= (StdScheduler)SpringContextUtil.getBean("schedulerFactoryBean"); //如果调度器未关闭,关闭调度器 if (scheduler != null && !scheduler.isShutdown()) { scheduler.shutdown(); } } catch (SchedulerException e) { logger.error("", e); } } /** * 获取JobDetail * * @param job * @param param * @return */ protected static JobDetail getJobDetail(Job job, String jobName, Map param) { Class jobClazz = job.getClass(); if (jobName == null || "".equals(jobName)) { jobName = jobClazz.getCanonicalName(); } String jobGroup = jobClazz.getCanonicalName() + "Group"; JobDetail jobDetail = new JobDetail(); jobDetail.setDurability(true); jobDetail.setRequestsRecovery(true); jobDetail.setName(jobName); jobDetail.setGroup(jobGroup); jobDetail.setJobClass(jobClazz); if (param != null && param.size() > 0) { JobDataMap jobDataMap = new JobDataMap(param);//存放参数 jobDetail.setJobDataMap(jobDataMap); logger.info("任务 " + jobName + " jobDetail存放的参数:" + param); } return jobDetail; } /** * 获取触发器 * * @param job * @param jobName * @param cronExpression * @return */ protected static CronTrigger getCronTrigger(Job job, String jobName, String jobGroup, String cronExpression) { Class jobClazz = job.getClass(); String triggerName = jobName+jobClazz.getCanonicalName() + "Trigger"; String triggerGroup = jobClazz.getCanonicalName() + "TriggerGroup"; CronTrigger cronTrigger = new CronTrigger(); cronTrigger.setName(triggerName); cronTrigger.setGroup(triggerGroup); cronTrigger.setJobName(jobName); cronTrigger.setJobGroup(jobGroup); try { cronTrigger.setCronExpression(cronExpression);//触发任务的时间表达式 } catch (Exception e) { logger.error("",e); } logger.info("任务 " + jobName + " 触发时间:" + cronExpression); return cronTrigger; } /** * 删除job * * @param jobName * @param jobGroup */ public static void removeJob(String jobName, String jobGroup) { logger.info("删除任务:jobName:" + jobName + " jobGroup:" + jobGroup); Scheduler scheduler = null; String[] jobNames = null; try { scheduler= (StdScheduler)SpringContextUtil.getBean("schedulerFactoryBean"); jobNames = scheduler.getJobNames(jobGroup); if (jobNames == null || jobNames.length == 0) { return; } for (String name : jobNames) { if (name.equals(jobName)) { scheduler.pauseTrigger(jobName, jobGroup);//停止触发器 scheduler.pauseJob(jobName, jobGroup);//暂停job scheduler.unscheduleJob(jobName, jobGroup);//取消预订的job scheduler.deleteJob(jobName, jobGroup);//删除job } } } catch (SchedulerException e) { logger.error("", e); } } /** * 获取任务列表 * * @return */ public static Map<String, List<String>> getJobList() { Scheduler scheduler = null; Map<String, List<String>> map = null; try { scheduler= (StdScheduler)SpringContextUtil.getBean("schedulerFactoryBean"); String[] jobGroupNames = scheduler.getJobGroupNames(); if (jobGroupNames == null || jobGroupNames.length == 0) { return null; } map = new HashMap<String, List<String>>(); for (String jobGroup : jobGroupNames) { String[] jobNames = scheduler.getJobNames(jobGroup); if (jobNames == null || jobNames.length == 0) { continue; } List<String> jobNameList = new ArrayList<String>(); for (String jobName : jobNames) { jobNameList.add(jobName); } map.put(jobGroup, jobNameList); } } catch (SchedulerException e) { logger.error("", e); } logger.info("获取job列表:" + map); return map; } }
6.程序中使用
直接抵用
addJob等即可