Spring+quartz实现定时任务集群

时间:2021-10-01 07:47:46

1.准备环境(以maven为例,如果不是请自行下载需要的jar包)

<!-- quartz定时调度器 -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.0</version>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.43</version>
</dependency>

配置这个集群需要建立数据库的表,去quartz的官网去下载他的包,解压之后在D:\软件开发\环境软件\quartz-2.2.3-distribution\quartz-2.2.3\docs\dbTables这个目录下面有很多个sql文件,我的是mysql所以我选择的是:tables_mysql_innodb.sql,拿到这个sql文件之后就可以在数据库执行了。

2.配置spring-quartz.properties

org.quartz.scheduler.instanceName = TestScheduler1  
org.quartz.scheduler.instanceId = AUTO

org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 10
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true

org.quartz.jobStore.misfireThreshold = 60000
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.maxMisfiresToHandleAtATime=10
org.quartz.jobStore.isClustered = true
org.quartz.jobStore.clusterCheckinInterval = 20000
3.配置spring-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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<!-- 自定义jobFactory,解决job中无法注入service的问题 -->
<bean id="jobFactory" class="com.mayi.common.Quartz.MyJobFactory" />
<!-- 配置任务bean类 -->
<!-- <bean id="scheduledJob" class="com.mayi.common.Quartz.FirstScheduledJob"></bean>-->

<!-- 配置方法映射工厂类 -->
<!-- MethodInvokingJobDetailFactoryBean不支持序列化 -->
<!-- concurrent : false表示等上一个任务执行完后再开启新的任务 -->
<!-- <bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="quartzTask"></property> <property name="targetMethod" value="startTask"></property>
<property name="concurrent" value="false"></property>
</bean> -->
<bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="com.mayi.common.Quartz.FirstScheduledJob"></property>
<property name="durability" value="true"></property>
<property name="requestsRecovery" value="true"/>
</bean>
<!-- 配置任务高度的的时间/周期 -->
<bean id="jobTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="jobDetail"></property>
<property name="cronExpression" value="*/1 * * * * ?"></property>
<!-- <property name="startDelay" value="3000"></property> -->
</bean>
</beans>
4.在spring-context.xml文件中加入下面的配置,并将 spring-quartz.xml和spring-quartz.properties引入到主配置文件中(这个不会的请自己去找相关spring的资料去学习)
<!-- 定时调度工厂 -->    <beans:bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">        <beans:property name="dataSource" ref="mixDataSource_push"></beans:property>        <!-- 引入自定义的bean -->        <beans:property name="jobFactory" ref="jobFactory" />        <!--可选,QuartzScheduler 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了 -->        <beans:property name="overwriteExistingJobs" value="true"/>        <!--必须的,QuartzScheduler 延时启动,应用启动完后 QuartzScheduler 再启动 -->        <beans:property name="startupDelay" value="3"/> <!-- 设置自动启动 -->        <beans:property name="autoStartup" value="true"/>        <beans:property name="applicationContextSchedulerContextKey" value="applicationContextKey"/>        <beans:property name="configLocation" value="classpath:spring-quartz.properties"/>        <beans:property name="triggers">            <beans:list>                <beans:ref bean="jobTrigger"/>            </beans:list>        </beans:property>    </beans:bean>     <beans:import resource="classpath:spring-quartz.xml" />
5.初次之外还需两个类,一个是自定义的jobFactory,一个是FirstScheduledJob;

package com.mayi.common.Quartz;

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 MyJobFactory extends AdaptableJobFactory {
//这个对象Spring会帮我们自动注入进来,也属于Spring技术范畴.
@Autowired
private AutowireCapableBeanFactory capableBeanFactory;

protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
//调用父类的方法
Object jobInstance = super.createJobInstance(bundle);
//进行注入,这属于Spring的技术,不清楚的可以查看Spring的API.
capableBeanFactory.autowireBean(jobInstance);
return jobInstance;
}
}
package com.mayi.common.Quartz;import com.mayi.push.dao.TbPushRecordMapper;import com.mayi.push.dao.TbSocketRecordMapper;import com.mayi.push.data.model.TbSocketRecord;import com.mayi.push.data.model.TbSocketRecordExample;import com.mayi.thirdparty.PushFactory;import org.quartz.DisallowConcurrentExecution;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;import org.quartz.PersistJobDataAfterExecution;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.scheduling.quartz.QuartzJobBean;import org.springframework.stereotype.Component;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.List;@Component@PersistJobDataAfterExecution@DisallowConcurrentExecution   // 不允许并发执行public class FirstScheduledJob extends QuartzJobBean {    private static final Logger logger = LoggerFactory.getLogger(FirstScheduledJob.class);    @Override    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {        try {            //执行你自己的任务        } catch (ParseException e) {            logger.error("FirstScheduledJob(定时器任务):"+e.getMessage());        }    }}



说明:这样就实现了多台服务器的quartz的集群,原理是一台服务器在运行定时任务的时候,其他服务器是无法运行的,直到本台服务器挂掉或者断掉,其他两台中的一台会接管继续执行。