Inleiding tot Spring Batch

1. Inleiding

In dit artikel gaan we ons concentreren op een praktische, codegerichte introductie van Spring Batch. Spring Batch is een verwerkingsraamwerk dat is ontworpen voor een robuuste uitvoering van taken.

Het is de huidige versie 3.0, die Spring 4 en Java 8 ondersteunt. Het is ook geschikt voor JSR-352, wat een nieuwe Java-specificatie is voor batchverwerking.

Hier zijn een paar interessante en praktische use-cases van het framework.

2. Workflow Basics

Spring batch volgt de traditionele batcharchitectuur, waarbij een jobrepository het werk van de job inroostert en ermee communiceert.

Een taak kan uit meer dan één stap bestaan ​​- en elke stap volgt doorgaans de volgorde van het lezen, verwerken en schrijven van gegevens.

En natuurlijk zal het raamwerk hier het meeste van het zware werk voor ons doen - vooral als het gaat om het lage persistentiewerk van het omgaan met de banen - met behulp van sqlite voor de vacaturebank.

2.1. Ons voorbeeldgebruik

De eenvoudige usecase die we hier gaan aanpakken, is: we gaan enkele financiële transactiegegevens migreren van CSV naar XML.

Het invoerbestand heeft een zeer eenvoudige structuur - het bevat een transactie per regel, bestaande uit: een gebruikersnaam, het gebruikers-ID, de datum van de transactie en het bedrag:

gebruikersnaam, gebruikers-ID, transactiedatum, transactiebedrag devendra, 1234, 31/10/2015, 10000 john, 2134, 3/12/2015, 12321 robin, 2134, 2/02/2015, 23411

3. De Maven POM

Afhankelijkheden die voor dit project vereist zijn, zijn veerkern, veerbatch en sqlite jdbc-aansluiting:

   org.xerial sqlite-jdbc 3.15.1 org.springframework spring-oxm 5.2.0.RELEASE org.springframework spring-jdbc 5.2.0.RELEASE org.springframework.batch spring-batch-core 4.2.0.RELEASE 

4. Veerbatchconfiguratie

Het eerste wat we zullen doen is Spring Batch configureren met XML:

Uiteraard is er ook een Java-configuratie beschikbaar:

@Configuration @EnableBatchProcessing openbare klasse SpringConfig {@Value ("org / springframework / batch / core / schema-drop-sqlite.sql") privé Resource dropReopsitoryTables; @Value ("org / springframework / batch / core / schema-sqlite.sql") privé Resource dataReopsitorySchema; @Bean openbare DataSource dataSource () {DriverManagerDataSource dataSource = nieuwe DriverManagerDataSource (); dataSource.setDriverClassName ("org.sqlite.JDBC"); dataSource.setUrl ("jdbc: sqlite: repository.sqlite"); retourneer dataSource; } @Bean openbare DataSourceInitializer dataSourceInitializer (DataSource dataSource) gooit MalformedURLException {ResourceDatabasePopulator databasePopulator = nieuwe ResourceDatabasePopulator (); databasePopulator.addScript (dropReopsitoryTables); databasePopulator.addScript (dataReopsitorySchema); databasePopulator.setIgnoreFailedDrops (true); DataSourceInitializer initializer = nieuwe DataSourceInitializer (); initializer.setDataSource (dataSource); initializer.setDatabasePopulator (databasePopulator); terugkeer initializer; } private JobRepository getJobRepository () gooit uitzondering {JobRepositoryFactoryBean factory = nieuwe JobRepositoryFactoryBean (); factory.setDataSource (dataSource ()); factory.setTransactionManager (getTransactionManager ()); factory.afterPropertiesSet (); return (JobRepository) factory.getObject (); } private PlatformTransactionManager getTransactionManager () {retourneer nieuwe ResourcelessTransactionManager (); } openbare JobLauncher getJobLauncher () gooit uitzondering {SimpleJobLauncher jobLauncher = nieuwe SimpleJobLauncher (); jobLauncher.setJobRepository (getJobRepository ()); jobLauncher.afterPropertiesSet (); terug jobLauncher; }}

5. Spring Batch Job Config

Laten we nu onze functiebeschrijving schrijven voor het CSV-naar-XML-werk:

                           com.baeldung.spring_batch_intro.model.Transaction 

En natuurlijk, de vergelijkbare op Java gebaseerde taakconfiguratie:

openbare klasse SpringBatchConfig {@Autowired privé JobBuilderFactory-banen; @Autowired private StepBuilderFactory stappen; @Value ("input / record.csv") privébron inputCsv; @Value ("bestand: xml / output.xml") privé Resource outputXml; @Bean openbare ItemReader itemReader () gooit UnexpectedInputException, ParseException {FlatFileItemReader reader = new FlatFileItemReader (); DelimitedLineTokenizer tokenizer = nieuwe DelimitedLineTokenizer (); String [] tokens = {"gebruikersnaam", "userid", "transactiondate", "amount"}; tokenizer.setNames (tokens); reader.setResource (inputCsv); DefaultLineMapper lineMapper = nieuwe DefaultLineMapper (); lineMapper.setLineTokenizer (tokenizer); lineMapper.setFieldSetMapper (nieuwe RecordFieldSetMapper ()); reader.setLineMapper (lineMapper); terug lezer; } @Bean public ItemProcessor itemProcessor () {retourneer nieuwe CustomItemProcessor (); } @Bean openbare ItemWriter itemWriter (Marshaller marshaller) gooit MalformedURLException {StaxEventItemWriter itemWriter = nieuwe StaxEventItemWriter (); itemWriter.setMarshaller (marshaller); itemWriter.setRootTagName ("transactionRecord"); itemWriter.setResource (outputXml); retourneer itemWriter; } @Bean openbare Marshaller marshaller () {Jaxb2Marshaller marshaller = nieuwe Jaxb2Marshaller (); marshaller.setClassesToBeBound (nieuwe klasse [] {Transaction.class}); terugkeer marshaller; } @Bean protected Step step1 (ItemReader-lezer, ItemProcessor-processor, ItemWriter-schrijver) {return steps.get ("step1"). chunk (10) .reader (lezer) .processor (processor) .writer (schrijver) .build (); } @Bean (name = "firstBatchJob") openbare Job job (@Qualifier ("step1") Stap step1) {return jobs.get ("firstBatchJob"). Start (step1) .build (); }}

OK, dus nu we de hele configuratie hebben, laten we het opsplitsen en beginnen met het bespreken ervan.

5.1. Lees gegevens en maak objecten met ItemReader

Eerst hebben we het cvsFileItemReader die de gegevens van de record.csv en zet het om in het Transactie voorwerp:

@SuppressWarnings ("beperking") @XmlRootElement (naam = "transactionRecord") openbare klasse Transaction {private String gebruikersnaam; private int userId; privé LocalDateTime transactionDate; privé dubbel bedrag; / * getters en setters voor de attributen * / @Override public String toString () {return "Transaction [gebruikersnaam =" + gebruikersnaam + ", userId =" + userId + ", transactionDate =" + transactionDate + ", amount =" + bedrag + "]"; }}

Om dit te doen - het gebruikt een aangepaste mapper:

openbare klasse RecordFieldSetMapper implementeert FieldSetMapper {openbare transactie mapFieldSet (FieldSet fieldSet) gooit BindException {DateTimeFormatter-formatter = DateTimeFormatter.ofPattern ("d / M / jjj"); Transactietransactie = nieuwe transactie (); transaction.setUsername (fieldSet.readString ("gebruikersnaam")); transactie.setUserId (fieldSet.readInt (1)); transactie.setAmount (fieldSet.readDouble (3)); String dateString = fieldSet.readString (2); transaction.setTransactionDate (LocalDate.parse (dateString, formatter) .atStartOfDay ()); retourtransactie; }}

5.2. Gegevens verwerken met ItemProcessor

We hebben onze eigen itemprocessor gemaakt, CustomItemProcessor. Dit verwerkt niets gerelateerd aan het transactieobject - het geeft alleen het originele object van de lezer door aan de schrijver:

openbare klasse CustomItemProcessor implementeert ItemProcessor {openbaar transactieproces (transactie-item) {retouritem; }}

5.3. Objecten naar de FS schrijven met ItemWriter

Ten slotte gaan we dit opslaan transactie naar een xml-bestand op xml / output.xml:

5.4. De batchopdracht configureren

Dus alles wat we hoeven te doen is de punten met een taak verbinden - met behulp van de batch: taak syntaxis.

Merk op commit-interval - dat is het aantal transacties dat in het geheugen moet worden bewaard voordat de batch naar het itemWriter; het houdt de transacties in het geheugen tot dat punt (of totdat het einde van de invoergegevens wordt aangetroffen):

5.5. De batch-taak uitvoeren

Dat is alles - laten we nu alles instellen en uitvoeren:

openbare klasse App {openbare statische leegte hoofd (String [] args) {// Spring Java-configuratie AnnotationConfigApplicationContext context = nieuwe AnnotationConfigApplicationContext (); context.register (SpringConfig.class); context.register (SpringBatchConfig.class); context.refresh (); JobLauncher jobLauncher = (JobLauncher) context.getBean ("jobLauncher"); Job job = (Job) context.getBean ("firstBatchJob"); System.out.println ("De batchtaak wordt gestart"); probeer {JobExecution-uitvoering = jobLauncher.run (job, nieuwe JobParameters ()); System.out.println ("Taakstatus:" + execution.getStatus ()); System.out.println ("Taak voltooid"); } catch (uitzondering e) {e.printStackTrace (); System.out.println ("Taak mislukt"); }}}

6. Conclusie

Deze tutorial geeft je een basisidee van hoe te werken met Spring Batch en hoe u het in een eenvoudig gebruik kunt gebruiken.

Het laat zien hoe u eenvoudig uw batchverwerkingspijplijn kunt ontwikkelen en hoe u verschillende stadia in lezen, verwerken en schrijven kunt aanpassen.

De volledige implementatie van deze tutorial is te vinden in het github-project - dit is een op Eclipse gebaseerd project, dus het zou gemakkelijk te importeren en uit te voeren moeten zijn zoals het is.