Planlægning om foråret med kvarts

1. Oversigt

I denne vejledning bygger vi en simpel Planlægning om foråret med kvarts.

Vi begynder med et simpelt mål for øje - nem konfiguration af et nyt planlagt job.

1.1. Nøglekomponenter i Quartz API

Kvarts har en modulær arkitektur. Den består af flere grundlæggende komponenter, der kan kombineres efter behov. I denne vejledning fokuserer vi på dem, der er fælles for hvert job: Job, Jobdetaljer, Udløser ogPlanlægning.

Selvom vi bruger Spring til at styre applikationen, kan hver enkelt komponent konfigureres på to måder: Kvarts måde eller Forår måde (ved hjælp af dets bekvemmelighedsklasser).

Vi dækker begge dele så vidt muligt for fuldstændighedens skyld, men begge kan vedtages. Lad os begynde at bygge en komponent ad gangen.

2. Job og Jobdetaljer

2.1. Job

API'en giver en Job interface med kun en metode - udføre. Det skal implementeres af den klasse, der indeholder det faktiske arbejde, der skal udføres, dvs. opgaven. Når udløseren af ​​et job udløses, påkalder planlæggeren udføre metode, videregive den a JobExecutionContext objekt.

Det JobExecutionContext giver jobforekomsten oplysninger om dens runtime-miljø, herunder et håndtag til planlæggeren, et håndtag til udløseren og jobets Jobdetaljer objekt.

I dette hurtige eksempel - opgaven delegerer opgaven til en serviceklasse:

@Component public class SampleJob implementerer job {@Autowired privat SampleJobService jobService; public void execute (JobExecutionContext context) kaster JobExecutionException {jobService.executeSampleJob (); }} 

2.2. Jobdetaljer

Mens jobbet er arbejdshesten, gemmer Quartz ikke en faktisk forekomst af jobklassen. I stedet kan vi definere en forekomst af Job bruger Jobdetaljer klasse. Jobets klasse skal leveres til Jobdetaljer så det kender type af det job, der skal udføres.

2.3. Kvarts JobBuilder

Kvartset JobBuilder giver en builder-stil API til konstruktion Jobdetaljer enheder.

@Bean offentlig JobDetail jobDetail () {return JobBuilder.newJob (). OfType (SampleJob.class) .storeDurably () .withIdentity ("Qrtz_Job_Detail") .withDescription ("Invoke Sample Job service ...") .build (); }

2.4. Forår JobDetailFactoryBean

Forårets JobDetailFactoryBean giver brug i bønnestil til konfiguration Jobdetaljer tilfælde. Det bruger Spring Bean-navnet som jobnavn, hvis ikke andet er angivet:

@Bean public JobDetailFactoryBean jobDetail () {JobDetailFactoryBean jobDetailFactory = ny JobDetailFactoryBean (); jobDetailFactory.setJobClass (SampleJob.class); jobDetailFactory.setDescription ("Invoke Sample Job service ..."); jobDetailFactory.setDurability (true); return jobDetailFactory; }

En ny forekomst af Jobdetaljer oprettes til hver udførelse af jobbet. Det Jobdetaljer objekt formidler de detaljerede egenskaber ved jobbet. Når udførelsen er afsluttet, henvises til forekomsten.

3. Udløser

EN Udløser er mekanismen til at planlægge en Job, dvs. a Udløser eksempel “fyrer” udførelsen af ​​et job. Der er en klar adskillelse af ansvaret mellem Job (begrebet opgave) og Udløser (planlægningsmekanisme).

I tillæg til Job, udløseren har også brug for en type der kan vælges ud fra planlægningskravene.

Lad os sige, vi vil planlægge, at vores opgave skal udføres en gang i timen, på ubestemt tid - vi kan bruge kvarts TriggerBuilder eller forårets SimpleTriggerFactoryBean for at gøre det.

3.1. Kvarts TriggerBuilder

TriggerBuilder er en builder-stil API til at konstruere Udløser enhed:

@Bean public Trigger trigger (JobDetail job) {return TriggerBuilder.newTrigger (). ForJob (job) .withIdentity ("Qrtz_Trigger") .withDescription ("Sample trigger") .withSchedule (simpleSchedule (). RepeatForever (). WithIntervalInHours (1) )) .build (); }

3.2. Forår SimpleTriggerFactoryBean

SimpleTriggerFactoryBean giver brug i bønnestil til konfiguration SimpleTrigger. Det bruger Spring Bean-navnet som udløsernavnet og er standard for ubestemt gentagelse, hvis ikke andet er angivet:

@Bean offentlig SimpleTriggerFactoryBean trigger (JobDetail job) {SimpleTriggerFactoryBean trigger = ny SimpleTriggerFactoryBean (); trigger.setJobDetail (job); trigger.setRepeatInterval (3600000); trigger.setRepeatCount (SimpleTrigger.REPEAT_INDEFINITELY); returudløser; }

4. Konfiguration af JobStore

JobStore giver lagringsmekanismen til Job og Udløser, og er ansvarlig for at vedligeholde alle de data, der er relevante for jobplanlæggeren. API'en understøtter begge dele i hukommelsen og vedholdende butikker.

4.1. In-Memory JobStore

For eksempel bruger vi in-memory RAMJobStore der tilbyder lynhurtig ydeevne og enkel konfiguration via kvarts. ejendomme:

org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore

Den åbenlyse ulempe ved RAMJobStore er, at det er flygtige i naturen. Alle planlægningsoplysninger går tabt mellem nedlukninger. Hvis jobdefinitioner og tidsplaner skal holdes mellem nedlukninger, er den vedvarende JDBCJobStore skal bruges i stedet.

For at aktivere en hukommelse JobStore om foråret, vi sætter denne ejendom i vores application.properties:

spring.quartz.job-store-type = hukommelse

4.2. JDBC JobStore

Der er to typer JDBCJobStore: JobStoreTX og JobStoreCMT. De gør begge det samme job med at gemme planlægningsoplysninger i en database.

Forskellen mellem de to er, hvordan de administrerer de transaktioner, der begår dataene. Det JobStoreCMT type kræver en applikationstransaktion for at gemme data, mens JobStoreTX type starter og administrerer sine egne transaktioner.

Der er flere egenskaber, der skal indstilles til en JDBCJobStore. Vi skal som minimum specificere typen af JDBCJobStore, datakilden og databasedriverklassen. Der er førerklasser for de fleste databaser, men StdJDBCDelegate dækker de fleste tilfælde:

org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate org.quartz.jobStore.dataSource = quartzDataSource

Opsætning af en JDBC JobStore i foråret tager et par skridt. For det første indstiller vi butiktypen i vores application.properties:

spring.quartz.job-store-type = jdbc

Dernæst skal vi aktivere automatisk konfiguration og give Spring den datakilde, der er nødvendig for Quartz-planlæggeren. Det @QuartzDataSource annotation gør det hårde arbejde med at konfigurere og initialisere Quartz-databasen for os:

@Configuration @EnableAutoConfiguration public class SpringQrtzScheduler {@Bean @QuartzDataSource public DataSource quartzDataSource () {return DataSourceBuilder.create (). Build (); }}

5. Planlægning

Det Planlægning interface er den vigtigste API til grænseflade med jobplanlæggeren.

EN Planlægning kan instantieres med en Planlægningsfabrik. Når de er oprettet, Jobs og Udløsers kan registreres med det. Oprindeligt blev Planlægning er i "stand-by" -tilstand, og dens Start metode skal påberåbes for at starte de tråde, der affyrer udførelsen af ​​job.

5.1. Kvarts StdSchedulerFactory

Ved blot at påberåbe sig getScheduler metode til StdSchedulerFactory, vi kan instantiere Planlægninginitialiser det (med den konfigurerede JobStore og TrådPool), og returner et håndtag til dets API:

@Bean public Scheduler scheduler (Trigger trigger, JobDetail job, SchedulerFactoryBean factory) kaster SchedulerException {Scheduler scheduler = factory.getScheduler (); scheduler.scheduleJob (job, trigger); scheduler.start (); returplanlægning; }

5.2. Forår SchedulerFactoryBean

Forårets SchedulerFactoryBean giver brug i bønnestil til konfiguration af en Planlægning, styrer sin livscyklus inden for applikationens sammenhæng og udsætter Planlægning som en bønne til afhængighedsinjektion:

@Bean public SchedulerFactoryBean scheduler (Trigger trigger, JobDetail job, DataSource quartzDataSource) {SchedulerFactoryBean schedulerFactory = new SchedulerFactoryBean (); schedulerFactory.setConfigLocation (ny ClassPathResource ("kvarts. ejendomme")); schedulerFactory.setJobFactory (springBeanJobFactory ()); schedulerFactory.setJobDetails (job); schedulerFactory.setTriggers (trigger); schedulerFactory.setDataSource (kvartsDataSource); returplanlæggerFabrik; }

5.3. Konfiguration SpringBeanJobFactory

Det SpringBeanJobFactory giver support til at indsprøjte planlægningskonteksten, jobdatakortet og udløse dataposter som egenskaber i jobbønnen, mens du opretter en forekomst.

Det mangler dog støtte til injektion af bønnereferencer fra applikationskontekst. Tak til forfatteren af ​​dette blogindlæg kan vi tilføje automatisk ledningsføring støtte til SpringBeanJobFactory ligesom:

@Bean public SpringBeanJobFactory springBeanJobFactory () {AutoWiringSpringBeanJobFactory jobFactory = ny AutoWiringSpringBeanJobFactory (); jobFactory.setApplicationContext (applicationContext); retur jobFabrik; }

6. Konklusion

Det er alt. Vi har netop bygget vores første grundlæggende planlægning ved hjælp af Quartz API såvel som Spring's bekvemmelighedsklasser.

Nøgleudtagningen fra denne vejledning er, at vi var i stand til at konfigurere et job med kun et par linjer kode og uden at bruge nogen XML-baseret konfiguration.

Det komplette kildekode for eksemplet er tilgængeligt i dette github-projekt. Det er et Maven-projekt, der kan importeres og køre som det er. Standardindstillingen bruger Spring's bekvemmelighedsklasser, som let kan skiftes til Quartz API med en kørselstidsparameter (se README.md i lageret).