使用spring+quartz配置多个定时任务(包括项目启动先执行一次,之后再间隔时间执行)
1.依赖
<!-- quartz --> <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.3.4.RELEASE</version> </dependency>
需要引入的jar包, 这里是采用maven的dependency依赖; 如果没有使用maven, 可以对照着上面的jar包截图一一进行下载. 这里唯一需要注意的就是, 如果使用spring 3.1以下的版本, quartz就需要相应的2.0以下版本, 否则会导致 org.springframework.beans.factory.CannotLoadBeanClassException: Error loading class [org.springframework.scheduling.quartz.CronTriggerBean] for bean with name 'cronTrigger_1' defined in file [E:\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\git-common\WEB-INF\classes\applicationContext.xml]: problem with class file or dependent class; nested exception isjava.lang.IncompatibleClassChangeError: class org.springframework.scheduling.quartz.CronTriggerBean has interface org.quartz.CronTrigger as super class 错误.
后续: 后来使用了spring 4.0.5.RELEASE版本+quartz 2.2.1版本, 还是报出了以上错误, 将quartz降低为1.8.6版本后, 问题消失...
2.举例代码
/** *要定时执行的任务一 * **/ package com.quartz.demo; import java.util.Date; public class Job1Demo { public void sayHello() { System.out.println(new Date() + " -> Hello, 我是任务 1"); } }
/** *要定时执行的任务一 * **/ package com.quartz.demo; import java.util.Date; public class Job2Demo { public void sayHello() { System.out.println(new Date() + " -> Hello, 我是任务 2"); } }
3.配置定时器applicationContext-quartz.xml
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd "> <!-- 将自定义job交给spring(将类注入Spring管理Bean) --> <bean name="job1" class="com.quartz.demo.Job1Demo"/> <!-- 配置JobDetail --> <bean id="SpringQtzJobMethod_1" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="concurrent" value="false" /> <!--false表示等上一个任务执行完后再开启新的任务(默认是true) --> <property name="targetObject"> <ref bean="job1" /> </property> <property name="targetMethod"> <!-- 要执行的方法名称 --> <value>sayHello</value> <!-- 要执行的方法名称 --> </property> </bean> <!-- 配置调度触发器 --> <bean id="cronTriggerFactoryBean_1" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean "> <property name="jobDetail" ref="SpringQtzJobMethod_1"></property> <!-- 每5秒执行一次 --> <property name="cronExpression" value="0/5 * * * * ?"></property> </bean> <!-- 将自定义job交给spring(将类注入Spring管理Bean) --> <bean name="job2" class="com.quartz.demo.Job2Demo"/> <!-- 配置JobDetail --> <bean id="SpringQtzJobMethod_2" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="concurrent" value="false" /> <!--false表示等上一个任务执行完后再开启新的任务(默认是true) --> <property name="targetObject"> <ref bean="job2" /> </property> <property name="targetMethod"> <!-- 要执行的方法名称 --> <value>sayHello</value> <!-- 要执行的方法名称 --> </property> </bean> <!-- 配置调度触发器 --> <bean id="cronTriggerFactoryBean_2" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean "> <property name="jobDetail" ref="SpringQtzJobMethod_2"></property> <!-- 每5秒执行一次 --> <property name="cronExpression" value="0/5 * * * * ?"></property> </bean> <!-- 项目启动就先执行一次,再按照间隔时间重复执行(SimpleTrigger) <bean id="simpleTriggerFactoryBean" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean"> <property name="jobDetail" ref="SpringQtzJobMethod_2" /> <property name="startDelay" value="2000" /> 启动延迟 单位/毫秒 <property name="repeatInterval" value="20000" /> 间隔时间 <property name="repeatCount" value="-1" /> 重复次数(-1:无数次;0:一次.....) </bean> --> <!-- 配置调度工厂 --> <bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <!-- 添加触发器 --> <property name="triggers"> <list> <ref bean="cronTriggerFactoryBean_1"/> <ref bean="cronTriggerFactoryBean_2"/> <!-- <ref bean="simpleTriggerFactoryBean"/> --> </list> </property> </bean> </beans>
4.web.xml加载定时配置文件
<display-name>Archetype Created Web Application</display-name> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/applicationContext-*.xml</param-value> </context-param> <!-- Spring 容器启动监听器 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
5.时间计算cron表达式
一个cron表达式有至少6个(也可能7个)有空格分隔的时间元素。
按顺序依次为
1 秒(0~59)
2 分钟(0~59)
3 小时(0~23)
4 天(0~31)
5 月(0~11)
6 星期(1~7 1为SUN-依次为SUN,MON,TUE,WED,THU,FRI,SAT)
7.年份(1970-2099)
在线时间计算cron表达式:http://cron.qqe2.com/
6.作者实际运用在项目中遇到的问题:
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 异常
解决方法:
这个是因为spring容器里面有两个类型一样的bean,但是spring不知道加载哪一个,需要你手动指定一个默认的加载(会优先加载@Primary注解的类型) 用@Primary在标识在Class上面 。
参考文章:
https://www.jianshu.com/p/d0edb298e891
https://www.cnblogs.com/qlqwjy/p/8721963.html