背景
最近要做一个定时的邮件发送的功能,定期在周一上午10点发送。
具体实现与测试
实现和测试的时候用的是
1 |
意为每隔60秒执行一遍任务,用以上表达式,一切OK,轻松加愉快的敲完了实现发送的代码,BingGo,测试通过后。最后需要上生产了,其他代码全没改,就改成cron
,如下:
1 |
问题来了
将表达式改成了@Scheduled(cron = "0 0 10 * * 2")
后,坐等生产上定时发送,叮叮~~到了10点过1分的时候,用户写邮件问我,嗨,小王(化名)在吗?我们没有收到邮件,可以看一下有神马问题吗?我一下就惊了,立马坐起来了,因为我没有在本地测试过@Scheduled(cron = "0 0 10 * * 2")
。
重新测试
1 |
我接到问题的时候是10点1分,于是我在本地设置了10点3分,坐等任务触发,d=====( ̄▽ ̄*)b,时间到了,可是没有进入我的断点。内心有点崩溃,找了各种cron在线表达式验证,如下:
今天是8月1日,而现在的时间超过了10点,今天也是星期一,故没有今天的时间,但可以从预测推断出,今天上午应该会执行。最后的数字2代表一周的第几天,礼拜天是第1天,所以周一是第2天,故我这写的2,在线检查的网站也肯定了我的写法。
结论
到此,我有点抓狂,不知道为什么死活不会进我的断点。于是疯狂的面向搜索引擎搜索,直到我看到了这个:
突然,仿佛看到了一束光,我的天呐,原来这俩玩意的起点不一样,想骂街了都。
Linux
的crontab
的day of week
是从周天算起,但是spring scheduled tasks
却是从周一算起,到此基本知道为啥会进入不了我的断点了,因为按照表达式@Scheduled(cron = "0 3 10 * * 2")
的写法,我需要在明天也就是周二debug的时候才能进断点。
缘由
但这还是不够,我想知道为什么spring scheduled
会整这个反人类的设计,于是我想到了去看关于这块实现的源码,于是我找到这个:
https://github.com/spring-projects/spring-framework/blob/6e4551131dddffecd7adc00d96e3ecddd4c4911c/spring-context/src/main/java/org/springframework/scheduling/support/QuartzCronField.javaDayOfWeek
来自java.time.DayOfWeek
是一个枚举类型
在网上搜索发现:
https://docs.oracle.com/javase/8/docs/api/java/time/DayOfWeek.html
在这里有描述:
In addition to the textual enum name, each day-of-week has an int value. The int value follows the ISO-8601 standard, from 1 (Monday) to 7 (Sunday). It is recommended that applications use the enum rather than the int value to ensure code clarity.
This enum provides access to the localized textual form of the day-of-week. Some locales also assign different numeric values to the days, declaring Sunday to have the value 1, however this class provides no support for this.
从这里找到源头了,1代表Monday,并且也说明了在有些地方会用1代表周天,但是在DayOfWeek这个类里,并不支持这种说法。
至此,我把@Scheduled(cron = "0 0 10 * * 2")
换成了@Scheduled(cron = "0 0 10 * * 1")
,就大功告成了。
如果您喜欢此博客或发现它对您有用,则欢迎对此发表评论。 也欢迎您共享此博客,以便更多人可以参与。 如果博客中使用的图像侵犯了您的版权,请与作者联系以将其删除。 谢谢 !