Uvod u kvarc

1. Pregled

Kvarcni je okvir za planiranje poslova otvorenog koda napisan u cijelosti na Javi i dizajniran za upotrebu u obje J2SE i J2EE aplikacije. Nudi veliku fleksibilnost bez žrtvovanja jednostavnosti.

Možete stvoriti složene rasporede za izvršavanje bilo kojeg posla. Primjeri su npr. zadaci koji se izvode svakodnevno, svaki drugi petak u 19:30. ili samo posljednjeg dana u mjesecu.

U ovom ćemo članku pogledati elemente za izgradnju posla s kvarcnim API-jem. Za uvod u kombinaciji s proljećem preporučujemo zakazivanje za proljeće s kvarcom.

2. Ovisnosti Mavena

Moramo dodati sljedeću ovisnost na pom.xml:

 org.kvarc-planer kvarc 2.3.0 

Najnoviju verziju možete pronaći u spremištu Maven Central.

3. Kvarcni API

Srce okvira je Planer. Odgovorna je za upravljanje vremenskim okruženjem za našu aplikaciju.

Kako bi osigurao skalabilnost, Quartz se temelji na višenitnoj arhitekturi. Kada se pokrene, okvir inicijalizira skup radničkih niti koje koriste Planer izvršiti Poslovi.

Na ovaj način okvir može pokretati mnoge Poslovi istovremeno. Također se oslanja na slabo povezan skup ThreadPool upravljačke komponente za upravljanje okolinom niti.

Ključna sučelja API-ja su:

  • Planer - primarni API za interakciju s planerom okvira
  • Posao - sučelje koje će implementirati komponente koje želimo izvršiti
  • Pojedinosti o poslu - koristi se za definiranje primjera Posaos
  • Okidač - komponenta koja određuje raspored prema kojem se daje Posao izvršit će se
  • JobBuilder - koristi za izgradnju Pojedinosti o poslu instanci, koje definiraju instance Poslovi
  • TriggerBuilder - koristi za izgradnju Okidač instance

Pogledajmo svaku od tih komponenata.

4. Planer

Prije nego što počnemo koristiti Planer, treba ga instancirati. Da bismo to učinili, možemo koristiti tvornicu PlanerFactory:

SchedulerFactory schedulerFactory = novi StdSchedulerFactory (); Planer planera = schedulerFactory.getScheduler ();

A PlanerŽivotni ciklus ograničen je svojim stvaranjem, putem a PlanerFactory i poziv na svoj ugasiti() metoda. Jednom stvoren Planer sučelje se može koristiti za dodavanje, uklanjanje i popis Poslovi i Okidačii izvodite druge radnje povezane s raspoređivanjem (poput zaustavljanja okidača).

Međutim, the Planer neće djelovati ni na jedan okidač dok se ne pokrene s početak() metoda:

planer.start ();

5. Poslovi

A Posao je klasa koja implementira Posao sučelje. Ima samo jednu jednostavnu metodu:

javna klasa SimpleJob provodi Job {public void execute (JobExecutionContext arg0) baca JobExecutionException {System.out.println ("Ovo je kvarcni posao!"); }}

Kada Job’s okidač požara, izvršiti() metodu poziva jedna od radničkih niti planera.

The JobExecutionContext objekt koji se prosljeđuje ovoj metodi pruža instancu posla informacije o svom runtime okruženju, ručku za Planer koja ga je izvršila, ručka za Okidač koji je pokrenuo izvršenje, posla Pojedinosti o poslu objekt i nekoliko drugih predmeta.

The Pojedinosti o poslu objekt kreira kvarcni klijent u vrijeme dok Posao dodaje se u Planer. To je u osnovi definicija instance posla:

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

Ovaj objekt može sadržavati i različite postavke svojstava za Posao, kao i a JobDataMap, koji se mogu koristiti za pohranu podataka o stanju za određeni primjerak naše radne klase.

5.1. JobDataMap

The JobDataMap koristi se za čuvanje bilo koje količine podatkovnih objekata koje želimo učiniti dostupnima instanci posla kada se izvrši. JobDataMap je implementacija Jave Karta sučelje i ima neke dodane pogodne metode za pohranu i dohvaćanje podataka primitivnih tipova.

Evo primjera stavljanja podataka u JobDataMap dok je gradio Pojedinosti o poslu, prije dodavanja posla u planer:

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

I evo primjera kako pristupiti tim podacima tijekom izvršenja posla:

javna klasa SimpleJob implementira Job {public void execute (JobExecutionContext context) baca JobExecutionException {JobDataMap dataMap = context.getJobDetail (). getJobDataMap (); String jobSays = dataMap.getString ("jobSays"); float myFloatValue = dataMap.getFloat ("myFloatValue"); System.out.println ("Posao kaže:" + jobSays + ", a val je:" + myFloatValue); }}

Gornji primjer ispisat će "Posao kaže Pozdrav svijetu!", A val je 3,141 ".

Također možemo dodati metode postavljača u našu klasu posla koja odgovara imenima ključeva u JobDataMap.

Ako to učinimo, zadani Quartz JobFactory implementacija automatski poziva te postavljače kada je posao instanciran, čime se sprječava potreba da se izričito izvade vrijednosti s karte unutar naše metode izvršavanja.

6. Okidači

Okidač objekti koriste se za pokretanje izvršavanja Poslovi.

Kada želimo zakazati a Posao, moramo instancirati okidač i prilagoditi njegova svojstva kako bismo konfigurirali naše zahtjeve za raspoređivanje:

Okidač okidača = TriggerBuilder.newTrigger () .withIdentity ("myTrigger", "group1") .startNow () .withSchedule (SimpleScheduleBuilder.simpleSchedule () .withIntervalInSeconds (40) .repeatForever ()).

A Okidač može imati i JobDataMap povezano s tim. Ovo je korisno za prosljeđivanje parametara u Posao koji su specifični za izvršenja okidača.

Postoje različite vrste okidača za različite potrebe raspoređivanja. Svaka ima drugačije TriggerKey svojstva za praćenje njihovog identiteta. Međutim, neka druga svojstva zajednička su svim vrstama okidača:

  • The jobKey svojstvo označava identitet posla koji bi se trebao izvršiti kada se okidač aktivira.
  • The vrijeme početka svojstvo označava kada raspored okidača prvi put stupa na snagu. Vrijednost je a java.util.Datum objekt koji definira trenutak u vremenu za dati kalendarski datum. Za neke vrste okidača okidač se aktivira u zadano vrijeme početka. Za ostale to jednostavno označava vrijeme kada bi raspored trebao započeti.
  • The endTime svojstvo označava kada treba otkazati raspored okidača.

Kvarc se isporučuje s pregršt različitih vrsta okidača, ali najčešće korišteni su SimpleTrigger i CronTrigger.

6.1. Prioritet

Ponekad, kada imamo mnogo okidača, Quartz možda neće imati dovoljno resursa za trenutno pokretanje svih poslova koji se planiraju istodobno. U ovom slučaju, možda ćemo htjeti kontrolirati koji će od naših okidača biti dostupan prvi. To je upravo ono što prioritet svojstvo na okidaču koristi se za.

Na primjer, kada se istodobno aktivira deset okidača i budu dostupne samo četiri radne niti, prva četiri okidača s najvišim prioritetom prvo će se izvršiti. Kad na okidaču ne postavimo prioritet, on koristi zadani prioritet od pet. Bilo koja cjelobrojna vrijednost dopuštena je kao prioritet, pozitivna ili negativna.

U donjem primjeru imamo dva okidača s različitim prioritetom. Ako nema dovoljno resursa za istovremeno aktiviranje svih okidača, okidačA bit će prva koja će dobiti otkaz:

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

6.2. Upute za preskakanje paljenja

Prekid paljenja događa se ako je trajni okidač promašuje vrijeme pucanja zbog Planer se isključuje ili u slučaju da u spremištu niti Quartz-a nema raspoloživih niti.

Dostupne su različite upute za preskakanje paljenja za različite vrste okidača. Prema zadanim postavkama koriste pametne upute o pravilima. Kada se planer pokrene, traži trajne okidače koji su se pogrešno aktivirali. Nakon toga ažurira svakog od njih na temelju njihovih individualno konfiguriranih uputa za preskakanje paljenja.

Pogledajmo primjere u nastavku:

Okidač misFiredTriggerA = TriggerBuilder.newTrigger () .startAt (DateUtils.addSeconds (novi datum (), -10)) .build (); Okidač misFiredTriggerB = TriggerBuilder.newTrigger () .startAt (DateUtils.addSeconds (novi datum (), -10)). S Schedule (SimpleScheduleBuilder.simpleSchedule () .withMisfireHandlingInstructionFireNow ().)

Planirali smo pokretanje okidača prije 10 sekundi (tako da kasni 10 sekundi dok se stvori) kako bi simulirao preskakanje paljenja, npr. jer je rokovnik bio u kvaru ili nije imao na raspolaganju dovoljnu količinu radničkih niti. Naravno, u stvarnom scenariju nikada ne bismo zakazali ovakve okidače.

U prvom okidaču (misFiredTriggerA) nisu postavljene upute za rukovanje preskakanjem paljenja. Stoga zvani pametna politika koristi se u tom slučaju i naziva se: withMisfireHandlingInstructionFireNow (). To znači da se posao izvršava odmah nakon što planer otkrije prekid paljenja.

Drugi okidač izričito definira kakvo ponašanje očekujemo kada se dogodi pogrešno paljenje. U ovom je primjeru slučajno ista pametna politika.

6.3. SimpleTrigger

SimpleTrigger koristi se za scenarije u kojima posao moramo izvršiti u određenom trenutku. To može biti točno jednom ili više puta u određenim intervalima.

Primjer bi mogao biti otpuštanje izvršenja posla točno u 00:20:00, 13. siječnja 2018. Slično tome, možemo započeti u to vrijeme, a zatim još pet puta, svakih deset sekundi.

U donjem kodu, datum myStartTime je prethodno definiran i koristi se za izgradnju okidača za određenu vremensku oznaku:

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

Dalje, izgradimo okidač za određeni trenutak u vremenu, a zatim ponavljamo svakih deset sekundi deset puta:

Okidač SimpleTrigger = (SimpleTrigger) TriggerBuilder.newTrigger () .withIdentity ("trigger2", "group1") .startAt (myStartTime) .withSchedule (simpleSchedule () .withIntervalInSeconds (10) .withRepeatCountJ 10 (10)). ) .build ();

6.4. CronTrigger

The CronTrigger koristi se kada su nam potrebni rasporedi na temelju kalendarskih izjava. Na primjer, možemo odrediti planove pucanja kao što su svakog petka u podne ili svakog radnog dana u 9:30.

Cron-Expressions koriste se za konfiguriranje instanci CronTrigger. Ovi se izrazi sastoje od Žice koji se sastoje od sedam podizraza. Više o Cron-Expressionsima možemo pročitati ovdje.

U donjem primjeru gradimo okidač koji se aktivira svake druge minute između 8 i 17 sati, svaki dan:

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

7. Zaključak

U ovom smo članku pokazali kako izraditi Planer za pokretanje a Posao. Također smo vidjeli neke od najčešće korištenih opcija okidača: SimpleTrigger i CronTrigger.

Kvarc se može koristiti za stvaranje jednostavnih ili složenih rasporeda za izvršavanje desetaka, stotina ili čak više poslova. Više informacija o okviru možete pronaći na glavnoj web stranici.

Izvorni kod primjera može se naći na GitHubu.