您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關SpringBoot定時任務如何在Java中使用,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。
一、SpringBoot使用Schedule
核心代碼:
@Component public class ScheduleTask { private Logger logger = LoggerFactory.getLogger(ScheduleTask.class); @Scheduled(cron = "0/1 * * * * ? ") public void one() { logger.info("one:" + new Date()); } @Scheduled(cron = "0/1 * * * * ? ") public void two() { logger.info("two:" + new Date()); } @Scheduled(cron = "0/1 * * * * ? ") public void three() { logger.info("three:" + new Date()); } }
運行效果如下:
除此之外還可以這樣實現,核心代碼:
@PropertySource(value = { "classpath:task.properties", }, encoding = "utf-8") @Component("scheduleTask") public class ScheduleTask implements SchedulingConfigurer { @Value("${TEST_JOB_TASK_CRON}") private String cron; @Override public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) { scheduledTaskRegistrar.addTriggerTask(new Runnable() { @Override public void run() { System.out.println("執行任務:" + DateUtil.date()); } }, new Trigger() { @Override public Date nextExecutionTime(TriggerContext triggerContext) { return new CronTrigger(cron).nextExecutionTime(triggerContext); } }); } public void setCron(String cron) { this.cron = cron; } }
有朋友或許很疑惑,為什么要寫這么一大堆,這個與前面的代碼又有何區別呢?
區別是多線程并行。其實多線程并行也可以不用這么寫,只需寫一段核心配置類代碼即可。
定時任務多線程配置類:
@Configuration public class ScheduleConfig implements SchedulingConfigurer { public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) { scheduledTaskRegistrar.setScheduler(Executors.newScheduledThreadPool(5)); } }
再次啟動,查看效果,如下:
由此看出走不同的線程執行,不同的線程執行的好處是,如果某一個線程掛掉后,并不會阻塞導致其它定時任務無法執行。
另外如果要想并發執行,前面的配置可以不要,直接用SpringBoot提供的現成注解即可,核心代碼如下:
@Component @EnableAsync public class ScheduleAsyncTask { private Logger logger = LoggerFactory.getLogger(ScheduleAsyncTask.class); @Scheduled(cron = "0/1 * * * * ? ") @Async public void one() { logger.info("one Async:" + new Date()); } @Scheduled(cron = "0/1 * * * * ? ") @Async public void two() { logger.info("two Async:" + new Date()); } @Scheduled(cron = "0/1 * * * * ? ") @Async public void three() { logger.info("three Async:" + new Date()); } }
除此外,還有基于schedule動態定時任務(所謂動態只不過是指cron表達式放在對應的數據表里),簡單示例代碼:
@Configuration public class DynamicScheduleTask implements SchedulingConfigurer { @Autowired @SuppressWarnings("all") CronMapper cronMapper; @Mapper public interface CronMapper { @Select("select cron from cron limit 1") public String getCron(); } /** * 執行定時任務. */ public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { taskRegistrar.addTriggerTask( //1.添加任務內容(Runnable) () -> System.out.println("執行動態定時任務: " + LocalDateTime.now().toLocalTime()), //2.設置執行周期(Trigger) triggerContext -> { //2.1 從數據庫獲取執行周期 String cron = cronMapper.getCron(); //2.2 合法性校驗. if (StringUtils.isEmpty(cron)) { // Omitted Code .. } //2.3 返回執行周期(Date) return new CronTrigger(cron).nextExecutionTime(triggerContext); } ); } }
核心配置文件(application.yml):
spring: datasource: url: jdbc:mysql://127.0.0.1:3306/test username: root password: 1234
SQL腳本:
DROP DATABASE IF EXISTS `test`; CREATE DATABASE `test`; USE `test`; DROP TABLE IF EXISTS `cron`; CREATE TABLE `cron` ( `cron_id` varchar(30) NOT NULL PRIMARY KEY, `cron` varchar(30) NOT NULL ); INSERT INTO `cron` VALUES ('1', '0/5 * * * * ?');
運行效果如下:
<!--引入quartz定時框架--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-quartz</artifactId> </dependency>
spring: quartz: #相關屬性配置 properties: org: quartz: scheduler: instanceName: clusteredScheduler instanceId: AUTO jobStore: class: org.quartz.impl.jdbcjobstore.JobStoreTX driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate tablePrefix: QRTZ_ isClustered: true clusterCheckinInterval: 10000 useProperties: false threadPool: class: org.quartz.simpl.SimpleThreadPool threadCount: 10 threadPriority: 5 threadsInheritContextClassLoaderOfInitializingThread: true #數據庫方式 job-store-type: jdbc #初始化表結構 jdbc: initialize-schema: always datasource: url: jdbc:mysql://127.0.0.1:3306/test username: root password: 1234
@SpringBootApplication @EnableScheduling public class BlogQuartzApplication { public static void main(String[] args) { SpringApplication.run(BlogQuartzApplication.class, args); } }
@Configuration public class QuartzConfiguration { // 使用jobDetail包裝job @Bean public JobDetail myCronJobDetail() { return JobBuilder.newJob(CouponTimeOutJob.class).withIdentity("couponTimeOutJob").storeDurably().build(); } // 把jobDetail注冊到Cron表達式的trigger上去 @Bean public Trigger CronJobTrigger() { CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule("0/1 * * * * ?"); return TriggerBuilder.newTrigger() .forJob(myCronJobDetail()) .withIdentity("CouponTimeOutJobTrigger") .withSchedule(cronScheduleBuilder) .build(); } }
public class CouponTimeOutJob extends QuartzJobBean { @Override protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException { System.out.println("定時任務執行"); } }
(1)對應的數據庫會生成定時任務相關的數據表
(2)控制臺不斷輸出定時任務執行日志
之前寫過一樣的例子,如今簡化了下。
關于xxl-job使用詳情,可以參考我的這篇文章:
SpringBoot整合Xxl-Job
<dependency> <groupId>com.xuxueli</groupId> <artifactId>xxl-job-core</artifactId> <version>2.2.0</version> </dependency>
@Configuration public class XxlJobConfig { private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class); @Value("${xxl.job.admin.addresses}") private String adminAddresses; @Value("${xxl.job.executor.appname}") private String appName; @Value("${xxl.job.executor.ip}") private String ip; @Value("${xxl.job.executor.port}") private int port; @Value("${xxl.job.accessToken}") private String accessToken; @Value("${xxl.job.executor.logpath}") private String logPath; @Value("${xxl.job.executor.logretentiondays}") private int logRetentionDays; @Bean(initMethod = "start", destroyMethod = "destroy") public XxlJobSpringExecutor xxlJobExecutor() { logger.info(">>>>>>>>>>> xxl-job config init."); XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor(); xxlJobSpringExecutor.setAdminAddresses(adminAddresses); xxlJobSpringExecutor.setAppname(appName); xxlJobSpringExecutor.setIp(ip); xxlJobSpringExecutor.setPort(port); xxlJobSpringExecutor.setAccessToken(accessToken); xxlJobSpringExecutor.setLogPath(logPath); xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays); return xxlJobSpringExecutor; } }
# web port server.port=8081 # no web #spring.main.web-environment=false ### xxl-job admin address list, such as "http://address" or "http://address01,http://address02" xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin ### xxl-job, access token xxl.job.accessToken= ### xxl-job executor appname xxl.job.executor.appname=blog-job-xxl-job ### xxl-job executor registry-address: default use address to registry , otherwise use ip:port if address is null xxl.job.executor.address= ### xxl-job executor server-info xxl.job.executor.ip= xxl.job.executor.port=8888 ### xxl-job executor log-path xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler ### xxl-job executor log-retention-days xxl.job.executor.logretentiondays=30
@Component public class XxlJobTaskExample { @XxlJob("blogJobHandler") public ReturnT<String> blogJobHandler(String param) throws Exception { System.out.println("執行"); XxlJobLogger.log("XXL-JOB, Hello World."); for (int i = 0; i < 5; i++) { XxlJobLogger.log("beat at:" + i); TimeUnit.SECONDS.sleep(2); } return ReturnT.SUCCESS; } }
分別如下所示:
<!-- 分布式定時任務鎖 --> <!-- https://mvnrepository.com/artifact/net.javacrumbs.shedlock/shedlock-spring --> <dependency> <groupId>net.javacrumbs.shedlock</groupId> <artifactId>shedlock-spring</artifactId> <version>4.0.4</version> </dependency> <!-- 使用redis做分布式任務 --> <dependency> <groupId>net.javacrumbs.shedlock</groupId> <artifactId>shedlock-provider-redis-spring</artifactId> <version>2.5.0</version> </dependency> <!-- redis組件 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
@Configuration @EnableSchedulerLock(defaultLockAtMostFor = "PT30M") public class ShedLockConfig { @Bean public LockProvider lockProvider(RedisTemplate redisTemplate) { return new RedisLockProvider(redisTemplate.getConnectionFactory()); } }
@Component public class TaskSchedule { /** * 每分鐘執行一次 * [秒] [分] [小時] [日] [月] [周] [年] */ @Scheduled(cron = "1 * * * * ?") @SchedulerLock(name = "synchronousSchedule") public void SynchronousSchedule() { System.out.println("Start run schedule to synchronous data:" + new Date()); } }
@SpringBootApplication @EnableScheduling public class ShedLockRedisApplication { public static void main(String[] args) { SpringApplication.run(ShedLockRedisApplication.class); } }
server: tomcat: uri-encoding: UTF-8 max-threads: 1000 min-spare-threads: 30 port: 8083 spring: redis: database: 0 host: localhost port: 6379 password: # 密碼(默認為空) timeout: 6000ms # 連接超時時長(毫秒) jedis: pool: max-active: 1000 # 連接池最大連接數(使用負值表示沒有限制) max-wait: -1ms # 連接池最大阻塞等待時間(使用負值表示沒有限制) max-idle: 10 # 連接池中的最大空閑連接 min-idle: 5 # 連接池中的最小空閑連接
我之所以用shedlock是因為確保在集群環境下各微服務的定時任務只執行一個,而不是全部都運行相同的定時任務。
本次測試效果如下:
關于SpringBoot定時任務如何在Java中使用就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。