Introduktion til kvarts

1. Oversigt

Kvarts er en open source jobplanlægningsramme skrevet udelukkende i Java og designet til brug i begge J2SE og J2EE applikationer. Det giver stor fleksibilitet uden at ofre enkelheden.

Du kan oprette komplekse tidsplaner for udførelse af ethvert job. Eksempler er f.eks. opgaver, der kører dagligt, hver anden fredag ​​kl. 19.30 eller kun den sidste dag i hver måned.

I denne artikel ser vi på elementer til at opbygge et job med Quartz API. For en introduktion i kombination med foråret anbefaler vi Planlægning om foråret med kvarts.

2. Maven-afhængigheder

Vi er nødt til at tilføje følgende afhængighed af pom.xml:

 org.quartz-scheduler kvarts 2.3.0 

Den seneste version kan findes i Maven Central repository.

3. Quartz API

Hjertet i rammen er Planlægning. Det er ansvarligt for at administrere runtime-miljøet til vores applikation.

For at sikre skalerbarhed er kvarts baseret på en arkitektur med flere tråde. Når det blev startet, initialiserer rammen et sæt arbejdstråde der bruges af Planlægning at udføre Job.

Sådan kan rammen køre mange Job samtidigt. Det er også afhængig af et løst koblet sæt af TrådPool styringskomponenter til styring af trådmiljøet.

API-nøglegrænsefladerne er:

  • Planlægning - den primære API til at interagere med planlæggeren af ​​rammen
  • Job - en grænseflade, der skal implementeres af komponenter, som vi ønsker at have udført
  • JobDetail - bruges til at definere forekomster af Jobs
  • Udløser - en komponent, der bestemmer tidsplanen for en given Job udføres
  • JobBuilder - brugt til at bygge Jobdetaljer instanser, der definerer forekomster af Job
  • TriggerBuilder - brugt til at bygge Udløser tilfælde

Lad os se på hver af disse komponenter.

4. Planlægning

Før vi kan bruge Planlægning, det skal instantieres. For at gøre dette kan vi bruge fabrikken Planlægningsfabrik:

SchedulerFactory schedulerFactory = ny StdSchedulerFactory (); Planlægningsplanlægger = schedulerFactory.getScheduler ();

EN PlanlægningLivscyklus er afgrænset af dets oprettelse via en Planlægningsfabrik og et opkald til dets lukke ned() metode. Når oprettet Planlægning interface kan bruges til at tilføje, fjerne og liste Job og Udløsere, og udfør andre planlægningsrelaterede operationer (såsom at sætte en trigger på pause).

Imidlertid, det Planlægning vil ikke reagere på nogen udløsere, før den er startet med Start() metode:

scheduler.start ();

5. Job

EN Job er en klasse, der implementerer Job interface. Det har kun en enkel metode:

offentlig klasse SimpleJob implementerer Job {public void execute (JobExecutionContext arg0) kaster JobExecutionException {System.out.println ("Dette er et kvartsjob!"); }}

Når Job udløse brande, den udføre () metode påberåbes af en af ​​planlægningens medarbejdertråde.

Det JobExecutionContext objekt, der sendes til denne metode, giver jobforekomsten information om dens runtime-miljø, et håndtag til Planlægning der udførte det, et håndtag til Udløser der udløste udførelsen, jobbet Jobdetaljer objekt og et par andre ting.

Det Jobdetaljer objekt oprettes af Quartz-klienten på det tidspunkt Job tilføjes til Planlægning. Det er i det væsentlige definitionen af ​​jobinstansen:

JobDetail job = JobBuilder.newJob (SimpleJob.class) .withIdentity ("myJob", "group1") .build ();

Dette objekt kan også indeholde forskellige egenskabsindstillinger for Job, samt en JobDataMap, som kan bruges til at gemme tilstandsoplysninger for en given forekomst af vores jobklasse.

5.1. JobDataMap

Det JobDataMap bruges til at holde en hvilken som helst mængde dataobjekter, som vi ønsker at gøre tilgængelige for jobforekomsten, når den udføres. JobDataMap er en implementering af Java Kort interface og har nogle tilføjede bekvemhedsmetoder til lagring og hentning af data af primitive typer.

Her er et eksempel på at indsætte data i JobDataMap mens du bygger Jobdetaljer, før du tilføjer jobbet til planlæggeren:

JobDetail job = newJob (SimpleJob.class) .withIdentity ("myJob", "group1") .usingJobData ("jobSays", "Hello World!") .UsingJobData ("myFloatValue", 3.141f) .build ();

Og her er et eksempel på, hvordan du får adgang til disse data under jobudførelsen:

offentlig klasse SimpleJob implementerer Job {public void execute (JobExecutionContext context) kaster JobExecutionException {JobDataMap dataMap = context.getJobDetail (). getJobDataMap (); String jobSays = dataMap.getString ("jobSays"); flyde myFloatValue = dataMap.getFloat ("myFloatValue"); System.out.println ("Job siger:" + jobSays + ", og val er:" + myFloatValue); }}

Ovenstående eksempel vil udskrive "Job siger Hello World !, og val er 3.141".

Vi kan også tilføje settermetoder til vores jobklasse, der svarer til navnene på nøglerne i JobDataMap.

Hvis vi gør dette, er Quartzs standard JobFabrik implementering kalder automatisk disse settere, når jobbet instantieres, hvilket forhindrer behovet for eksplicit at få værdierne ud af kortet inden for vores eksekveringsmetode.

6. Udløsere

Udløser objekter bruges til at udløse udførelsen af Job.

Når vi ønsker at planlægge en Job, vi er nødt til at starte en trigger og justere dens egenskaber for at konfigurere vores planlægningskrav:

Trigger trigger = TriggerBuilder.newTrigger () .withIdentity ("myTrigger", "group1") .startNow () .withSchedule (SimpleScheduleBuilder.simpleSchedule () .withIntervalInSeconds (40) .repeatForever ()) .build ();

EN Udløser kan også have en JobDataMap forbundet med det. Dette er nyttigt til overføring af parametre til a Job der er specifikke for udførelsen af ​​udløseren.

Der er forskellige typer udløsere til forskellige planlægningsbehov. Hver enkelt har forskellige TriggerKey egenskaber til sporing af deres identiteter. Imidlertid er nogle andre egenskaber fælles for alle udløsertyper:

  • Det jobKey egenskab angiver identiteten på det job, der skal udføres, når udløseren udløses.
  • Det starttidspunkt egenskab angiver, hvornår triggerens tidsplan først træder i kraft. Værdien er en java.util.Date objekt, der definerer et øjeblik i tiden for en given kalenderdato. For nogle triggertyper udløses triggeren på det givne starttidspunkt. For andre markerer det simpelthen det tidspunkt, hvor tidsplanen skal starte.
  • Det sluttid egenskab angiver, hvornår triggerens tidsplan skal annulleres.

Kvarts sendes med en håndfuld forskellige udløsertyper, men de mest almindeligt anvendte er SimpleTrigger og CronTrigger.

6.1. Prioritet

Nogle gange, når vi har mange udløsere, har kvarts muligvis ikke nok ressourcer til straks at fyre alle de job, der er planlagt til at affyre på samme tid. I dette tilfælde vil vi måske kontrollere, hvilke af vores udløsere, der først bliver tilgængelige. Dette er præcis hvad prioritet ejendom på en udløser bruges til.

For eksempel, når ti udløsere er indstillet på samme tid, og kun fire arbejdertråde er tilgængelige, udføres de første fire udløsere med den højeste prioritet først. Når vi ikke indstiller en prioritet på en trigger, bruger den en standardprioritet på fem. Enhver heltalværdi er tilladt som en prioritet, positiv eller negativ.

I eksemplet nedenfor har vi to udløsere med en anden prioritet. Hvis der ikke er nok ressourcer til at affyre alle udløserne på samme tid, triggerA bliver den første, der fyres:

Trigger triggerA = TriggerBuilder.newTrigger () .withIdentity ("triggerA", "group1") .startNow () .withPriority (15) .withSchedule (SimpleScheduleBuilder.simpleSchedule () .withIntervalInSeconds (40) .repeatForever ().) ; Trigger triggerB = TriggerBuilder.newTrigger () .withIdentity ("triggerB", "group1") .startNow () .withPriority (10) .withSchedule (SimpleScheduleBuilder.simpleSchedule () .withIntervalInSeconds (20) .repeatForever ().) ;

6.2. Misfire instruktioner

En fejlfejl opstår, hvis en vedvarende udløser savner dens affyringstid på grund af Planlægning lukkes, eller hvis der ikke er nogen tilgængelige tråde i kvarts trådpulje.

De forskellige udløsertyper har forskellige instruktioner om fejlfejl. Som standard bruger de en smart politikinstruktion. Når planlæggeren starter, søger den efter eventuelle vedvarende udløsere, der er fejlagtigt. Derefter opdateres den hver af dem baseret på deres individuelt konfigurerede instruktioner om fejlagtig brand.

Lad os se på eksemplerne nedenfor:

Trigger misFiredTriggerA = TriggerBuilder.newTrigger () .startAt (DateUtils.addSeconds (ny dato (), -10)) .build (); Trigger misFiredTriggerB = TriggerBuilder.newTrigger () .startAt (DateUtils.addSeconds (new Date (), -10)) .withSchedule (SimpleScheduleBuilder.simpleSchedule () .withMisfireHandlingInstructionFireNow ()) .build ();

Vi har planlagt, at udløseren skal køre for 10 sekunder siden (så det er 10 sekunder forsinket, når den oprettes) for at simulere en fejlfejl, f.eks. fordi planlæggeren var nede eller ikke havde en tilstrækkelig mængde medarbejdertråde tilgængelig. Selvfølgelig ville vi i et virkeligt scenarie aldrig planlægge udløsere som denne.

I den første trigger (misFiredTriggerA) der er ikke angivet nogen instruktioner til håndtering af fejl ved brand Derfor kaldes det smart politik bruges i så fald og kaldes: withMisfireHandlingInstructionFireNow (). Dette betyder, at jobbet udføres umiddelbart efter, at planlæggeren opdager fejltændingen.

Den anden udløser definerer eksplicit, hvilken form for adfærd vi forventer, når der opstår misfiring. I dette eksempel sker det bare at være den samme smarte politik.

6.3. SimpleTrigger

SimpleTrigger bruges til scenarier, hvor vi har brug for at udføre et job på et bestemt tidspunkt. Dette kan enten være nøjagtigt en gang eller gentagne gange med bestemte intervaller.

Et eksempel kan være at fyre en jobudførelse nøjagtigt kl. 12.20 den 13. januar 2018. Tilsvarende kan vi starte på det tidspunkt og derefter fem gange mere hvert tiende sekund.

I koden nedenfor, datoen myStartTime er tidligere blevet defineret og bruges til at oprette en trigger til en bestemt tidsstempel:

SimpleTrigger trigger = (SimpleTrigger) TriggerBuilder.newTrigger () .withIdentity ("trigger1", "group1") .startAt (myStartTime) .forJob ("job1", "group1") .build ();

Lad os derefter bygge en udløser til et bestemt tidspunkt og gentage derefter hvert tiende sekund ti gange:

SimpleTrigger trigger = (SimpleTrigger) TriggerBuilder.newTrigger () .withIdentity ("trigger2", "group1") .startAt (myStartTime) .withSchedule (simpleSchedule () .withIntervalInSeconds (10) .withRepeatCount (10)). "ForJob (" job) " ) .build ();

6.4. CronTrigger

Det CronTrigger bruges, når vi har brug for tidsplaner baseret på kalenderlignende udsagn. For eksempel kan vi specificere fyringsplaner som f.eks hver fredag ​​kl eller hver hverdag kl. 9:30.

Cron-udtryk bruges til at konfigurere forekomster af CronTrigger. Disse udtryk består af Strenge der består af syv underudtryk. Vi kan læse mere om Cron-Expressions her.

I eksemplet nedenfor bygger vi en trigger, der affyrer hvert andet minut mellem kl. 8 og 17 hver dag:

CronTrigger trigger = TriggerBuilder.newTrigger () .withIdentity ("trigger3", "group1") .withSchedule (CronScheduleBuilder.cronSchedule ("0 0/2 8-17 * *?")) .ForJob ("myJob", "group1" ) .build ();

7. Konklusion

I denne artikel har vi vist, hvordan man bygger en Planlægning at udløse en Job. Vi så også nogle af de mest almindelige udløsermuligheder, der blev brugt: SimpleTrigger og CronTrigger.

Kvarts kan bruges til at oprette enkle eller komplekse tidsplaner til udførelse af snesevis, hundreder eller endda flere job. Flere oplysninger om rammen kan findes på hovedwebstedet.

Kildekoden til eksemplerne kan findes på GitHub.