In Ihren privaten oder beruflichen Projekten verarbeiten Sie teilweise große Datenmengen. Die Datenstapelverarbeitung ist eine effiziente Methode zur Verarbeitung großer Datenmengen, bei der die Daten gesammelt, verarbeitet und anschließend die Stapelergebnisse erstellt werden. Die Stapelverarbeitung kann in vielen Anwendungsfällen angewendet werden. Ein häufiger Anwendungsfall für die Stapelverarbeitung ist die Umwandlung einer großen Menge von CSV- oder JSON-Dateien in ein strukturiertes Format, das zur weiteren Verarbeitung bereit ist.
In diesem Tutorial werden wir versuchen zu sehen, wie man diese Architektur mit Spring Boot einrichtet, einem Framework, das die Entwicklung von Anwendungen auf Basis von Spring erleichtert.
Spring Batch ist ein Open-Source-Framework für die Stapelverarbeitung. Es handelt sich um eine leichte, umfassende Lösung, die die Entwicklung robuster Batch-Anwendungen ermöglicht, die häufig in modernen Unternehmenssystemen zu finden sind. Seine Entwicklung ist das Ergebnis einer Zusammenarbeit zwischen SpringSource und Accenture.
Es ermöglicht die Überwindung wiederkehrender Probleme während der Batch-Entwicklung:
Hinweis: In der IT ist ein Batch ein Programm, das eigenständig arbeitet und eine Reihe von Verarbeitungsvorgängen für ein Datenvolumen ausführt.
Um Chargendaten zu verwalten, verwenden wir hauptsächlich die folgenden drei Tools:
JobLauncher: Dies ist die Komponente, die für den Start/Start des Batch-Programms verantwortlich ist. Es kann so konfiguriert werden, dass es sich selbst oder durch ein externes Ereignis auslöst (manueller Start). Im Spring Batch-Workflow ist der JobLauncher für die Ausführung eines Jobs verantwortlich.
Job: Dies ist die Komponente, die die Aufgabe darstellt, an die die Verantwortung für die im Programm angesprochenen Geschäftsanforderungen delegiert wird. Es ist dafür verantwortlich, nacheinander einen oder mehrere Schritte zu starten.
Schritt: Dies ist die Komponente, die den Kern des Geschäftsbedürfnisses umhüllt, das angegangen werden muss. Es ist für die Definition von drei Unterkomponenten verantwortlich, die wie folgt strukturiert sind:
ItemReader: Dies ist die Komponente, die für das Lesen der zu verarbeitenden Eingabedaten verantwortlich ist. Sie können aus verschiedenen Quellen stammen (Datenbanken, Flatfiles (CSV, XML, XLS usw.), Warteschlange);
ItemProcessor: Dies ist die Komponente, die für die Transformation der gelesenen Daten verantwortlich ist. Darin werden alle Verwaltungsregeln umgesetzt.
ItemWriter: Diese Komponente speichert die vom Prozessor umgewandelten Daten in einem oder mehreren gewünschten Containern (Datenbanken, Flatfiles (CSV, XML, XLS usw.), Cloud).
JobRepository: Dies ist die Komponente, die für die Aufzeichnung von Statistiken aus der Überwachung des JobLauncher, des Jobs und der Schritte bei jeder Ausführung verantwortlich ist. Es bietet zwei mögliche Techniken zum Speichern dieser Statistiken: die Verwendung einer Datenbank oder die Verwendung einer Karte. Wenn die Statistiken in einer Datenbank gespeichert und somit dauerhaft gespeichert werden, ermöglicht dies eine kontinuierliche Überwachung des Batches über die Zeit, um mögliche Probleme im Fehlerfall zu analysieren. Wenn es sich dagegen in einer Map befindet, gehen die beibehaltenen Statistiken am Ende jeder Batch-Ausführungsinstanz verloren. In jedem Fall muss das eine oder das andere konfiguriert werden.
Für weitere Informationen empfehle ich Ihnen, die Spring-Website zu konsultieren.
Nach dieser kurzen Erläuterung der Spring-Batch-Architektur versuchen wir nun zu zeigen, wie man einen Spring-Batch-Job einrichtet, der Daten aus einer CSV-Datei liest, die wir anschließend in eine Datenbank einfügen.“ Kommen wir zum Codieren".
Der einfachste Weg, ein Spring Boot-Projekt zu generieren, ist die Verwendung des Spring Boot Tools mit den folgenden Schritten:
Sobald das Projekt generiert ist, müssen Sie es entpacken und dann in Ihre IDE importieren.
Verwendete Technologien:
Alle Projektabhängigkeiten befinden sich in der Datei pom.xml. Die drei Buchstaben POM sind das Akronym für Project Object Model. Seine XML-Darstellung wird von Maven in eine Datenstruktur übersetzt, die das Projektmodell darstellt.
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.pathus</groupId> <artifactId>SpringBatchExample</artifactId> <version>0.0.1-SNAPSHOT</version> <name>SpringBatchExample</name> <description>Demo of spring batch project </description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-batch</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.batch</groupId> <artifactId>spring-batch-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
Die Struktur des Projekts ist wie folgt:
Um die Stapelverarbeitung zu aktivieren, müssen wir die Konfigurationsklasse mit @EnableBatchProcessing annotieren. Wir müssen dann einen Reader erstellen, um unsere CSV-Datei zu lesen, einen Prozessor erstellen, um die Eingabedaten vor dem Schreiben zu verarbeiten, und einen Writer erstellen, um in die Datenbank zu schreiben.
import org.springframework.batch.core.Job; import org.springframework.batch.core.Step; import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; import org.springframework.batch.item.ItemProcessor; import org.springframework.batch.item.ItemReader; import org.springframework.batch.item.ItemWriter; import org.springframework.batch.item.file.FlatFileItemReader; import org.springframework.batch.item.file.LineMapper; import org.springframework.batch.item.file.mapping.DefaultLineMapper; import org.springframework.batch.item.file.transform.DelimitedLineTokenizer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import com.pathus90.springbatchexample.batch.StudentProcessor; import com.pathus90.springbatchexample.batch.StudentWriter; import com.pathus90.springbatchexample.model.Student; import com.pathus90.springbatchexample.model.StudentFieldSetMapper; @Configuration @EnableBatchProcessing @EnableScheduling public class BatchConfig { private static final String FILE_NAME = "results.csv"; private static final String JOB_NAME = "listStudentsJob"; private static final String STEP_NAME = "processingStep"; private static final String READER_NAME = "studentItemReader"; @Value("${header.names}") private String names; @Value("${line.delimiter}") private String delimiter; @Autowired private JobBuilderFactory jobBuilderFactory; @Autowired private StepBuilderFactory stepBuilderFactory; @Bean public Step studentStep() { return stepBuilderFactory.get(STEP_NAME) .<Student, Student>chunk(5) .reader(studentItemReader()) .processor(studentItemProcessor()) .writer(studentItemWriter()) .build(); } @Bean public Job listStudentsJob(Step step1) { return jobBuilderFactory.get(JOB_NAME) .start(step1) .build(); } @Bean public ItemReader<Student> studentItemReader() { FlatFileItemReader<Student> reader = new FlatFileItemReader<>(); reader.setResource(new ClassPathResource(FILE_NAME)); reader.setName(READER_NAME); reader.setLinesToSkip(1); reader.setLineMapper(lineMapper()); return reader; } @Bean public LineMapper<Student> lineMapper() { final DefaultLineMapper<Student> defaultLineMapper = new DefaultLineMapper<>(); final DelimitedLineTokenizer lineTokenizer = new DelimitedLineTokenizer(); lineTokenizer.setDelimiter(delimiter); lineTokenizer.setStrict(false); lineTokenizer.setNames(names.split(delimiter)); final StudentFieldSetMapper fieldSetMapper = new StudentFieldSetMapper(); defaultLineMapper.setLineTokenizer(lineTokenizer); defaultLineMapper.setFieldSetMapper(fieldSetMapper); return defaultLineMapper; } @Bean public ItemProcessor<Student, Student> studentItemProcessor() { return new StudentProcessor(); } @Bean public ItemWriter<Student> studentItemWriter() { return new StudentWriter(); } }
Die erste Methode definiert den Job und die zweite definiert einen einzelnen Schritt. Jobs werden aus Schritten erstellt, wobei jeder Schritt einen Leser, einen Prozessor und einen Autor umfassen kann. In der Schrittdefinition definieren wir die Datenmenge, die gleichzeitig geschrieben werden soll. In unserem Fall werden bis zu 5 Datensätze gleichzeitig geschrieben. Anschließend konfigurieren wir den Reader, den Prozessor und den Writer mithilfe der zuvor injizierten Beans. Wenn wir unsere Aufgabe definieren, können wir verschiedene Schritte innerhalb unserer Ausführung durch eine genaue Reihenfolge definieren. Der Schritt studentStep wird vom Job listStudentsJob ausgeführt.
@Bean public Step studentStep() { return stepBuilderFactory.get(STEP_NAME) .<Student, Student>chunk(5) .reader(studentItemReader()) .processor(studentItemProcessor()) .writer(studentItemWriter()) .build(); } @Bean public Job listStudentsJob(Step step1) { return jobBuilderFactory.get(JOB_NAME) .start(step1) .build(); }
In unserer Batch-Konfiguration liest der Reader eine Datenquelle und wird innerhalb eines Schritts nacheinander aufgerufen und gibt Objekte zurück, für die er definiert ist (in unserem Fall Student).
@Bean public ItemReader<Student> studentItemReader() { FlatFileItemReader<Student> reader = new FlatFileItemReader<>(); reader.setResource(new ClassPathResource(FILE_NAME)); reader.setName(READER_NAME); reader.setLinesToSkip(1); reader.setLineMapper(lineMapper()); return reader; }
Die Klasse „FlatFileItemReader“ verwendet die Klasse „DefaultLineMapper“, die wiederum die Klasse „DelimitedLineTokenizer“ verwendet. Die Rolle von DelimitedLineTokenizer besteht darin, jede Zeile in ein FieldSet-Objekt zu zerlegen. Die Eigenschaft „names“ gibt das Format des Dateiheaders an und ermöglicht die Identifizierung der Daten jeder Zeile. Diese Namenseigenschaft wird von der Datentransformations-Implementierungsklasse über das FieldSet-Objekt in ein Geschäftsobjekt verwendet. Dies ist die Klasse, die durch die Eigenschaft fieldSetMapper (StudentFieldSetMapper) angegeben wird.
import org.springframework.batch.item.file.mapping.FieldSetMapper; import org.springframework.batch.item.file.transform.FieldSet; public class StudentFieldSetMapper implements FieldSetMapper<Student> { @Override public Student mapFieldSet(FieldSet fieldSet) { return Student.builder() .rank(fieldSet.readString(0)) .firstName(fieldSet.readString(1)) .lastName(fieldSet.readString(2)) .center(fieldSet.readString(3)) .pv(fieldSet.readString(4)) .origin(fieldSet.readString(5)) .mention(fieldSet.readString(6)) .build(); } }
Die LineMapper-Schnittstelle wird zum Zuordnen von Linien (Strings) zu Objekten verwendet, die im Allgemeinen zum Zuordnen von aus einer Datei gelesenen Linien verwendet werden
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.pathus</groupId> <artifactId>SpringBatchExample</artifactId> <version>0.0.1-SNAPSHOT</version> <name>SpringBatchExample</name> <description>Demo of spring batch project </description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-batch</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.batch</groupId> <artifactId>spring-batch-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
Im Gegensatz zu einem Reader dienen die Implementierungen eines Prozessors eher funktionalen Anforderungen. Es ist nicht obligatorisch und wir können darauf verzichten, wenn in unserer Verarbeitung kein funktionaler Bedarf vorgesehen ist. In unserem Beispiel haben wir einen einfachen Prozessor geschrieben, der nur einige Attribute unseres Studentenobjekts in Großbuchstaben umwandelt und mit dem wir über dieses Beispiel hinausgehen können konkretere Funktionsfälle.
import org.springframework.batch.core.Job; import org.springframework.batch.core.Step; import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; import org.springframework.batch.item.ItemProcessor; import org.springframework.batch.item.ItemReader; import org.springframework.batch.item.ItemWriter; import org.springframework.batch.item.file.FlatFileItemReader; import org.springframework.batch.item.file.LineMapper; import org.springframework.batch.item.file.mapping.DefaultLineMapper; import org.springframework.batch.item.file.transform.DelimitedLineTokenizer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import com.pathus90.springbatchexample.batch.StudentProcessor; import com.pathus90.springbatchexample.batch.StudentWriter; import com.pathus90.springbatchexample.model.Student; import com.pathus90.springbatchexample.model.StudentFieldSetMapper; @Configuration @EnableBatchProcessing @EnableScheduling public class BatchConfig { private static final String FILE_NAME = "results.csv"; private static final String JOB_NAME = "listStudentsJob"; private static final String STEP_NAME = "processingStep"; private static final String READER_NAME = "studentItemReader"; @Value("${header.names}") private String names; @Value("${line.delimiter}") private String delimiter; @Autowired private JobBuilderFactory jobBuilderFactory; @Autowired private StepBuilderFactory stepBuilderFactory; @Bean public Step studentStep() { return stepBuilderFactory.get(STEP_NAME) .<Student, Student>chunk(5) .reader(studentItemReader()) .processor(studentItemProcessor()) .writer(studentItemWriter()) .build(); } @Bean public Job listStudentsJob(Step step1) { return jobBuilderFactory.get(JOB_NAME) .start(step1) .build(); } @Bean public ItemReader<Student> studentItemReader() { FlatFileItemReader<Student> reader = new FlatFileItemReader<>(); reader.setResource(new ClassPathResource(FILE_NAME)); reader.setName(READER_NAME); reader.setLinesToSkip(1); reader.setLineMapper(lineMapper()); return reader; } @Bean public LineMapper<Student> lineMapper() { final DefaultLineMapper<Student> defaultLineMapper = new DefaultLineMapper<>(); final DelimitedLineTokenizer lineTokenizer = new DelimitedLineTokenizer(); lineTokenizer.setDelimiter(delimiter); lineTokenizer.setStrict(false); lineTokenizer.setNames(names.split(delimiter)); final StudentFieldSetMapper fieldSetMapper = new StudentFieldSetMapper(); defaultLineMapper.setLineTokenizer(lineTokenizer); defaultLineMapper.setFieldSetMapper(fieldSetMapper); return defaultLineMapper; } @Bean public ItemProcessor<Student, Student> studentItemProcessor() { return new StudentProcessor(); } @Bean public ItemWriter<Student> studentItemWriter() { return new StudentWriter(); } }
Der Writer schreibt die Daten, die vom Prozessor kommen (oder direkt vom Reader gelesen werden). In unserem Fall empfängt es die transformierten Objekte vom Prozessor und jedes Objekt wird anschließend in unserer Datenbank gespeichert und die Transaktion wird validiert.
@Bean public Step studentStep() { return stepBuilderFactory.get(STEP_NAME) .<Student, Student>chunk(5) .reader(studentItemReader()) .processor(studentItemProcessor()) .writer(studentItemWriter()) .build(); } @Bean public Job listStudentsJob(Step step1) { return jobBuilderFactory.get(JOB_NAME) .start(step1) .build(); }
@Bean public ItemReader<Student> studentItemReader() { FlatFileItemReader<Student> reader = new FlatFileItemReader<>(); reader.setResource(new ClassPathResource(FILE_NAME)); reader.setName(READER_NAME); reader.setLinesToSkip(1); reader.setLineMapper(lineMapper()); return reader; }
import org.springframework.batch.item.file.mapping.FieldSetMapper; import org.springframework.batch.item.file.transform.FieldSet; public class StudentFieldSetMapper implements FieldSetMapper<Student> { @Override public Student mapFieldSet(FieldSet fieldSet) { return Student.builder() .rank(fieldSet.readString(0)) .firstName(fieldSet.readString(1)) .lastName(fieldSet.readString(2)) .center(fieldSet.readString(3)) .pv(fieldSet.readString(4)) .origin(fieldSet.readString(5)) .mention(fieldSet.readString(6)) .build(); } }
Sobald wir mit der Einrichtung der Batch-Konfiguration fertig sind, wollen wir nun sehen, ob alles, was oben gesagt wurde, funktioniert
Um die Anwendung auszuführen, müssen Sie nach der Datei suchen, die die Anmerkung @SpringBootApplication enthält, die den Hauptteil unserer Anwendung darstellt.
@Bean public LineMapper<Student> lineMapper() { final DefaultLineMapper<Student> defaultLineMapper = new DefaultLineMapper<>(); final DelimitedLineTokenizer lineTokenizer = new DelimitedLineTokenizer(); lineTokenizer.setDelimiter(delimiter); lineTokenizer.setStrict(false); lineTokenizer.setNames(names.split(delimiter)); final StudentFieldSetMapper fieldSetMapper = new StudentFieldSetMapper(); defaultLineMapper.setLineTokenizer(lineTokenizer); defaultLineMapper.setFieldSetMapper(fieldSetMapper); return defaultLineMapper; }
Durch das Starten des Hauptmenüs oben wird unser Job gestartet und der Batch-Launcher sieht folgendermaßen aus:
import org.springframework.batch.item.ItemProcessor; import com.pathus90.springbatchexample.model.Student; public class StudentProcessor implements ItemProcessor<Student, Student> { @Override public Student process(Student student) { student.setFirstName(student.getFirstName().toUpperCase()); student.setLastName(student.getLastName().toUpperCase()); student.setCenter(student.getCenter().toUpperCase()); student.setOrigin(student.getOrigin().toUpperCase()); student.setMention(student.getMention().toUpperCase()); return student; } }
Es wurde ein Zeitplaner eingerichtet, der es ermöglicht, die Charge automatisch auszulösen. In diesem Beispiel wird der Stapel nach dem Start alle 8 Sekunden ausgeführt. Sie können damit herumspielen, indem Sie den fixedDelayWert in Millisekunden ändern.
import java.util.List; import org.springframework.batch.item.ItemWriter; import org.springframework.beans.factory.annotation.Autowired; import com.pathus90.springbatchexample.model.Student; import com.pathus90.springbatchexample.service.IStudentService; import lombok.extern.slf4j.Slf4j; @Slf4j public class StudentWriter implements ItemWriter<Student> { @Autowired private IStudentService studentService; @Override public void write(List<? extends Student> students) { students.stream().forEach(student -> { log.info("Enregistrement en base de l'objet {}", student); studentService.insertStudent(student); }); } }
Zusätzlich zum Ausführen der Hauptdatei oben, um den Stapel zu starten, können Sie auch den Befehl mvn spring-boot:run ausführen, während Sie eine Eingabeaufforderung verwenden.
Sie können die Anwendung auch mit der JAR-Archivdatei starten. In diesem Fall müssen Sie Folgendes tun:
Gehen Sie über eine Eingabeaufforderung zum übergeordneten Ordner des Projekts und führen Sie den Befehl mvn clean package aus, der unser Projekt verpackt.
Im Zielordner wird eine JAR-Datei erstellt.
Um die Anwendung auszuführen, verwenden Sie den Befehl java -jar target/generated_file_name-0.0.1-SNAPSHOT.jar
Stellen Sie außerdem sicher, dass die H2Konsole beim Starten unserer Spring-Batch-Anwendung bereits gestartet ist und die Datenbank automatisch generiert wird, ebenso wie die Erstellung der Tabelle Student .
Wir können deutlich erkennen, dass unsere Datei gut in unsere Datenbank integriert wurde.
Hinweis:Wenn wir den Batch auch manuell starten möchten, ohne einen Schedulerzu übergeben, der abhängig von unseren Einstellungen ausgelöst wird, habe ich eine API bereitgestellt, die den Controller zum Aufrufen verwendet der Job Spring Batch.
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.pathus</groupId> <artifactId>SpringBatchExample</artifactId> <version>0.0.1-SNAPSHOT</version> <name>SpringBatchExample</name> <description>Demo of spring batch project </description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-batch</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.batch</groupId> <artifactId>spring-batch-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
Starten Sie einfach die URL: http://localhost:8080/load und der Batch wird gestartet
Wir sind am Ende unserer ersten Lektion zur Batch-Programmierung mit dem Spring-Framework angelangt. Hinterlassen Sie Kommentare oder Fragen, wenn Sie welche haben!
Viel Spaß beim Lernen und ich hoffe, dass dieses erste Tutorial für Sie von Nutzen sein wird.
Den Quellcode finden Sie hier
Das obige ist der detaillierte Inhalt vonBeginnen Sie mit der Programmierung mit SPRING BATCH. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!