Spring+Quartz集群环境搭建

所需依赖

<dependencies>
    <!--核心包-->
    <dependency>
      <groupId>org.quartz-scheduler</groupId>
      <artifactId>quartz</artifactId>
      <version>2.3.0</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context-support</artifactId>
      <version>4.1.9.RELEASE</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>4.1.9.RELEASE</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>4.1.9.RELEASE</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>4.1.9.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.38</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>4.1.9.RELEASE</version>
    </dependency>

    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.0.24</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>4.1.9.RELEASE</version>
    </dependency>
  </dependencies>

配置文件quartz.properties

#是否用这个配置文件 默认不使用
#org.quartz.jobStore.useProperties= true
#表的前缀名
org.quartz.jobStore.tablePrefix = qrtz_
#是否使用集群
org.quartz.jobStore.isClustered = true
#检查时间间隔
org.quartz.jobStore.clusterCheckinInterval =5000
#最大时间间隔
org.quartz.jobStore.misfireThreshold =60000
org.quartz.jobStore.txIsolationLevelReadCommitted= true
#=========================================================================================
#内存
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
#代理
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#=========================================================================================
#如果使用集群,id必须唯一,所以必须自动生成
org.quartz.scheduler.instanceId =AUTO
#调度器名称
org.quartz.scheduler.instanceName =MY_CLUSTERED_JOB_SCHEDULER
org.quartz.scheduler.rmi.export = false
org.quartz.scheduler.rmi.proxy = false
#=========================================================================================
# Configure ThreadPool
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 10
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true

applicationContext.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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!--配置扫描的包-->
    <context:component-scan base-package="com.otc"/>
    <!--数据库连接池-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/quartz"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
    </bean>
    <!--分布式配置-->

    <!--配置线程池-->
    <bean name="executor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
        <property name="corePoolSize" value="15"/>
        <property name="maxPoolSize" value="25"/>
        <property name="queueCapacity" value="100"/>
    </bean>

    <!--配置事务管理器-->
    <bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--配置job详情-->
    <!--任务一-->
    <bean name="jobDetail_1" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
        <property name="jobClass" value="com.otc.HelloJob"/>
        <!--开启持久化-->
        <property name="durability" value="true"/>
        <!--是否覆盖-->
        <property name="requestsRecovery" value="false"/>
    </bean>

    <!--任务二-->
    <bean name="jobDetail_2" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
        <property name="jobClass" value="com.otc.HelloJob2"/>
        <!--开启持久化-->
        <property name="durability" value="true"/>
        <!--是否覆盖-->
        <property name="requestsRecovery" value="false"/>
    </bean>

    <!--任务三-->
    <bean name="jobDetail_3" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
        <property name="jobClass" value="com.otc.Test11"/>
        <!--开启持久化-->
        <property name="durability" value="true"/>
        <!--是否覆盖-->
        <property name="requestsRecovery" value="false"/>
    </bean>


    <!--配置触发时间-->
    <bean id="cronTrigger_1" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
    <property name="jobDetail">
        <ref bean="jobDetail_1"/>
    </property>
    <!-- 每1秒钟执行一次 -->
    <property name="cronExpression">
        <value>0/1 * * * * ?</value>
    </property>
    <property name="timeZone">
        <value>GMT+8:00</value>
    </property>
</bean>

    <bean id="cronTrigger_2" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
    <property name="jobDetail">
        <ref bean="jobDetail_2"/>
    </property>
    <!-- 每5秒钟执行一次 -->
    <property name="cronExpression">
        <value>0/5 * * * * ?</value>
    </property>
    <property name="timeZone">
        <value>GMT+8:00</value>
    </property>
</bean>

    <bean id="cronTrigger_3" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
        <property name="jobDetail">
            <ref bean="jobDetail_3"/>
        </property>
        <!-- 每10秒钟执行一次 -->
        <property name="cronExpression">
            <value>0/10 * * * * ?</value>
        </property>
        <property name="timeZone">
            <value>GMT+8:00</value>
        </property>
    </bean>


    <!--定义调度器,并将Trigger注册到调度器中-->
    <bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <!--配置文件-->
        <property name="configLocation" value="classpath:quartz.properties"/>
        <!--数据源-->
        <property name="dataSource" ref="dataSource"/>
        <!--任务唯一的名称,将持久化到数据库-->
        <property name="schedulerName" value="mavenTest2"/>
        <!--每台集群机器部署应用的时候更新触发器-->
        <property name="overwriteExistingJobs" value="true"/>
        <property name="applicationContextSchedulerContextKey" value="appl"/>
        <!-- 设置自动启动 -->
        <property name="autoStartup" value="true"/>
        <!--线程池-->
        <property name="taskExecutor" ref="executor"/>
        <!--事务-->
        <property name="transactionManager" ref="transactionManager"/>
        <property name="triggers">
            <list>
                <ref bean="cronTrigger_1"/>
                <ref bean="cronTrigger_2"/>
                <ref bean="cronTrigger_3"/>
            </list>
        </property>
    </bean>
</beans>

job类  继承QuartzJobBean或者实现Job接口

public class HelloJob extends QuartzJobBean {
    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        String format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        System.out.println("任务 1 当前时间:  "+format);
    }
}

测试

public class TestQuartzSpring {
    public static void main(String[] args) {
        //工厂启动,调度器启动,任务调度开始
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    }
}

可以同时启动多个任务来查看效果

分布式方式使用数据库,任务相关的信息存入到数据库中,所有的节点连接到同一个数据库,能够进行共享数据,实现任务不重复跑不漏跑

 其中持久化时:

如果需要使用单个方法设置定时任务,是不能持久化的:
 Spring从2.0.2开始便不再支持Quartz。具体表现在Quartz+Spring把Quartz的Task实例化进入数据库时,会产生:Serializable的错误:
Unable to serialize JobDataMap for insertion into database because the value of property 'methodInvoker' is not serializable

所以需要自己定义一个类实现MethodInvoker的逻辑
使用JobDetail的jobClass和JobDataAsMap属性定义一个类来实现,思路是这样,但我没成功.......所以就不放代码了

原文地址:https://www.cnblogs.com/huahualove/p/14109517.html