quarz定时任务调度集成

任务调度 只需做三件事,再什么时候在哪里做什么事;

一.工作原理:

1、scheduler是一个计划调度器容器(总部),容器里面可以盛放众多的JobDetail和trigger,当容器启动后,里面的每个JobDetail都会根据trigger按部就班自动去执行。

2、JobDetail是一个可执行的工作,它本身可能是有状态的。

3、Trigger代表一个调度参数的配置,什么时候去调。

4、当JobDetail和Trigger在scheduler容器上注册后,形成了装配好的作业(JobDetail和Trigger所组成的一对儿),就可以伴随容器启动而调度执行了。

5、scheduler是个容器,容器中有一个线程池,用来并行调度执行每个作业,这样可以提高容器效率。

 

二.集成

1.导包到pom

	<!-- quartz任务调度 -->
<dependency>
			<groupId>commons-dbcp</groupId>
			<artifactId>commons-dbcp</artifactId>
			<version>1.3</version>
		</dependency>

<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context-support</artifactId>
			<version>${spring.version}</version>
		</dependency>

     
		<dependency>
			<groupId>org.quartz-scheduler</groupId>
			<artifactId>quartz</artifactId>
			<version>2.2.1</version>
		</dependency>
		<dependency>
			<groupId>org.quartz-scheduler</groupId>
			<artifactId>quartz-jobs</artifactId>
			<version>2.2.1</version>
		</dependency>
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-lang3</artifactId>
			<version>3.0</version>
		</dependency>

 

2.创建数据库表

解压缩quartz官方发行包,找到quartz-2.2.3\docs\dbTables 下的 tables_mysql_innodb.sql在navicat中执行即可创建quartz持久化相关的表。

3.将quartz的工厂对象交给spring管理

spring-quartz.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="  
    http://www.springframework.org/schema/context  
    http://www.springframework.org/schema/context/spring-context.xsd  
    http://www.springframework.org/schema/beans  
    http://www.springframework.org/schema/beans/spring-beans.xsd">
	<!-- 配置连接池 -->
	<bean id="quartzDataSource" class="org.apache.commons.dbcp.BasicDataSource">
		<property name="username" value="root"></property>
		<property name="password" value="root"></property>
		<property name="url" value="jdbc:mysql:///quartz?characterEncoding=utf-8"></property>
		<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
	</bean>   
 <!-- quartz持久化存储 -->
    <bean name="quartzScheduler"  
        class="org.springframework.scheduling.quartz.SchedulerFactoryBean">  
        <property name="dataSource">  
            <ref bean="quartzDataSource" />  
        </property>
        <property name="applicationContextSchedulerContextKey" value="applicationContext" />  
       <!--  也可以在quartz.properties中配置   -->
        <property name="quartzProperties">  
            <props>  
                <prop key="org.quartz.scheduler.instanceName">AIGOUscheduler</prop>  
                <prop key="org.quartz.scheduler.instanceId">AUTO</prop>  
              <!--   线程池配置   -->
                <prop key="org.quartz.threadPool.class">org.quartz.simpl.SimpleThreadPool</prop>  
                <prop key="org.quartz.threadPool.threadCount">20</prop>  
                <prop key="org.quartz.threadPool.threadPriority">5</prop>  
                <prop key="org.quartz.jobStore.misfireThreshold">120000</prop>  
                <!-- JobStore 配置   -->
                <prop key="org.quartz.jobStore.class">org.quartz.impl.jdbcjobstore.JobStoreTX</prop>  
               <!--  集群配置   -->
                <prop key="org.quartz.jobStore.isClustered">true</prop>  
                <prop key="org.quartz.jobStore.clusterCheckinInterval">15000</prop>  
                <prop key="org.quartz.jobStore.maxMisfiresToHandleAtATime">1</prop>  
              <!--   数据表设置   -->
                <prop key="org.quartz.jobStore.tablePrefix">qrtz_</prop>  
                <prop key="org.quartz.jobStore.dataSource">qzDS</prop>  
            </props>  
        </property>  
      <!--   可选,QuartzScheduler启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了   -->
        <property name="overwriteExistingJobs" value="true" />  
        <!-- 设置自动启动   -->
        <property name="autoStartup" value="true" />  
    </bean>  
</beans>

整合dubbo

spring-dubbo-quartz.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
	xsi:schemaLocation="  
    http://www.springframework.org/schema/beans  
    http://www.springframework.org/schema/beans/spring-beans.xsd  
    http://code.alibabatech.com/schema/dubbo 
    http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

	<!-- dubbo服务发布 -->
	<dubbo:application name="www-service-common" />
	<dubbo:protocol name="dubbo" port="20885"></dubbo:protocol>
	<import resource="classpath*:spring-dubbo-common-base.xml"/>
</beans>

spring-service-quartz.xml

spring的配置中

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="  
    http://www.springframework.org/schema/context  
    http://www.springframework.org/schema/context/spring-context.xsd  
    http://www.springframework.org/schema/beans  
    http://www.springframework.org/schema/beans/spring-beans.xsd">
	
	<import resource="classpath*:spring-dubbo-quartz.xml"/>
	<import resource="classpath*:spring-quartz.xml"/>
</beans>

 

创建QuartzUtils工具类,用于动态管理任务

/**
 * Quartz调度管理器
 * 
 */
public class QuartzUtils {
	private static String JOB_GROUP_NAME = "JOB_GROUP_SYSTEM";
	private static String TRIGGER_GROUP_NAME = "TRIGGER_GROUP_SYSTEM";

	/**
	 * @Description: 添加一个定时任务,使用默认的任务组名,触发器名,触发器组名
	 * 
	 * @param sched
	 *            调度器
	 * 
	 * @param jobName
	 *            任务名
	 * @param cls
	 *            任务
	 * @param params
	 *            任务参数
	 * @param time
	 *            时间设置,参考quartz说明文档
	 * 
	 * @Title: QuartzManager.java
	 */
	public static void addJob(Scheduler sched, String jobName, @SuppressWarnings("rawtypes") Class cls, Object params,
			String time) {
		try {
			JobKey jobKey = new JobKey(jobName, JOB_GROUP_NAME);// 任务名,任务组,任务执行类
			@SuppressWarnings("unchecked")

			JobDataMap jobDataMap = new JobDataMap();
			jobDataMap.put("params", params);
			JobDetail jobDetail = newJob(cls).withIdentity(jobKey).setJobData(jobDataMap).build();
			TriggerKey triggerKey = new TriggerKey(jobName, TRIGGER_GROUP_NAME);// 触发器
			
			Trigger trigger = newTrigger().withIdentity(triggerKey).withSchedule(cronSchedule(time)).build();// 触发器时间设定
			sched.scheduleJob(jobDetail, trigger);
			if (!sched.isShutdown()) {
				sched.start();// 启动
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * @Description: 添加一个定时任务
	 * 
	 * @param sched
	 *            调度器
	 * 
	 * @param jobName
	 *            任务名
	 * @param jobGroupName
	 *            任务组名
	 * @param triggerName
	 *            触发器名
	 * @param triggerGroupName
	 *            触发器组名
	 * @param jobClass
	 *            任务
	 * @param params
	 *            任务参数
	 * @param time
	 *            时间设置,参考quartz说明文档
	 * 
	 * @Title: QuartzManager.java
	 */
	public static void addJob(Scheduler sched, String jobName, String jobGroupName, String triggerName,
			String triggerGroupName, @SuppressWarnings("rawtypes") Class jobClass,  Object params, String time) {
		try {
			JobKey jobKey = new JobKey(jobName, jobGroupName);
			JobDataMap jobDataMap = new JobDataMap();
			jobDataMap.put("params", params);
			@SuppressWarnings("unchecked")
			JobDetail jobDetail = newJob(jobClass).withIdentity(jobKey).setJobData(jobDataMap).build();
			// 触发器
			TriggerKey triggerKey = new TriggerKey(triggerName, triggerGroupName);
			Trigger trigger = newTrigger().withIdentity(triggerKey).withSchedule(cronSchedule(time)).build();
			sched.scheduleJob(jobDetail, trigger);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * @Description: 修改一个任务的触发时间(使用默认的任务组名,触发器名,触发器组名)
	 * 
	 * @param sched
	 *            调度器
	 * @param jobName
	 * @param time
	 * 
	 * @Title: QuartzManager.java
	 */
	@SuppressWarnings("rawtypes")
	public static void modifyJobTime(Scheduler sched, String jobName, String time) {
		try {
			TriggerKey triggerKey = new TriggerKey(jobName, TRIGGER_GROUP_NAME);
			CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerKey);
			if (trigger == null) {
				return;
			}
			String oldTime = trigger.getCronExpression();
			if (!oldTime.equalsIgnoreCase(time)) {
				JobKey jobKey = new JobKey(jobName, JOB_GROUP_NAME);
				JobDetail jobDetail = sched.getJobDetail(jobKey);
				Class objJobClass = jobDetail.getJobClass();
				Object params = jobDetail.getJobDataMap().get("params");
				removeJob(sched, jobName);
				System.out.println("修改任务:" + jobName);
				addJob(sched, jobName, objJobClass, params,time);
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * @Description: 修改一个任务的触发时间
	 * 
	 * @param sched
	 *            调度器 *
	 * @param sched
	 *            调度器
	 * @param triggerName
	 * @param triggerGroupName
	 * @param time
	 * 
	 * @Title: QuartzManager.java
	 */
	public static void modifyJobTime(Scheduler sched, String triggerName, String triggerGroupName, String time) {
		try {
			TriggerKey triggerKey = new TriggerKey(triggerName, triggerGroupName);
			CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerKey);
			if (trigger == null) {
				return;
			}
			String oldTime = trigger.getCronExpression();
			if (!oldTime.equalsIgnoreCase(time)) {
				// 修改时间
				trigger.getTriggerBuilder().withSchedule(cronSchedule(time));
				// 重启触发器
				sched.resumeTrigger(triggerKey);
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * @Description: 移除一个任务(使用默认的任务组名,触发器名,触发器组名)
	 * 
	 * @param sched
	 *            调度器
	 * @param jobName
	 * 
	 * @Title: QuartzManager.java
	 */
	public static void removeJob(Scheduler sched, String jobName) {
		try {
			TriggerKey triggerKey = new TriggerKey(jobName, TRIGGER_GROUP_NAME);
			sched.pauseTrigger(triggerKey);// 停止触发器
			sched.unscheduleJob(triggerKey);// 移除触发器
			JobKey jobKey = new JobKey(jobName, JOB_GROUP_NAME);
			sched.deleteJob(jobKey);// 删除任务
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * @Description: 移除一个任务
	 * 
	 * @param sched
	 *            调度器
	 * @param jobName
	 * @param jobGroupName
	 * @param triggerName
	 * @param triggerGroupName
	 * 
	 * @Title: QuartzManager.java
	 */
	public static void removeJob(Scheduler sched, String jobName, String jobGroupName, String triggerName,
			String triggerGroupName) {
		try {
			TriggerKey triggerKey = new TriggerKey(triggerName, triggerGroupName);
			sched.pauseTrigger(triggerKey);// 停止触发器
			sched.unscheduleJob(triggerKey);// 移除触发器
			JobKey jobKey = new JobKey(jobName, jobGroupName);
			sched.deleteJob(jobKey);// 删除任务
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * @Description:启动所有定时任务
	 * 
	 * @param sched  调度器
	 * 
	 * @Title: QuartzManager.java
	 */
	public static void startJobs(Scheduler sched) {
		try {
			sched.start();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * @Description:关闭所有定时任务
	 * 
	 * @param sched
	 *            调度器
	 * 
	 */
	public static void shutdownJobs(Scheduler sched) {
		try {
			if (!sched.isShutdown()) {
				sched.shutdown();
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
}

 

创建任务执行类

public class MainJob implements Job{

	@Override
	public void execute(JobExecutionContext context)
			throws JobExecutionException {
		
		JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();  
        Map<String, Object>  params = (Map<String, Object>) jobDataMap.get("params");
		System.out.println("Hello World...."+params);
	}

}

 

 测试:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath*:spring-service-quartz.xml")
public class JobTest {
	@Autowired
	private SchedulerFactoryBean schedulerFactory;
	@Test
	public void testName() throws Exception {
		//schedulerFactory通过spring注入
		Scheduler sche = schedulerFactory.getScheduler();
		String job_name = "JOB_NAME";
		String clazz = "cn.itsource.aigou.job.MainJob";
		String cron = "/1 * * * * ? ";
		Map<String, Object> params = new HashMap<>();
		params.put("firstJob", 1);
		params.put("firstName", "myFirstName");
		QuartzUtils.addJob(sche, job_name, Class.forName(clazz), params, cron);
         // System.in.read();
		Thread.sleep(10000);     
		System.out.println("【移除定时】开始...");
		QuartzUtils.removeJob(sche, job_name);
		System.out.println("【移除定时】成功");
	}

 

解决quartz的job无法注入spring对象  全网仅此一份

/**
 * 以静态变量保存Spring ApplicationContext, 可在任何代码任何地方任何时候取出ApplicaitonContext.
 * 
 */
@Service
@Lazy(false)
public class SpringContextHolder implements ApplicationContextAware, DisposableBean {

    private static ApplicationContext applicationContext = null;


    /**
     * 取得存储在静态变量中的ApplicationContext.
     */
    public static ApplicationContext getApplicationContext() {
        assertContextInjected();
        return applicationContext;
    }

    /**
     * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
     */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) {
        assertContextInjected();
        return (T) applicationContext.getBean(name);
    }

    /**
     * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
     */
    public static <T> T getBean(Class<T> requiredType) {
        assertContextInjected();
        return applicationContext.getBean(requiredType);
    }

    /**
     * 清除SpringContextHolder中的ApplicationContext为Null.
     */
    public static void clearHolder() {
        applicationContext = null;
    }

    /**
     * 实现ApplicationContextAware接口, 注入Context到静态变量中.
     */
    public void setApplicationContext(ApplicationContext appContext) {
        applicationContext = appContext;
    }

    /**
     * 实现DisposableBean接口, 在Context关闭时清理静态变量.
     */
    public void destroy() throws Exception {
        SpringContextHolder.clearHolder();
    }

    /**
     * 检查ApplicationContext不为空.
     */
    private static void assertContextInjected() {
        Validate.validState(applicationContext != null, "applicaitonContext属性未注入, 请在applicationContext.xml中定义SpringContextHolder.");
    }
}

 

优点是:解耦性强,不必改别人的代码

还有一种方法可解决,就是用static方法解决,但是这样任务多了,每个类都要写就麻烦了

希望我的文章能帮到你

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值