欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

SpringBoot集成SpringScheduler和QuartzScheduler

本文介紹了Spring Boot集成Spring Scheduler和Quartz Scheduler的基礎(chǔ)知識(shí),利用ShedLock解決Spring Scheduler多實(shí)例運(yùn)行沖突,介紹了Quartz ScheduleBuilder、Calendar,介紹了動(dòng)態(tài)創(chuàng)建Quartz Job的方法。

創(chuàng)新互聯(lián)-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設(shè)、高性價(jià)比濟(jì)源網(wǎng)站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式濟(jì)源網(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設(shè)找我們,業(yè)務(wù)覆蓋濟(jì)源地區(qū)。費(fèi)用合理售后完善,十余年實(shí)體公司更值得信賴。

GitHub源碼

Spring Scheduler

Spring Framework提供了簡單、易用的Job調(diào)度框架Spring Scheduler。

示例

在Spring Boot中,只需兩步即可啟用Scheduler:

  1. 啟用Scheduling
package org.itrunner.heroes.scheduling;

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;

@Configuration
@EnableScheduling
public class ScheduleConfig {
}
  1. 定義Schedule方法
package org.itrunner.heroes.scheduling;

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
@Slf4j
public class HelloSpring {

    @Scheduled(cron = "0 */10 * * * *")
    public void sayHello() {
        log.info("Hello Spring Scheduler");
    }

}

@Scheduled支持cron、fixedDelay、fixedRate三種定義方式,方法必須沒有參數(shù),返回void類型。

ShedLock

默認(rèn)情況下,Spring無法同步多個(gè)實(shí)例的調(diào)度程序,而是在每個(gè)節(jié)點(diǎn)上同時(shí)執(zhí)行作業(yè)。我們可以使用shedlock-spring解決這一問題,確保在同一時(shí)間僅調(diào)度一次任務(wù)。

<dependency>
    <groupId>net.javacrumbs.shedlock</groupId>
    <artifactId>shedlock-spring</artifactId>
    <version>4.1.0</version>
</dependency>
<dependency>
    <groupId>net.javacrumbs.shedlock</groupId>
    <artifactId>shedlock-provider-jdbc-template</artifactId>
    <version>4.1.0</version>
</dependency>

ShedLock是利用數(shù)據(jù)庫鎖機(jī)制實(shí)現(xiàn)的,當(dāng)前支持DynamoDB、Hazelcast、Mongo、redis、ZooKeeper和任何JDBC Driver。為了使用JDBC,增加下面依賴:

<dependency>
  <groupId>net.javacrumbs.shedlock</groupId>
  <artifactId>shedlock-provider-jdbc-template</artifactId>
  <version>4.1.0</version>
</dependency>

創(chuàng)建Shedlock Entity:

package org.itrunner.heroes.domain;

import lombok.Data;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.time.LocalDateTime;

@Entity
@Table(name = "shedlock")
@Data
public class Shedlock {
    @Id
    @Column(name = "name", length = 64)
    private String name;

    @Column(name = "lock_until")
    private LocalDateTime lockUntil;

    @Column(name = "locked_at")
    private LocalDateTime lockedAt;

    @Column(name = "locked_by")
    private String lockedBy;
}

啟用ShedLock:

package org.itrunner.heroes.scheduling;

import net.javacrumbs.shedlock.core.LockProvider;
import net.javacrumbs.shedlock.provider.jdbctemplate.JdbcTemplateLockProvider;
import net.javacrumbs.shedlock.spring.annotation.EnableSchedulerLock;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;

import javax.sql.DataSource;

@Configuration
@EnableScheduling
@EnableSchedulerLock(defaultLockAtMostFor = "PT30S")
public class ScheduleConfig {

    @Bean
    public LockProvider lockProvider(DataSource dataSource) {
        return new JdbcTemplateLockProvider(dataSource);
    }

}
package org.itrunner.heroes.scheduling;

import lombok.extern.slf4j.Slf4j;
import net.javacrumbs.shedlock.spring.annotation.SchedulerLock;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
@Slf4j
public class HelloSpring {

    @Scheduled(cron = "0 */10 * * * *")
    @SchedulerLock(name = "helloSpringScheduler", lockAtLeastFor = "PT30S", lockAtMostFor = "PT3M")
    public void sayHello() {
        log.info("Hello Spring Scheduler");
    }

}

其中l(wèi)ockAtLeastFor和lockAtMostFor設(shè)置lock的最短和最長時(shí)間,上例分別為30秒、3分鐘。

Quartz Scheduler

Quartz Scheduler是功能強(qiáng)大的任務(wù)調(diào)度框架,在Spring Scheduler不能滿足需求時(shí)可以使用Quartz。

集成Quartz

  1. POM依賴

Spring Boot項(xiàng)目中僅需引入依賴spring-boot-starter-quartz:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
  1. 配置Quartz

默認(rèn),使用內(nèi)存JobStore,在生產(chǎn)環(huán)境中應(yīng)配置使用數(shù)據(jù)庫:

spring:
  quartz:
    auto-startup: true
    job-store-type: jdbc
    jdbc:
      initialize-schema: always
    overwrite-existing-jobs: true
    properties:
      org.quartz.threadPool.threadCount: 5

在spring.quartz.properties中可以配置Quartz高級(jí)屬性。

  1. 定義Quartz Job
package org.itrunner.heroes.scheduling;

import lombok.extern.slf4j.Slf4j;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;

@Slf4j
public class HelloQuartz extends QuartzJobBean {

    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        log.info("Hello Quartz Scheduler");
    }

}
  1. 注冊(cè)Job

集成Quartz后,一個(gè)Scheduler被自動(dòng)配置。SchedulerFactoryBean負(fù)責(zé)創(chuàng)建和配置Quartz Scheduler,作為Spring application context的一部分管理其生命周期。scheduler可以在其它組件中注入。

所有的JobDetail、Calendar和Trigger Bean自動(dòng)與scheduler關(guān)聯(lián),在Spring Boot初始化時(shí)自動(dòng)啟動(dòng)scheduler,并在銷毀時(shí)將其關(guān)閉。

靜態(tài)注冊(cè)Job
僅需在啟動(dòng)時(shí)靜態(tài)注冊(cè)Job的情況下,只需聲明Bean,無需在程序中訪問scheduler實(shí)例本身,如下:

package org.itrunner.heroes.scheduling;

import org.itrunner.heroes.util.DateUtils;
import org.quartz.*;
import org.quartz.impl.calendar.HolidayCalendar;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.time.LocalDate;

@Configuration
public class QuartzConfig {
    private static final String CRON_EXPRESSION = "0 0/5 * * * ?";
    private static final String GROUP = "iTRunner";

    @Bean
    public Trigger helloJobTrigger(JobDetail helloJob) {
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(CRON_EXPRESSION);
        return TriggerBuilder.newTrigger().forJob(helloJob).withIdentity(getTriggerKey(helloJob.getKey())).withSchedule(scheduleBuilder).modifiedByCalendar("holidayCalendar").build();
    }

    @Bean
    public JobDetail helloJob() {
        return JobBuilder.newJob(HelloQuartz.class).withIdentity(getJobKey(HelloQuartz.class)).storeDurably().build();
    }

    @Bean
    public Calendar holidayCalendar() {
        HolidayCalendar calendar = new HolidayCalendar();
        LocalDate date = LocalDate.of(2020, 1, 1);
        calendar.addExcludedDate(DateUtils.toDate(date));
        return calendar;
    }

    private static <T> JobKey getJobKey(Class<T> cls) {
        return new JobKey(cls.getSimpleName(), GROUP);
    }

    private static TriggerKey getTriggerKey(JobKey jobKey) {
        return new TriggerKey(jobKey.getName(), GROUP);
    }
}

ScheduleBuilder

上例,我們使用了CronScheduleBuilder,Quartz還支持SimpleScheduleBuilder、DailyTimeIntervalScheduleBuilder、CalendarIntervalScheduleBuilder。

  • SimpleScheduleBuilder 按指定的時(shí)間間隔執(zhí)行任務(wù),單位可以為毫秒、秒、分或小時(shí);可以指定執(zhí)行任務(wù)的總次數(shù)。
  • DailyTimeIntervalScheduleBuilder 每天按指定的時(shí)間間隔執(zhí)行任務(wù),單位可以為秒、分或小時(shí);可以指定每天執(zhí)行任務(wù)的起止時(shí)間;可以指定在星期幾執(zhí)行;可以指定每天執(zhí)行任務(wù)的總次數(shù)
  • CalendarIntervalScheduleBuilder 按指定的時(shí)間間隔執(zhí)行任務(wù),單位可以為秒、分、時(shí)、日、周、月、年
  • CronScheduleBuilder 使用Cron表達(dá)式定義任務(wù)執(zhí)行時(shí)間,也支持dailyAtHourAndMinute()、atHourAndMinuteOnGivenDaysOfWeek()、weeklyOnDayAndHourAndMinute()、monthlyOnDayAndHourAndMinute()等便利方法。

Cron-Expression
Cron 表達(dá)式由 6 個(gè)必選字段和一個(gè)可選字段組成,字段間由空格分隔。

Field NameAllowed ValuesAllowed Special Characters
0-59 , - * /
0-59 , - * /
時(shí) 0-23 , - * /
1-31 , - * ? / L W
0-11 或 JAN-DEC , - * /
1-7 或 SUN-SAT , - * ? / L #
年 (可選) 空 或 1970-2199 , - * /
* 可用在所有字段,例如,在分鐘字段表示每分鐘
? 允許應(yīng)用在日和周字段,用于指定“非特定值”,相當(dāng)于占位符
- 用于指定范圍,如在小時(shí)字段,“10-12”表示10,11,12
, 指定列表值,如在周字段,"MON,WED,FRI"表示周一,周三,周五
/ 指定步長,如在秒字段,"0/15"表示0,15,30,45;"5/15"表示5, 20, 35, 50。如使用*/x,相當(dāng)于0/x。
L 只用于日和周字段,意為“l(fā)ast”。在日字段,如一月的31號(hào),非閏年二月的28號(hào);在周字段,表示7或"SAT",若在L前還有一個(gè)值,如6L,表示這個(gè)月最后的周五。
W 僅用于日字段,表示離指定日期最近的工作日(周一至周五),如15W,表示離該月15號(hào)最近的工作日,注意不能跨月。
LW組合, 表示當(dāng)月最后一個(gè)工作日
# 僅用于周字段,表示第幾,如“6#3”,表示本月第3個(gè)周五

示例:

0 0/5 * * * ?    每5分鐘
10 0/5 * * * ?  每5分鐘,10秒時(shí)執(zhí)行,如10:00:10, 10:05:10
0 30 10-13 ? * WED,FRI  每周三和周五的10:30, 11:30, 12:30 和 13:30
0 0/30 8-9 5,20 * ?  每月5號(hào)和20號(hào)的8:00, 8:30, 9:00 和 9:30

Calendar

Calendar不定義實(shí)際的觸發(fā)時(shí)間,而是與Trigger結(jié)合使用,用于排除特定的時(shí)間。

AnnualCalendar 排除每年中的一天或多天
CronCalendar 使用Cron表達(dá)式定義排除的時(shí)間,如"* * 0-7,18-23 ? * *",排除每天的8點(diǎn)至17點(diǎn)
DailyCalendar 排除每天指定的時(shí)間段
HolidayCalendar 排除節(jié)假日,需要指定確切的日期
MonthlyCalendar 排除每月的一天或多天
WeeklyCalendar 排除每周的一天或多天,默認(rèn)排除周六、周日

動(dòng)態(tài)Job

在很多情況下我們需要?jiǎng)討B(tài)創(chuàng)建或啟停Job,比如Job數(shù)據(jù)是動(dòng)態(tài)的、Job間有依賴關(guān)系、根據(jù)條件啟停Job等。

下面示例簡單演示了動(dòng)態(tài)創(chuàng)建Job、添加calendar、添加listener、啟停job的方法:

package org.itrunner.heroes.scheduling;

import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.quartz.impl.calendar.WeeklyCalendar;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import static org.itrunner.heroes.scheduling.Constants.*;

@Service
@Slf4j
public class ScheduleService {
    private final Scheduler scheduler;

    @Autowired
    public ScheduleService(Scheduler scheduler) { // 注入scheduler
        this.scheduler = scheduler;

        try {
            addJobListener();
            addCalendar();
            scheduleJob();
        } catch (SchedulerException e) {
            log.error(e.getMessage(), e);
        }
    }

    public void unscheduleJob(String jobName) throws SchedulerException {
        scheduler.pauseJob(JobKey.jobKey(jobName, GROUP_NAME));
        scheduler.unscheduleJob(TriggerKey.triggerKey(jobName, GROUP_NAME));
    }

     /**
     * 立即觸發(fā)job
     */
    public void triggerJob(String jobName) throws SchedulerException {
        scheduler.triggerJob(JobKey.jobKey(jobName, GROUP_NAME));
    }

    private void addJobListener() throws SchedulerException {
        UnscheduleJobListener jobListener = new UnscheduleJobListener();
        GroupMatcher<JobKey> groupMatcher = GroupMatcher.jobGroupEquals(GROUP_NAME);
        this.scheduler.getListenerManager().addJobListener(jobListener, groupMatcher);
    }

    private void addCalendar() throws SchedulerException {
        WeeklyCalendar calendar = new WeeklyCalendar();
        calendar.setDayExcluded(1, true); // 排除周日
        calendar.setDayExcluded(7, false);
        this.scheduler.addCalendar("weekly", calendar, false, false);
    }

    private void scheduleJob() throws SchedulerException {
        JobDetail jobDetail = createJobDetail();
        Trigger trigger = createTrigger(jobDetail);
        scheduler.scheduleJob(jobDetail, trigger);
    }

    private JobDetail createJobDetail() {
        JobDataMap jobDataMap = new JobDataMap(); // 添加Job數(shù)據(jù)
        jobDataMap.put(JOB_NAME, "getHeroes");
        jobDataMap.put(JOB_REST_URI, "http://localhost:8080/api/heroes");
        jobDataMap.put(JOB_REQUEST_METHOD, "GET");

        return JobBuilder.newJob(RestJob.class).withIdentity("getHeroes", GROUP_NAME).usingJobData(jobDataMap).storeDurably().build();
    }

    private Trigger createTrigger(JobDetail jobDetail) {
        DailyTimeIntervalScheduleBuilder scheduleBuilder = DailyTimeIntervalScheduleBuilder.dailyTimeIntervalSchedule().withIntervalInMinutes(1).onEveryDay();
        return TriggerBuilder.newTrigger().forJob(jobDetail).withIdentity("getHeroes", GROUP_NAME).withSchedule(scheduleBuilder).modifiedByCalendar("weekly").build();
    }

}

Job定義

下面Job調(diào)用了REST服務(wù),調(diào)用成功后在JobExecutionContext中添加stop標(biāo)志:

package org.itrunner.heroes.scheduling;

import lombok.extern.slf4j.Slf4j;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.quartz.QuartzJobBean;

import java.util.List;

import static org.itrunner.heroes.scheduling.Constants.JOB_REST_URI;
import static org.itrunner.heroes.scheduling.Constants.JOB_STOP_FLAG;

@Slf4j
public class RestJob extends QuartzJobBean {
    @Autowired
    private RestService restService;

    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        JobDataMap jobDataMap = jobExecutionContext.getMergedJobDataMap();
        String restUri = jobDataMap.getString(JOB_REST_URI);

        ResponseEntity<List> responseEntity = restService.requestForEntity(restUri, HttpMethod.GET, List.class);
        log.info(responseEntity.getBody().toString());

        // set stop flag
        jobExecutionContext.put(JOB_STOP_FLAG, true);
    }
}

JobListener
UnscheduleJobListener檢查JobExecutionContext中是否有stop標(biāo)志,如有則停止Job:

package org.itrunner.heroes.scheduling;

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobListener;
import org.quartz.SchedulerException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class UnscheduleJobListener implements JobListener {
    private static Logger log = LoggerFactory.getLogger(UnscheduleJobListener.class);

    @Override
    public String getName() {
        return "HERO_UnscheduleJobListener";
    }

    @Override
    public void jobToBeExecuted(JobExecutionContext context) {
        log.info(getJobName(context) + " is about to be executed.");
    }

    @Override
    public void jobExecutionVetoed(JobExecutionContext context) {
        log.info(getJobName(context) + " Execution was vetoed.");
    }

    @Override
    public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
        log.info(getJobName(context) + " was executed.");

        Boolean stop = (Boolean) context.get(Constants.JOB_STOP_FLAG);

        if (stop == null || !stop) {
            return;
        }

        String jobName = getJobName(context);

        log.info("Unschedule " + jobName);

        try {
            context.getScheduler().unscheduleJob(context.getTrigger().getKey());
        } catch (SchedulerException e) {
            log.error("Unable to unschedule " + jobName, e);
        }
    }

    private String getJobName(JobExecutionContext context) {
        return "Hero job " + context.getJobDetail().getKey().getName();
    }
}

文章題目:SpringBoot集成SpringScheduler和QuartzScheduler
網(wǎng)站鏈接:http://aaarwkj.com/article32/pcccsc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供微信小程序、自適應(yīng)網(wǎng)站、標(biāo)簽優(yōu)化、品牌網(wǎng)站設(shè)計(jì)、外貿(mào)建站、網(wǎng)站收錄

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

營銷型網(wǎng)站建設(shè)
欧美国产成人精品一区| 亚洲成人午夜免费在线观看| 最新日韩人妻中文字幕一区| 国产精品成人大片在线播放| 超碰97精品在线观看| 蜜臀视频在线观看免费| 亚洲一区成人免费电影| 亚洲国产精品综合色在线| 日本三级黄色免费的网站| 国产亚洲一区二区视频| 国产精品妇女一二三区| 欧美一区二区三区日| 日本一区二区高清网址| 在线播放精品免费不卡| 99热这里只有精品免费播放| 麻豆精东传媒一区二区| 欧美欧美欧美欧美一二三区| 日本三卡=卡无人区| 国内传媒视频免费观看| 97免费公开在线观看| 日本人妻三级精品久久| 深夜福利在线观看97| 亚洲码与欧洲码一二三| 久久精品国产亚洲av高清大结局| 亚洲国产欧美日韩在线不卡成人| 日韩一级久久精品理论| 日韩人妻熟妇中文字幕| 成人中文字幕日韩电影| 国产精品一区二区剧情熟女| 午夜在线观看成人av| 中文乱码字幕午夜无线观看| 欧美日韩亚洲精品一区二区三区| 亚洲日本韩国美女二区| 日韩深夜成人在线视频| 青青草原在线影视一区| 国产成人综合久久三区北岛玲| 欧美三级视频一区二区三区 | 野花日本免费高清完整| 人妻少妇被粗大爽av| 国产又大又爽免费视频| 精品久久人妻中文字幕免费|