Spring定时器的两种实现方式

有两种流行的Spring定时器配置:Java的Timer类和OpenSymphony的Quartz。

1、Java Timer定时器

1. 首先创任务TimeTaskTest,该类继承java.util.TimerTask,并实现run方法

import java.util.TimerTask;
/*
 * TimerTask实现了Runnable接口,由 Timer 安排为一次执行或重复执行的任务。
 */
public class TimeTaskTest extends TimerTask {
	@Override
	public void run() {
		System.out.println("start");
	}
}
2. Spring的TimerFactoryBean负责启动定时任务

	<!-- 定义任务的bean -->
	<bean id="timeTaskTest" class="com.zhu.TimeTaskTest"></bean>

	<!-- TimerFactoryBean负责启动定时任务 -->
	<bean id="timerFactory" class="org.springframework.scheduling.timer.TimerFactoryBean">
		<!-- scheduledTimerTasks里显示一个需要启动的定时器任务的列表 -->
		<property name="scheduledTimerTasks">
		   <list>
		   		<ref bean="scheduleTask"/>
		   </list>
		</property>
	</bean>

	<bean id="scheduleTask" class="org.springframework.scheduling.timer.ScheduledTimerTask">
		<!-- 引用执行的任务been -->
		<property name="timerTask" ref="timeTaskTest"/>
		<!-- 延迟1000毫秒执行 -->
		<property name="delay" value="1000"/>
		<!-- 固定频率每2000毫秒执行一次 -->
		<property name="period" value="2000"/>
	</bean>

3.测试方式

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
	public static void main(String[] args) {
		ApplicationContext ac = new ClassPathXmlApplicationContext("application_bean.xml");
	}
}

这个任务我们只能规定每隔多长时间运行一次,无法精确到某时启动

2、Quartz定时器
      Quartz的org.quartz.Trigger类描述了何时及以怎样的频度运行一个Quartz工作。Spring提供了两个触发器SimpleTriggerBean和CronTriggerBean(SimpleTriggerBean与scheduledTimerTasks类似,指定工作的执行频度,模仿scheduledTimerTasks配置)这里只介绍 CronTriggerBean:

1.编写一个简单的JAVA类,和普通的类没有区别,并配置到Spring配置文件上

/**
 * 普通Java类
 */
public class SimpleTest {
	/**
	 * 需要每隔5秒执行一次的方法
	 */
	public void test() {
		System.out.println("start");
	}
}

2.在spring配置文件中定义定时器

</pre><pre>

	<!-- 定义要定期执行的目标bean -->
	<bean id="simpleTest" class="com.zhu.SimpleTest" />

	<!-- 使用MethodInvokingJobDetailFactoryBean建立任务 -->
	<bean id="sendByPayDetail"
		class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
		<property name="targetObject" ref="simpleTest" />
		<property name="targetMethod" value="test" />
		<property name="concurrent" value="false" />
	</bean>
	
	<!-- 使用CronTriggerBean建立规则,调度任务 -->
	<bean id="myTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
		<property name="jobDetail">
			<ref bean="sendByPayDetail" />
		</property>
		<!-- 每隔5秒执行一次 -->
		<property name="cronExpression">
			<value>0/5 * * * * ?</value>
		</property>
	</bean>
	
	<!-- 使用SchedulerFactoryBean包装任务 -->
	<bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> 
		<!-- triggers属性接受一组触发器 -->
		<property name="triggers">
			<list>
				<ref bean="myTrigger" />
			</list>
		</property>
		<property name="autoStartup" value="true"/>
        <property name="schedulerName" value="cronScheduler"/>
	</bean>

参数说明:

MethodInvokingJobDetailFactoryBean

targetObject : 目标对象,即需要定时执行的POJO

targetMethod : 目标方法,即需要定时执行的POJO方法  

concurrent : 默认情况下,Quartz Jobs是无状态的,可能导致jobs之间互相的影响,如果你为相同的JobDetail指定两个Trigger,很可能当第一个job完成之前,第二个job就开始了。如果Jobdetail实现了Stateful接口,就不会发生这样的事情。第二个job将不会在第一个job完成之前开始。为了使得jobs不并发运行,设置concurrent标记为false

CronTriggerBean

jobDetail : 任务详情,即所需要调度的任务

cronExpression : 调用规则,即什么时候调用 

SchedulerFactoryBeantriggers :  触发器,调用哪些任务autoStartup : 是否自动启动,该Bean被初始化后是否自动启动定时任务。Set whether to automatically start the scheduler after initialization. schedulerName : 给这个计划设定一个名称。Set the name of the Scheduler to fetch from the SchedulerFactory. 

3.测试方法

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
	public static void main(String[] args){
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext_context.xml");
	}
}

说明:属性cronExpression指明何时触发,最神秘就是cron表达式:

      Linux系统的计划任务通常有cron来承担。一个cron表达式有至少6个(也可能7个)有空格分隔的时间元素。从左到右:
     1 秒    2 分    3 小时    4 月份中的日期(1-31)   5 月份(1-12或JAN-DEC)    6 星期中的日期(1-7或SUN-SAT)  7 年份(1970-2099) 
      每个元素都显示的规定一个值(如6),一个区间(9-12),一个列表(9,11,13),一个通配符(*)。

      因为4和6这两个元素是互斥的,因此应该通过设置一个问号(?)来表明不想设置的那个字段,“/” 如果值组合就表示重复次数(10/6表示每10秒重复6次)。

具体时间设定可参考 
"0/10 * * * * ?" 每10秒触发 
"0 0 12 * * ?" 每天中午12点触发 
"0 15 10 ? * *" 每天上午10:15触发 
"0 15 10 * * ?" 每天上午10:15触发 
"0 15 10 * * ? *" 每天上午10:15触发 
"0 15 10 * * ? 2005" 2005年的每天上午10:15触发 
"0 * 14 * * ?" 在每天下午2点到下午2:59期间的每1分钟触发 
"0 0/5 14 * * ?" 在每天下午2点到下午2:55期间的每5分钟触发 
"0 0/5 14,18 * * ?" 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发 
"0 0-5 14 * * ?" 在每天下午2点到下午2:05期间的每1分钟触发 
"0 10,44 14 ? 3 WED" 每年三月的星期三的下午2:10和2:44触发 
"0 15 10 ? * MON-FRI" 周一至周五的上午10:15触发 
"0 15 10 15 * ?" 每月15日上午10:15触发 
"0 15 10 L * ?" 每月最后一日的上午10:15触发 
"0 15 10 ? * 6L" 每月的最后一个星期五上午10:15触发 
"0 15 10 ? * 6L 2002-2005" 2002年至2005年的每月的最后一个星期五上午10:15触发 
"0 15 10 ? * 6#3" 每月的第三个星期五上午10:15触发 
每隔5秒执行一次:*/5 * * * * ? 
每隔1分钟执行一次:0 */1 * * * ? 
每天23点执行一次:0 0 23 * * ? 
每天凌晨1点执行一次:0 0 1 * * ? 
每月1号凌晨1点执行一次:0 0 1 1 * ? 
每月最后一天23点执行一次:0 0 23 L * ? 
每周星期天凌晨1点实行一次:0 0 1 ? * L 
在26分、29分、33分执行一次:0 26,29,33 * * * ? 
每天的0点、13点、18点、21点都执行一次:0 0 0,13,18,21 * * ?


注:实现spring触发器需要加入相关quartz的jar包


CronTrigger说明
     如果需要复杂的任务计划调度,像日历样式的任务,而不是简单的时间间隔调度,需要使用CronTrigger,SimpleTrigger满足不了需求。
用CronTrigger,你可以定义任务计划像“每周五的中午”,或“每个工作日的早上9:30”,甚至可以定义“1月份的每周一、周三、周五早上9:00至10:00,每5分钟一次”。
      虽然如此,像SimpleTrigger一样,CronTrigger仍有startTime属性定义计划的开始时间,endTime(可选)属性定义计划的中止时间。


Cron Expressions
      Cron-Expressions是用来配置CronTrigger实例。Cron-Expressions是由七段子表达式组成的字符串,描述各个细节计划。这些子字符串由空格分开,每个子字符串表示一个域,分别为:
1 秒
2 分
3 时
4 几号
5 月份
6 星期几
7 年(可选域)
例如:"0 0 12 ? * WED"-表示每周三12:00:00pm"。其中每个独立的子表达式都可以用范围或者列表表示。例如:
前例的”WED“也可以写成:
"MON-FRI"(范围表示)
"MON,WED,FRI"(列表表示)
"MON-WED,SAT"(范围加列表)
通配符(*)可以用来表示某个子表达式域的每一个可能的值。因此,“*”号用在月份里,表示每月。用在星期几里,表示一周中的每天。
每个子表达式域都有一组有效的值,这些值都是显然意见的。例:用0-59表示秒和分,用0到23表示小时。几号用0-31中的任何值,但是要小心每月的天数。月份指定的值应该是0至11,也可以用字符串 JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV和DEC表示。星期几用1到7表示(1=星期天),或用英文字符表示:SUN,MON,TUE,WED,THU,FRI和SAT。
字符“/”用来表示增量的值。例如:如果用“0/15”表示分,就表示从一个小时的0分开始,在这小时内每隔15分钟一次。如果用"3/20"表示分,则表示从一个小时的3分开始,在这小时内每隔20分钟一次。也可以用“3,23,43”表示。注意"*/35"并不是表示每35分钟,而是表示从一个小时的0分开始,每隔35分钟一次,相当于"0,35"。
“?"号允许用在几号和星期几的子字符串域中,用来说明没有指定值。
“L”字符允许用在几号和星期几域中,是"last"的缩写。“L”用在几号里意思是这个月的最后一天,如果是1月就指31号,如果是闰年的2月就是28号。如果用在星期几里,他就是表示“7”或者“SAT”(星期六)。但是如果L用在一个值的后面联合表示星期几域,就表示“这个月最后一个星期几”。例如:“6L”或“FRIL”表示这个月的最后一个星期五。同样也可以用一个偏移变量表示距离某个月最后一天的天数。例如:“L-3”表示某月最后一天的倒数第三天。但用“L“字符时,不要将“L”用在列表或范围中,那样你会混淆或者获得不是预期的结果。
“W”用来指定某一号最近的工作日(星期一至五),例如:“15W”放在几号里,表示这个月15号最近的一个工作日。
“#”号用指定某月第几个工作日,例如:“6#3”或“FRI#3”放在星期几域中,表示这个月第三个星期五。
下面是一些表达式的样例,你可以从JavaDoc中找到更多的例子。

Cron Expressions示例
例1-一个表达式表示每5分钟。
"0 0/5 * * * ?"
例2——表示每分钟的10秒后,每5钟一次(如:10:00:10 am,10:05:10 am,等等)
"10 0/5 * * * ?"
例3——表示运行在每个星期三,星期五的10:30,11:30,12:30 and 13:30
"0 30 10-13 ? * WED,FRI"
例4——表示每月的5号和20号的早8点至早10点每30分钟一次。
"0 0/30 8-10 5,20 * ?"
注意,有些计划调度需求如果用一个触发器会很复杂,例如:“早9:00至10:00每5分钟,下午1:00至10:00每20分钟”,这种情况下可以是单的创建两个触发器同时运行一个JOB

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring中使用注解方式实现定时任务非常方便。以下是实现步骤: 1. 添加依赖:首先,确保在你的项目中添加了Spring的相关依赖,包括spring-context和spring-tasks。 2. 启用定时任务:在Spring的配置文件中,添加`<task:annotation-driven />`标签来启用注解驱动的定时任务。 3. 创建定时任务类:创建一个带有定时任务方法的类。在该方法上添加`@Scheduled`注解来标识该方法为定时任务。 ```java import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @Component public class MyScheduledTasks { @Scheduled(fixedRate = 5000) // 定义任务执行的时间间隔,这里是每5秒执行一次 public void doSomething() { // 执行定时任务的逻辑代码 System.out.println("定时任务执行中..."); } } ``` 在上面的例子中,使用`@Scheduled`注解来定义定时任务的执行时间间隔。可以根据需求设置不同的属性,如`fixedRate`、`cron`等。 4. 注解配置扫描:在Spring的配置文件中添加`@ComponentScan`注解来扫描定时任务类。 ```xml <context:component-scan base-package="com.example.tasks" /> ``` 这里的`com.example.tasks`是你的定时任务类所在的包路径。 5. 运行应用程序:启动你的Spring应用程序,定时任务将会自动被调度执行。 以上是使用注解方式实现Spring定时任务的基本步骤。你可以根据具体的需求,使用不同的注解属性来定义更复杂的定时任务逻辑。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值