|
| 1 | + |
| 2 | + |
| 3 | +<header> |
| 4 | + |
| 5 | +# Spring Boot调度 |
| 6 | + |
| 7 | +以下内容仅是站长或网友个人学习笔记、总结和研究收藏。不保证正确性,因使用而带来的风险与本站无关! |
| 8 | + |
| 9 | +</header> |
| 10 | + |
| 11 | + |
| 12 | + |
| 13 | +<script>( adsbygoogle = window.adsbygoogle || []).push({});</script> |
| 14 | + |
| 15 | + |
| 16 | + |
| 17 | +调度是执行特定时间段的任务的过程。Spring Boot为在Spring应用程序上编写调度程序提供了很好的支持。 |
| 18 | + |
| 19 | +## Java Cron表达式 |
| 20 | + |
| 21 | +Java Cron表达式用于配置CronTrigger的实例,它是`org.quartz.Trigger`的子类。 有关Java cron表达式的更多信息,请参阅此链接 - |
| 22 | + |
| 23 | +* [https://docs.oracle.com/cd/E12058_01/doc/doc.1014/e12030/cron_expressions.html](https://docs.oracle.com/cd/E12058_01/doc/doc.1014/e12030/cron_expressions.html) |
| 24 | + |
| 25 | +`[@EnableScheduling](https://github.com/EnableScheduling "@EnableScheduling")`注解用于为应用程序启用调度程序。将此批注添加到主Spring Boot应用程序类文件中。 |
| 26 | + |
| 27 | +``` |
| 28 | +@SpringBootApplication |
| 29 | +@EnableScheduling |
| 30 | +
|
| 31 | +public class DemoApplication { |
| 32 | + public static void main(String[] args) { |
| 33 | + SpringApplication.run(DemoApplication.class, args); |
| 34 | + } |
| 35 | +} |
| 36 | +
|
| 37 | +``` |
| 38 | + |
| 39 | +`[@Scheduled](https://github.com/Scheduled "@Scheduled")`注解用于在特定时间段内触发调度程序。 |
| 40 | + |
| 41 | +``` |
| 42 | +@Scheduled(cron = "0 * 9 * * ?") |
| 43 | +public void cronJobSch() throws Exception { |
| 44 | +} |
| 45 | +
|
| 46 | +``` |
| 47 | + |
| 48 | +以下是一个示例代码,演示如何在每天上午9:00开始到每天上午9:59结束执行任务。 |
| 49 | + |
| 50 | +``` |
| 51 | +package com.yiibai.demo.scheduler; |
| 52 | +
|
| 53 | +import java.text.SimpleDateFormat; |
| 54 | +import java.util.Date; |
| 55 | +import org.springframework.scheduling.annotation.Scheduled; |
| 56 | +import org.springframework.stereotype.Component; |
| 57 | +
|
| 58 | +@Component |
| 59 | +public class Scheduler { |
| 60 | + @Scheduled(cron = "0 * 9 * * ?") |
| 61 | + public void cronJobSch() { |
| 62 | + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); |
| 63 | + Date now = new Date(); |
| 64 | + String strDate = sdf.format(now); |
| 65 | + System.out.println("Java cron job expression:: " + strDate); |
| 66 | + } |
| 67 | +} |
| 68 | +
|
| 69 | +``` |
| 70 | + |
| 71 | +以下屏幕截图显示了应用程序如何在`09:03:23`启动,并且从那时起每隔一分钟执行一次cron作业调度程序任务。 |
| 72 | + |
| 73 | + |
| 74 | + |
| 75 | +## 固定速率 |
| 76 | + |
| 77 | +固定速率调度程序用于在特定时间执行任务。它不等待前一个任务的完成。 值是以毫秒为单位。 示例代码显示在此处 - |
| 78 | + |
| 79 | +``` |
| 80 | +@Scheduled(fixedRate = 1000) |
| 81 | +public void fixedRateSch() { |
| 82 | +} |
| 83 | +
|
| 84 | +``` |
| 85 | + |
| 86 | +此处显示了应用程序启动时每秒执行任务的示例代码 - |
| 87 | + |
| 88 | +``` |
| 89 | +package com.yiibai.demo.scheduler; |
| 90 | +
|
| 91 | +import java.text.SimpleDateFormat; |
| 92 | +import java.util.Date; |
| 93 | +import org.springframework.scheduling.annotation.Scheduled; |
| 94 | +import org.springframework.stereotype.Component; |
| 95 | +
|
| 96 | +@Component |
| 97 | +public class Scheduler { |
| 98 | + @Scheduled(fixedRate = 1000) |
| 99 | + public void fixedRateSch() { |
| 100 | + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); |
| 101 | +
|
| 102 | + Date now = new Date(); |
| 103 | + String strDate = sdf.format(now); |
| 104 | + System.out.println("Fixed Rate scheduler:: " + strDate); |
| 105 | + } |
| 106 | +} |
| 107 | +
|
| 108 | +``` |
| 109 | + |
| 110 | +请注意以下屏幕截图,其中显示了在`09:12:00`启动的应用程序,之后每隔一个固定速率调度程序执行任务。 |
| 111 | + |
| 112 | + |
| 113 | + |
| 114 | +## 固定延迟 |
| 115 | + |
| 116 | +固定延迟调度程序用于在特定时间执行任务。 它应该等待上一个任务完成。 值应以毫秒为单位。 此处显示示例代码 - |
| 117 | + |
| 118 | +``` |
| 119 | +@Scheduled(fixedDelay = 1000, initialDelay = 1000) |
| 120 | +public void fixedDelaySch() { |
| 121 | +} |
| 122 | +
|
| 123 | +``` |
| 124 | + |
| 125 | +这里,`initialDelay`是在初始延迟值之后第一次执行任务的时间。 |
| 126 | + |
| 127 | +从应用程序启动完成`3`秒后每秒执行一次任务的示例如下所示 - |
| 128 | + |
| 129 | +``` |
| 130 | +package com.yiibai.demo.scheduler; |
| 131 | +
|
| 132 | +import java.text.SimpleDateFormat; |
| 133 | +import java.util.Date; |
| 134 | +import org.springframework.scheduling.annotation.Scheduled; |
| 135 | +import org.springframework.stereotype.Component; |
| 136 | +
|
| 137 | +@Component |
| 138 | +public class Scheduler { |
| 139 | + @Scheduled(fixedDelay = 1000, initialDelay = 3000) |
| 140 | + public void fixedDelaySch() { |
| 141 | + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); |
| 142 | + Date now = new Date(); |
| 143 | + String strDate = sdf.format(now); |
| 144 | + System.out.println("Fixed Delay scheduler:: " + strDate); |
| 145 | + } |
| 146 | +} |
| 147 | +
|
| 148 | +``` |
| 149 | + |
| 150 | +执行上面代码后,它会显示在`09:18:39`开始的应用程序,每`3`秒后,固定延迟计划程序任务(每秒执行一次)。 |
| 151 | + |
| 152 | + |
| 153 | + |
| 154 | + |
| 155 | + |
| 156 | +//更多请阅读:https://www.yiibai.com/spring-boot/spring_boot_scheduling.html |
| 157 | + |
| 158 | +@EnableAsync 注解 |
| 159 | +要使用 @Async,首先需要使用 @EnableAsync 注解开启 Spring Boot 中的异步特性。 |
| 160 | + |
| 161 | +@Configuration |
| 162 | +@EnableAsync |
| 163 | +public class AppConfig { |
| 164 | +} |
| 165 | +更详细的配置说明,可以参考:AsyncConfigurer(opens new window) |
| 166 | + |
| 167 | +#@Async 注解 |
| 168 | +#支持的用法 |
| 169 | +(1)无入参无返回值方法 |
| 170 | + |
| 171 | +您可以用 @Async 注解修饰方法,这表明这个方法是异步方式调用。换句话说,程序在调用此方法时会立即返回,而方法的实际执行发生在已提交给 Spring TaskExecutor 的任务中。在最简单的情况下,您可以将注解应用于返回 void 的方法,如以下示例所示: |
| 172 | + |
| 173 | +@Async |
| 174 | +void doSomething() { |
| 175 | +// this will be executed asynchronously |
| 176 | +} |
| 177 | +(2)有入参无返回值方法 |
| 178 | + |
| 179 | +与使用 @Scheduled 注释注释的方法不同,这些方法可以指定参数,因为它们在运行时由调用者以“正常”方式调用,而不是由容器管理的调度任务调用。例如,以下代码是 @Async 注解的合法应用: |
| 180 | + |
| 181 | +@Async |
| 182 | +void doSomething(String s) { |
| 183 | +// this will be executed asynchronously |
| 184 | +} |
| 185 | +(3)有入参有返回值方法 |
| 186 | + |
| 187 | +甚至可以异步调用返回值的方法。但是,这些方法需要具有 Future 类型的返回值。这仍然提供了异步执行的好处,以便调用者可以在调用 Future 上的 get() 之前执行其他任务。以下示例显示如何在返回值的方法上使用@Async: |
| 188 | + |
| 189 | +@Async |
| 190 | +Future<String> returnSomething(int i) { |
| 191 | +// this will be executed asynchronously |
| 192 | +} |
| 193 | +#不支持的用法 |
| 194 | +@Async 不能与生命周期回调一起使用,例如 @PostConstruct。 |
| 195 | + |
| 196 | +要异步初始化 Spring bean,必须使用单独的初始化 Spring bean,然后在目标上调用 @Async 带注释的方法,如以下示例所示: |
| 197 | + |
| 198 | +public class SampleBeanImpl implements SampleBean { |
| 199 | + |
| 200 | + @Async |
| 201 | + void doSomething() { |
| 202 | + // ... |
| 203 | + } |
| 204 | + |
| 205 | +} |
| 206 | + |
| 207 | +public class SampleBeanInitializer { |
| 208 | + |
| 209 | + private final SampleBean bean; |
| 210 | + |
| 211 | + public SampleBeanInitializer(SampleBean bean) { |
| 212 | + this.bean = bean; |
| 213 | + } |
| 214 | + |
| 215 | + @PostConstruct |
| 216 | + public void initialize() { |
| 217 | + bean.doSomething(); |
| 218 | + } |
| 219 | + |
| 220 | +} |
| 221 | +#明确指定执行器 |
| 222 | +默认情况下,在方法上指定 @Async 时,使用的执行器是在启用异步支持时配置的执行器,即如果使用 XML 或 AsyncConfigurer 实现(如果有),则为 annotation-driven 元素。但是,如果需要指示在执行给定方法时应使用默认值以外的执行器,则可以使用 @Async 注解的 value 属性。以下示例显示了如何执行此操作: |
| 223 | + |
| 224 | +@Async("otherExecutor") |
| 225 | +void doSomething(String s) { |
| 226 | +// this will be executed asynchronously by "otherExecutor" |
| 227 | +} |
| 228 | +在这种情况下,“otherExecutor”可以是 Spring 容器中任何 Executor bean 的名称,也可以是与任何 Executor 关联的限定符的名称(例如,使用 <qualifier> 元素或 Spring 的 @Qualifier 注释指定) )。 |
| 229 | + |
| 230 | +#管理 @Async 的异常 |
| 231 | +当 @Async 方法的返回值类型为 Future 型时,很容易管理在方法执行期间抛出的异常,因为在调用 get 结果时会抛出此异常。但是,对于返回值类型为 void 型的方法,异常不会被捕获且无法传输。您可以提供 AsyncUncaughtExceptionHandler 来处理此类异常。以下示例显示了如何执行此操作: |
| 232 | + |
| 233 | +public class MyAsyncUncaughtExceptionHandler implements AsyncUncaughtExceptionHandler { |
| 234 | + |
| 235 | + @Override |
| 236 | + public void handleUncaughtException(Throwable ex, Method method, Object... params) { |
| 237 | + // handle exception |
| 238 | + } |
| 239 | +} |
| 240 | +默认情况下,仅记录异常。您可以使用 AsyncConfigurer 或 <task:annotation-driven /> XML 元素定义自定义 AsyncUncaughtExceptionHandler。 |
0 commit comments