Willkommen beim Spring Batch Beispiel. Spring Batch ist ein Modul des Spring Frameworks zur Ausführung von Stapelaufträgen. Wir können Spring Batch verwenden, um eine Reihe von Aufträgen zu verarbeiten.
Spring Batch Beispiel
Bevor wir das Beispielprogramm für Spring Batch durchgehen, erhalten wir eine Vorstellung von den Spring Batch-Terminologien.
- A job can consist of ‘n’ number of steps. Each step contains Read-Process-Write task or it can have single operation, which is called tasklet.
- Read-Process-Write bedeutet im Wesentlichen, aus einer Quelle wie einer Datenbank, einer CSV-Datei usw. zu lesen, die Daten zu verarbeiten und sie in eine Quelle wie eine Datenbank, eine CSV-Datei, eine XML-Datei usw. zu schreiben.
- Tasklet bedeutet die Ausführung einer einzelnen Aufgabe oder Operation, wie das Bereinigen von Verbindungen, das Freigeben von Ressourcen nach abgeschlossener Verarbeitung.
- Read-Process-Write und Tasklets können miteinander verkettet werden, um einen Auftrag auszuführen.
Spring Batch Beispiel
Lassen Sie uns ein Arbeitsbeispiel für die Implementierung von Spring Batch betrachten. Wir werden das folgende Szenario für die Implementierungszwecke berücksichtigen. Eine CSV-Datei mit Daten muss als XML konvertiert werden, wobei die Daten und Tags nach dem Spaltennamen benannt werden. Unten sind die wichtigen Tools und Bibliotheken, die für das Spring Batch Beispiel verwendet werden.
- Apache Maven 3.5.0 – für Projektbau und Abhängigkeitsverwaltung.
- Eclipse Oxygen Release 4.7.0 – IDE zur Erstellung von Spring Batch Maven-Anwendungen.
- Java 1.8
- Spring Core 4.3.12.RELEASE
- Spring OXM 4.3.12.RELEASE
- Spring JDBC 4.3.12.RELEASE
- Spring Batch 3.0.8.RELEASE
- MySQL Java-Treiber 5.1.25 – verwenden Sie ihn entsprechend Ihrer MySQL-Installation. Dies ist für die Spring Batch-Metadatentabellen erforderlich.
Verzeichnisstruktur für Spring Batch-Beispiel
Das folgende Bild veranschaulicht alle Komponenten unseres Spring Batch-Beispielprojekts.
Spring Batch Maven-Abhängigkeiten
Im Folgenden finden Sie den Inhalt der pom.xml-Datei mit allen erforderlichen Abhängigkeiten für unser Spring Batch-Beispielprojekt.
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.journaldev.spring</groupId>
<artifactId>SpringBatchExample</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>SpringBatchDemo</name>
<url>https://maven.apache.org</url>
<properties>
<jdk.version>1.8</jdk.version>
<spring.version>4.3.12.RELEASE</spring.version>
<spring.batch.version>3.0.8.RELEASE</spring.batch.version>
<mysql.driver.version>5.1.25</mysql.driver.version>
<junit.version>4.11</junit.version>
</properties>
<dependencies>
<!-- Spring Core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Spring jdbc, for database -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Spring XML to/back object -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- MySQL database driver -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.driver.version}</version>
</dependency>
<!-- Spring Batch dependencies -->
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-core</artifactId>
<version>${spring.batch.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-infrastructure</artifactId>
<version>${spring.batch.version}</version>
</dependency>
<!-- Spring Batch unit test -->
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-test</artifactId>
<version>${spring.batch.version}</version>
</dependency>
<!-- Junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.10</version>
</dependency>
</dependencies>
<build>
<finalName>spring-batch</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.9</version>
<configuration>
<downloadSources>true</downloadSources>
<downloadJavadocs>false</downloadJavadocs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>${jdk.version}</source>
<target>${jdk.version}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Spring Batch Verarbeitung von CSV-Eingabedateien
Hier ist der Inhalt unserer Beispieldatei im CSV-Format für die Spring Batch Verarbeitung.
1001,Tom,Moody, 29/7/2013
1002,John,Parker, 30/7/2013
1003,Henry,Williams, 31/7/2013
Spring Batch Job Konfiguration
Wir müssen eine Frühlingsbohne und einen Spring Batch-Job in einer Konfigurationsdatei definieren. Nachfolgend finden Sie der Inhalt der Datei job-batch-demo.xml
, die den wichtigsten Teil des Spring Batch-Projekts darstellt.
<beans xmlns="https://www.springframework.org/schema/beans"
xmlns:batch="https://www.springframework.org/schema/batch" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://www.springframework.org/schema/batch
https://www.springframework.org/schema/batch/spring-batch-3.0.xsd
https://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans-4.3.xsd
">
<import resource="../config/context.xml" />
<import resource="../config/database.xml" />
<bean id="report" class="com.journaldev.spring.model.Report"
scope="prototype" />
<bean id="itemProcessor" class="com.journaldev.spring.CustomItemProcessor" />
<batch:job id="DemoJobXMLWriter">
<batch:step id="step1">
<batch:tasklet>
<batch:chunk reader="csvFileItemReader" writer="xmlItemWriter"
processor="itemProcessor" commit-interval="10">
</batch:chunk>
</batch:tasklet>
</batch:step>
</batch:job>
<bean id="csvFileItemReader" class="org.springframework.batch.item.file.FlatFileItemReader">
<property name="resource" value="classpath:csv/input/report.csv" />
<property name="lineMapper">
<bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
<property name="lineTokenizer">
<bean
class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
<property name="names" value="id,firstname,lastname,dob" />
</bean>
</property>
<property name="fieldSetMapper">
<bean class="com.journaldev.spring.ReportFieldSetMapper" />
<!-- if no data type conversion, use BeanWrapperFieldSetMapper to map
by name <bean class="org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper">
<property name="prototypeBeanName" value="report" /> </bean> -->
</property>
</bean>
</property>
</bean>
<bean id="xmlItemWriter" class="org.springframework.batch.item.xml.StaxEventItemWriter">
<property name="resource" value="file:xml/outputs/report.xml" />
<property name="marshaller" ref="reportMarshaller" />
<property name="rootTagName" value="report" />
</bean>
<bean id="reportMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="classesToBeBound">
<list>
<value>com.journaldev.spring.model.Report</value>
</list>
</property>
</bean>
</beans>
- Wir verwenden
FlatFileItemReader
, um die CSV-Datei zu lesen,CustomItemProcessor
, um die Daten zu verarbeiten, und schreiben sie mitStaxEventItemWriter
in eine XML-Datei. batch:job
– Dieses Tag definiert den Job, den wir erstellen möchten. Die ID-Eigenschaft gibt die ID des Jobs an. Wir können mehrere Jobs in einer einzigen XML-Datei definieren.batch:step
– Dieses Tag wird verwendet, um verschiedene Schritte eines Spring Batch-Jobs zu definieren.- Zwei verschiedene Arten von Verarbeitungsstilen werden vom Spring Batch Framework angeboten, nämlich „TaskletStep Oriented“ und „Chunk Oriented“. Der Chunk-Oriented-Stil, der in diesem Beispiel verwendet wird, bezieht sich darauf, die Daten einzeln zu lesen und ‚Chunks‘ zu erstellen, die innerhalb einer Transaktionsgrenze geschrieben werden.
- reader: Spring Bean, der zum Lesen der Daten verwendet wird. In diesem Beispiel haben wir das
csvFileItemReader
-Bean verwendet, das eine Instanz vonFlatFileItemReader
ist. - processor: Dies ist die Klasse, die zum Verarbeiten der Daten verwendet wird. In diesem Beispiel haben wir
CustomItemProcessor
verwendet. - writer: Bean, der verwendet wird, um Daten in eine XML-Datei zu schreiben.
- commit-interval: Diese Eigenschaft definiert die Größe des Chunks, der einmal die Verarbeitung abgeschlossen ist, committed wird. Im Wesentlichen bedeutet dies, dass der ItemReader die Daten einzeln liest und der ItemProcessor sie auf die gleiche Weise verarbeitet, aber der ItemWriter die Daten nur schreibt, wenn sie die Größe des Commit-Intervalls erreichen.
- Drei wichtige Schnittstellen, die im Rahmen dieses Projekts verwendet werden, sind
ItemReader
,ItemProcessor
undItemWriter
aus dem Paketorg.springframework.batch.item
.
Spring Batch Model Class
Zuerst lesen wir die CSV-Datei in ein Java-Objekt ein und verwenden dann JAXB, um sie in eine XML-Datei zu schreiben. Hier ist unsere Model-Klasse mit den erforderlichen JAXB Annotations.
package com.journaldev.spring.model;
import java.util.Date;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "record")
public class Report {
private int id;
private String firstName;
private String lastName;
private Date dob;
@XmlAttribute(name = "id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@XmlElement(name = "firstname")
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
@XmlElement(name = "lastname")
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
@XmlElement(name = "dob")
public Date getDob() {
return dob;
}
public void setDob(Date dob) {
this.dob = dob;
}
@Override
public String toString() {
return "Report [id=" + id + ", firstname=" + firstName + ", lastName=" + lastName + ", DateOfBirth=" + dob
+ "]";
}
}
Beachten Sie, dass die Felder der Model-Klasse mit denen in der Spring Batch Mapper-Konfiguration übereinstimmen sollten, d. h. property name="names" value="id,firstname,lastname,dob"
in unserem Fall.
Spring Batch FieldSetMapper
A custom FieldSetMapper
is needed to convert a Date. If no data type conversion is required, then only BeanWrapperFieldSetMapper
should be used to map the values by name automatically. The java class which extends FieldSetMapper
is ReportFieldSetMapper
.
package com.journaldev.spring;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import org.springframework.batch.item.file.mapping.FieldSetMapper;
import org.springframework.batch.item.file.transform.FieldSet;
import org.springframework.validation.BindException;
import com.journaldev.spring.model.Report;
public class ReportFieldSetMapper implements FieldSetMapper {
private SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
public Report mapFieldSet(FieldSet fieldSet) throws BindException {
Report report = new Report();
report.setId(fieldSet.readInt(0));
report.setFirstName(fieldSet.readString(1));
report.setLastName(fieldSet.readString(2));
// Standardformat yyyy-MM-dd
// fieldSet.readDate(4);
String date = fieldSet.readString(3);
try {
report.setDob(dateFormat.parse(date));
} catch (ParseException e) {
e.printStackTrace();
}
return report;
}
}
Spring Batch Item Processor
Wie in der Job-Konfiguration festgelegt, wird ein ItemProcessor vor dem ItemWriter ausgeführt. Wir haben eine Klasse CustomItemProcessor.java
dafür erstellt.
package com.journaldev.spring;
import org.springframework.batch.item.ItemProcessor;
import com.journaldev.spring.model.Report;
public class CustomItemProcessor implements ItemProcessor<Report, Report> {
public Report process(Report item) throws Exception {
System.out.println("Processing..." + item);
String fname = item.getFirstName();
String lname = item.getLastName();
item.setFirstName(fname.toUpperCase());
item.setLastName(lname.toUpperCase());
return item;
}
}
Wir können Daten in der ItemProcessor-Implementierung manipulieren, wie Sie sehen können, dass ich Vor- und Nachnamen in Großbuchstaben umwandle.
Spring-Konfigurationsdateien
In unserer Spring-Batch-Konfigurationsdatei haben wir zwei zusätzliche Konfigurationsdateien importiert – context.xml
und database.xml
.
<beans xmlns="https://www.springframework.org/schema/beans"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
https://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
<!-- stored job-meta in memory -->
<!--
<bean id="jobRepository"
class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean">
<property name="transactionManager" ref="transactionManager" />
</bean>
-->
<!-- stored job-meta in database -->
<bean id="jobRepository"
class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="transactionManager" ref="transactionManager" />
<property name="databaseType" value="mysql" />
</bean>
<bean id="transactionManager"
class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />
<bean id="jobLauncher"
class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
</bean>
</beans>
- jobRepository – Das JobRepository ist dafür verantwortlich, jedes Java-Objekt in seine richtige Metadatentabelle für Spring Batch zu speichern.
- transactionManager – Dies ist dafür verantwortlich, die Transaktion zu bestätigen, sobald die Größe des Commit-Intervalls und die verarbeiteten Daten gleich sind.
- jobLauncher – Dies ist das Herzstück von Spring Batch. Diese Schnittstelle enthält die Run-Methode, die verwendet wird, um den Job auszulösen.
<beans xmlns="https://www.springframework.org/schema/beans"
xmlns:jdbc="https://www.springframework.org/schema/jdbc" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans-4.3.xsd
https://www.springframework.org/schema/jdbc
https://www.springframework.org/schema/jdbc/spring-jdbc-4.3.xsd">
<!-- connect to database -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/Test" />
<property name="username" value="test" />
<property name="password" value="test123" />
</bean>
<bean id="transactionManager"
class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />
<!-- create job-meta tables automatically -->
<!-- <jdbc:initialize-database data-source="dataSource"> <jdbc:script location="org/springframework/batch/core/schema-drop-mysql.sql"
/> <jdbc:script location="org/springframework/batch/core/schema-mysql.sql"
/> </jdbc:initialize-database> -->
</beans>
Spring Batch verwendet einige Metadatentabellen, um Informationen zu Batch-Jobs zu speichern. Wir können sie aus den Spring-Batch-Konfigurationen erstellen lassen, aber es ist ratsam, dies manuell durch Ausführen der SQL-Dateien zu tun, wie im kommentierten Code oben zu sehen ist. Aus Sicherheitssicht ist es besser, dem Spring-Batch-Datenbankbenutzer keinen DDL-Ausführungszugriff zu geben.
Spring Batch-Tabellen
Spring Batch-Tabellen entsprechen den Domain-Objekten, die sie in Java darstellen, sehr genau. Zum Beispiel – JobInstance, JobExecution, JobParameters und StepExecution werden jeweils BATCH_JOB_INSTANCE, BATCH_JOB_EXECUTION, BATCH_JOB_EXECUTION_PARAMS und BATCH_STEP_EXECUTION zugeordnet. ExecutionContext wird sowohl BATCH_JOB_EXECUTION_CONTEXT als auch BATCH_STEP_EXECUTION_CONTEXT zugeordnet. Das JobRepository ist dafür verantwortlich, jedes Java-Objekt in seine richtige Tabelle zu speichern und zu speichern. Nachfolgend finden Sie die Details jeder Metadatentabelle.
- Batch_job_instance: Die Tabelle BATCH_JOB_INSTANCE enthält alle relevanten Informationen zu einer JobInstance.
- Batch_job_execution_params: Die Tabelle BATCH_JOB_EXECUTION_PARAMS enthält alle relevanten Informationen zum JobParameters-Objekt.
- Batch_job_execution: Die Tabelle BATCH_JOB_EXECUTION enthält Daten zum JobExecution-Objekt. Eine neue Zeile wird jedes Mal hinzugefügt, wenn ein Job ausgeführt wird.
- Batch_step_execution: Die Tabelle BATCH_STEP_EXECUTION enthält alle relevanten Informationen zum StepExecution-Objekt.
- Batch_job_execution_context: Die Tabelle BATCH_JOB_EXECUTION_CONTEXT enthält Daten zum ExecutionContext eines Jobs. Für jede JobExecution gibt es genau einen Job-ExecutionContext, der alle jobbezogenen Daten enthält, die für diese bestimmte Jobausführung benötigt werden. Diese Daten stellen typischerweise den Zustand dar, der nach einem Fehler abgerufen werden muss, damit eine JobInstance von dem Punkt aus neu gestartet werden kann, an dem sie fehlgeschlagen ist.
- Batch_step_execution_context: Die Tabelle BATCH_STEP_EXECUTION_CONTEXT enthält Daten, die für den ExecutionContext eines Schritts relevant sind. Für jede StepExecution gibt es genau einen ExecutionContext, der alle Daten enthält, die für eine bestimmte Schrittausführung gespeichert werden müssen. Diese Daten stellen typischerweise den Zustand dar, der nach einem Fehler wiederhergestellt werden muss, damit eine JobInstance von dem Punkt aus neu gestartet werden kann, an dem der Fehler aufgetreten ist.
- Batch_job_execution_seq: Diese Tabelle enthält die Daten zur Ausführungsreihenfolge des Jobs.
- Batch_step_execution_seq: Diese Tabelle enthält die Daten zur Sequenz für die Schrittausführung.
- Batch_job_seq: Diese Tabelle enthält die Daten zur Reihenfolge des Jobs. Falls wir mehrere Jobs haben, erhalten wir mehrere Zeilen.
Spring Batch Testprogramm
Unser Beispielprojekt für Spring Batch ist fertig. Der letzte Schritt besteht darin, eine Testklasse zu schreiben, um es als Java-Programm auszuführen.
package com.journaldev.spring;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
String[] springConfig = { "spring/batch/jobs/job-batch-demo.xml" };
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(springConfig);
JobLauncher jobLauncher = (JobLauncher) context.getBean("jobLauncher");
Job job = (Job) context.getBean("DemoJobXMLWriter");
JobParameters jobParameters = new JobParametersBuilder().addLong("time", System.currentTimeMillis())
.toJobParameters();
try {
JobExecution execution = jobLauncher.run(job, jobParameters);
System.out.println("Exit Status : " + execution.getStatus());
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Done");
context.close();
}
}
Führen Sie einfach das obige Programm aus, und Sie erhalten eine Ausgabe-XML wie unten angegeben.
<?xml version="1.0" encoding="UTF-8"?><report><record id="1001"><dob>2013-07-29T00:00:00+05:30</dob><firstname>TOM</firstname><lastname>MOODY</lastname></record><record id="1002"><dob>2013-07-30T00:00:00+05:30</dob><firstname>JOHN</firstname><lastname>PARKER</lastname></record><record id="1003"><dob>2013-07-31T00:00:00+05:30</dob><firstname>HENRY</firstname><lastname>WILLIAMS</lastname></record></report>
Das ist alles für das Beispiel Spring Batch. Sie können das endgültige Projekt über den untenstehenden Link herunterladen.
Spring Batch Beispielprojekt herunterladen
Referenz: Offizieller Leitfaden
Source:
https://www.digitalocean.com/community/tutorials/spring-batch-example