cron表达式学习和spring的@Scheduled使用
在学到java的定时任务开发时用到spring的定时器,会涉及到cron表达式,这里参考其他资料,总结出cron表达式的规则。
cron表达式其实就是一个字符串,有2种语法格式。
第一种是以6个空格隔开分7个域,其格式为Seconds Minutes Hours DayofMonth Month DayofWeek Year(秒 分 时 月中的第几天 月 一周的第几天 年)
第二种是字符串以5个空格隔开分为6个域,其格式为Seconds Minutes Hours DayofMonth Month DayofWeek(秒 分 时 月中的第几天 月 一周的第几天)
每一个域代表一个含义,其取值范围如下:
字段 | 含义 | 允许值 | 范围 | 可能出现的特殊字符 |
Seconds | 秒 | 整数 | 0-59 | ", - * /"四个字符 |
Minutes | 分 | 整数 | 0-59 | ", - * /"四个字符 |
Hours | 小时 | 整数 | 0-23 | ", - * /"四个字符 |
DayofMonth | 日期 | 整数 | 0-31(受月份限制) | ", - * / ? L W C"八个字符 |
Month | 月份 |
整数或指定字符 |
1-12或JAN-DEc |
", - * /"四个字符 |
DayofWeek | 星期 | 整数或指定字符 | 1-7或SUN-SAT (1表示星期天,2表示星期一, 依次类推) |
", - * / ? L C #"四个字符 |
Year(可选,留空) | 年 | 整数 | 1970-2099 | ", - * /"四个字符 |
各个特殊字符的含义:
(1)*:表示匹配该域的任意值,假如在Seconds域使用*, 即表示每秒执行一次。
(2)?:只能用在DayofMonth和DayofWeek两个域。它也匹配域的任意值,但实际不会。因为DayofMonth和 DayofWeek会相互影响。例如想在每月的20日执行调度,不管20日到底是星期几,则只能使用如下写法: 13 13 15 20 * ?, 其中最后一位只能用?,而不能使用*,如果使用*表示不管星期几都会执行,实际上并不是这样。——这个有歧义,待验证
(3)-:表示范围,例如在Seconds域使用5-10,表示从5分到10分钟每秒执行一次
(4)/:表示起始时间和每多少时间,例如在Seconds域使用5/10,则意味着第5秒钟执行一次,以后每10秒执行一次,也就是说在第5秒、第10秒、第15秒……执行。
注意:这个有歧义,每n秒和每隔n秒是不同意思的,但很多资料没区分,每隔n秒相当于每(n+1)秒,如每隔4秒相当于每5秒,如果是从0开始,就是第0秒、第5秒、第10秒等等。
(5),:表示列出枚举值值。例如:在Seconds域使用5,15,则意味着在第5秒和第15秒执行一次。
(6)L:表示最后,只能出现在DayofWeek和DayofMonth域,如果在DayofWeek域使用5L,意味着在最后的一个星期四触发。
(7)W: 表示有效工作日(周一到周五),只能出现在DayofMonth域,系统将在离指定日期的最近的有效工作日触发事件。例如:在 DayofMonth使用5W,如果5日是星期六,则将在最近的工作日:星期五,即4日触发。如果5日是星期天,则在6日(周一)触发;如果5日在星期一 到星期五中的一天,则就在5日触发。另外一点,W的最近寻找不会跨过月份
(8)LW:这两个字符可以连用,表示在某个月最后一个工作日,即最后一个星期五。
(9)#:用于确定每个月第几个星期几,只能出现在DayofMonth域。例如在4#2,表示某月的第二个星期三。
cron表达式范例:
每10秒执行一次:*/10 * * * * ?
每分钟执行一次:0 */1 * * * ?
每小时统计一次:0 0 */1 * * ?
每天23点59分清理一次:0 59 23 * * ?
spring中Schedule定时器的使用
spring-task.xml配置文件如下(xmlns里带有多余的配置):
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?xml version="1.0" encoding="UTF-8"?> <!-- xml 的头部 --> <!-- 注意 .xsd 文件尽量不要带版本号 --> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd"> <task:annotation-driven /> <!-- 定时器开关--> <!-- 这个bean对应的class是你编写了定时任务的java文件 --> <bean id="schedule" class="com.ccb.ic.mytask.Mytask"></bean> </beans>
java测试实现代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.ccb.ic.mytask; import java.util.Date; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @Component //import org.springframework.stereotype.Component; public class Mytask { public static void main(String[] args) { Mytask bean = new Mytask(); ApplicationContext context = new ClassPathXmlApplicationContext( "com/ccb/ic/mytask/spring-task.xml"); System.out.println("1"); bean.myTest(); System.out.println("================="); } @Scheduled(cron="*/5 * * * * ? ") //每5秒执行一次 public void myTest(){ long tms = System.currentTimeMillis(); Date date = new Date(tms); long h = date.getHours(); long m = date.getMinutes(); long s = date.getSeconds(); String res = h + ":" + m + ":" + s; System.out.println(res); } }
这两个文件放在maven工创建的同一个包下基本可以实现测试了。