Spring Boot With Spring Batch

1. Oversigt

Spring Batch er en stærk ramme til udvikling af robuste batchapplikationer. I vores tidligere vejledning introducerede vi Spring Batch.

I denne vejledning bygger vi på den foregående og lærer, hvordan man opsætter og opretter en grundlæggende batchdrevet applikation ved hjælp af Spring Boot.

2. Maven-afhængigheder

Lad os først tilføje spring-boot-starter-batch til vores pom.xml:

 org.springframework.boot spring-boot-starter-batch 2.4.0.RELEASE 

Vi tilføjer også org.hsqldb afhængighed, som også er tilgængelig fra Maven Central:

 org.hsqldb hsqldb 2.5.1 runtime 

3. Definition af et simpelt springbatchjob

Vi skal opbygge et job, der importerer en kaffeliste fra en CSV-fil, transformerer den ved hjælp af en brugerdefineret processor og gemmer de endelige resultater i en in-memory database.

3.1. Kom godt i gang

Lad os starte med at definere vores applikationsindgangspunkt:

@SpringBootApplication public class SpringBootBatchProcessingApplication {public static void main (String [] args) {SpringApplication.run (SpringBootBatchProcessingApplication.class, args); }}

Som vi kan se, er dette en standard Spring Boot-applikation. Da vi ønsker at bruge standardkonfigurationsværdier, hvor det er muligt, skal vi bruge et meget let sæt applikationskonfigurationsegenskaber.

Vi definerer disse egenskaber i vores src / main / resources / application.properties fil:

file.input = kaffe-liste.csv

Denne egenskab indeholder placeringen af ​​vores input-kaffeliste. Hver linje indeholder vores kaffes mærke, oprindelse og nogle egenskaber:

Blue Mountain, Jamaica, Fruity Lavazza, Colombia, Strong Folgers, America, Smokey

Som vi skal se, er dette en flad CSV-fil, hvilket betyder, at Spring kan håndtere det uden nogen speciel tilpasning.

Dernæst tilføjer vi et SQL-script schema-all.sql at skabe vores kaffe tabel til at gemme dataene:

DROP TABELkaffe, HVIS DET FINDES; OPRET TABELkaffe (kaffe_id BIGINT IDENTITET IKKE NULL PRIMÆR NØGLE, mærke VARCHAR (20), oprindelse VARCHAR (20), egenskaber VARCHAR (30));

Spring Boot kører bekvemt dette script automatisk under opstart.

3.2. Kaffe domæne klasse

Derefter har vi brug for en simpel domæneklasse til at holde vores kaffeprodukter:

offentlig klasse kaffe {private String brand; privat String oprindelse; private strengegenskaber; offentlig kaffe (String-mærke, String-oprindelse, String-egenskaber) {this.brand = brand; denne. oprindelse = oprindelse; dette. egenskaber = egenskaber; } // getters og setters}

Som tidligere nævnt, vores Kaffe objekt indeholder tre egenskaber:

  • Et mærke
  • En oprindelse
  • Nogle yderligere egenskaber

4. Jobkonfiguration

Nu, videre til nøglekomponenten, vores jobkonfiguration. Vi går trin for trin, opbygger vores konfiguration og forklarer hver del undervejs:

@Configuration @EnableBatchProcessing public class BatchConfiguration {@Autowired public JobBuilderFactory jobBuilderFactory; @Autowired offentlig StepBuilderFactory stepBuilderFactory; @Value ("$ {file.input}") privat streng filinput; // ...}

For det første starter vi med en standard forår @Konfiguration klasse. Dernæst tilføjer vi en @EnableBatchProcessing kommentar til vores klasse. Især giver dette os adgang til mange nyttige bønner, der understøtter job og vil spare os for meget benarbejde.

Desuden giver brugen af ​​denne kommentar os også adgang til to nyttige fabrikker, som vi bruger senere, når vi bygger vores jobkonfiguration og jobtrin.

I den sidste del af vores oprindelige konfiguration inkluderer vi en henvisning til file.input ejendom, vi tidligere har erklæret.

4.1. En læser og forfatter til vores job

Nu kan vi gå videre og definere en læserbønne i vores konfiguration:

@Bean offentlig FlatFileItemReader-læser () {returner ny FlatFileItemReaderBuilder (). Navn ("coffeeItemReader") .resource (ny ClassPathResource (fileInput)) .delimiteret () .navne (ny String [] {"brand", "origin", " egenskaber "}) .fieldSetMapper (ny BeanWrapperFieldSetMapper () {{setTargetType (Coffee.class);}}) .build (); }

Kort sagt, vores læserbønne defineret ovenfor ser efter en fil, der hedder kaffe-liste.csv og analyserer hver linjepost i en Kaffe objekt.

På samme måde definerer vi en forfatterbønne:

@Bean offentlig JdbcBatchItemWriter-skribent (DataSource dataSource) {returner ny JdbcBatchItemWriterBuilder () .itemSqlParameterSourceProvider (nyt BeanPropertyItemSqlParameterSourceProvider ()) .sql ("INSERT INTO-egenskab) .dataSource (dataSource) .build (); }

Denne gang inkluderer vi den SQL-sætning, der er nødvendig for at indsætte et enkelt kaffeprodukt i vores database, drevet af vores Java-bønneegenskaber Kaffe objekt. Nemt den datakilde oprettes automatisk af @EnableBatchProcessing kommentar.

4.2. Sætte vores job sammen

Endelig skal vi tilføje de aktuelle jobtrin og konfiguration:

@Bean public Job importUserJob (JobCompletionNotificationListener listener, Step step1) {return jobBuilderFactory.get ("importUserJob") .incrementer (new RunIdIncrementer ()) .listener (listener) .flow (step1) .end () .build (); } @Bean offentlige trin trin 1 (JdbcBatchItemWriter-forfatter) {returner stepBuilderFactory.get ("trin1"). klump (10) .læser (læser ()) .processor (processor ()). forfatter (forfatter) .build (); } @Bean offentlig CoffeeItemProcessor-processor () {returner ny CoffeeItemProcessor (); }

Som vi kan se, er vores job relativt simpelt og består af et trin defineret i trin 1 metode.

Lad os se på, hvad dette trin gør:

  • Først konfigurerer vi vores trin, så det vil skrive op til ti poster ad gangen ved hjælp af klump (10) erklæring
  • Derefter læser vi i kaffedataene ved hjælp af vores læserbønne, som vi indstiller ved hjælp af læser metode
  • Derefter sender vi hver af vores kaffeprodukter til en brugerdefineret processor, hvor vi anvender en brugerdefineret forretningslogik
  • Endelig skriver vi hvert kaffeprodukt til databasen ved hjælp af den forfatter, vi så tidligere

På den anden side vores importUserJob indeholder vores jobdefinition, som indeholder et id ved hjælp af indbygget RunIdIncrementer klasse. Vi indstiller også en JobFuldførelseNotifikationLytter, som vi bruger til at få besked, når jobbet er afsluttet.

For at fuldføre vores jobkonfiguration viser vi hvert trin (selvom dette job kun har et trin). Vi har nu et perfekt konfigureret job!

5. En brugerdefineret kaffeprocessor

Lad os se nærmere på den brugerdefinerede processor, vi tidligere definerede i vores jobkonfiguration:

offentlig klasse CoffeeItemProcessor implementerer ItemProcessor {privat statisk endelig Logger LOGGER = LoggerFactory.getLogger (CoffeeItemProcessor.class); @ Override offentlig kaffeproces (endelig kaffe kaffe) kaster undtagelse {String brand = coffee.getBrand (). ToUpperCase (); String origin = coffee.getOrigin (). ToUpperCase (); String chracteristics = coffee.getCharacteristics (). ToUpperCase (); Kaffe transformedCoffee = ny kaffe (mærke, oprindelse, chracteristics); LOGGER.info ("Konvertering ({}) til ({})", kaffe, transformedCoffee); return transformedCoffee; }}

Af særlig interesse er ItemProcessor interface giver os en mekanisme til at anvende en bestemt forretningslogik under vores jobudførelse.

For at holde tingene enkle, vi definerer vores CoffeeItemProcessor, som tager et input Kaffe objekt og transformerer hver af egenskaberne til store bogstaver.

6. Afslutning af job

Derudover skal vi også skrive en JobCompletionNotificationListener for at give feedback, når vores job er færdigt:

@ Overstyr offentlig ugyldighed efterJob (JobExecution jobExecution) {if (jobExecution.getStatus () == BatchStatus.COMPLETED) {LOGGER.info ("!!! JOB FERDIG! Tid til at bekræfte resultaterne"); Strengeforespørgsel = "VÆLG mærke, oprindelse, egenskaber FRA kaffe"; jdbcTemplate.query (forespørgsel, (rs, række) -> ny kaffe (rs.getString (1), rs.getString (2), rs.getString (3))) .forEach (kaffe -> LOGGER.info ("Fundet i databasen. ", kaffe)); }}

I ovenstående eksempel tilsidesætter vi efterJob metode og kontrollere det afsluttede job med succes. Desuden kører vi en triviel forespørgsel for at kontrollere, at hver kaffeart blev gemt i databasen med succes.

7. At køre vores job

Nu hvor vi har alt på plads til at køre vores job, her kommer den sjove del. Lad os gå videre og køre vores job:

... 17: 41: 16.336 [main] INFO c.b.b.JobCompletionNotificationListener - !!! JOB FÆRDIG! Tid til at verificere resultaterne 17: 41: 16.336 [main] INFO c.b.b.JobCompletionNotificationListener - Fundet i databasen. 17: 41: 16.337 [main] INFO c.b.b.JobCompletionNotificationListener - Fundet i databasen. 17: 41: 16.337 [main] INFO c.b.b.JobCompletionNotificationListener - Fundet i databasen. ... 

Som vi kan se, kørte vores job med succes, og hver kaffeart blev gemt i databasen som forventet.

8. Konklusion

I denne artikel har vi lært, hvordan man opretter et simpelt Spring Batch-job ved hjælp af Spring Boot. Først startede vi med at definere nogle grundlæggende konfigurationer.

Derefter så vi, hvordan man tilføjede en fillæser og databaseforfatter. Endelig kiggede vi på, hvordan vi anvendte tilpasset behandling og kontrollerede, at vores job blev udført med succes.

Som altid er artiklens fulde kildekode tilgængelig på GitHub.


$config[zx-auto] not found$config[zx-overlay] not found