개인적이거나 직업적인 프로젝트에서는 때때로 대용량의 데이터를 처리할 때가 있습니다. 데이터 일괄 처리는 대량의 데이터를 효율적으로 처리하는 방법으로, 데이터를 수집하고 처리한 후 일괄 결과를 생성합니다. 일괄 처리는 다양한 사용 사례에 적용될 수 있습니다. 일괄 처리의 일반적인 사용 사례는 대규모 CSV 또는 JSON 파일 세트를 추가 처리가 가능한 구조화된 형식으로 변환하는 것입니다.
이 튜토리얼에서는 Spring 기반 애플리케이션 개발을 용이하게 하는 프레임워크인 Spring Boot를 사용하여 이 아키텍처를 설정하는 방법을 살펴보겠습니다.
Spring Batch는 일괄 처리를 위한 오픈 소스 프레임워크입니다. 이는 현대 엔터프라이즈 시스템에서 흔히 볼 수 있는 강력한 배치 애플리케이션의 개발을 가능하게 하도록 설계된 가볍고 포괄적인 솔루션입니다. 이 개발은 SpringSource와 Accenture 간의 협력의 결과입니다.
일괄 개발 중에 반복되는 문제를 극복할 수 있습니다.
주의: IT에서 배치는 독립형으로 작동하는 프로그램으로, 대량의 데이터에 대해 일련의 처리 작업을 수행합니다.
배치 데이터를 관리하기 위해 주로 다음 세 가지 도구를 사용합니다.
JobLauncher: 배치 프로그램 실행/시작을 담당하는 구성 요소입니다. 자체적으로 트리거되거나 외부 이벤트(수동 실행)에 의해 트리거되도록 구성할 수 있습니다. Spring Batch 워크플로에서 JobLauncher는 작업 실행을 담당합니다.
직업: 프로그램에서 다루는 비즈니스 요구에 대한 책임이 위임되는 작업을 나타내는 구성 요소입니다. 하나 이상의 단계를 순차적으로 시작하는 역할을 담당합니다.
단계: 이는 해결해야 할 비즈니스 요구의 핵심을 포괄하는 구성 요소입니다. 다음과 같이 구성된 세 가지 하위 구성 요소를 정의하는 역할을 담당합니다.
ItemReader: 처리할 입력 데이터를 읽는 역할을 담당하는 구성 요소입니다. 다양한 소스(데이터베이스, 플랫 파일(csv, xml, xls 등), 대기열)에서 가져올 수 있습니다.
ItemProcessor: 읽은 데이터를 변환하는 구성 요소입니다. 그 안에 모든 관리 규칙이 구현됩니다.
ItemWriter: 이 구성 요소는 프로세서에 의해 변환된 데이터를 하나 이상의 원하는 컨테이너(데이터베이스, 플랫 파일(csv, xml, xls 등), 클라우드)에 저장합니다.
JobRepository: JobLauncher, Job 및 각 실행 단계에 대한 모니터링 통계를 기록하는 구성 요소입니다. 이러한 통계를 저장하기 위한 두 가지 가능한 기술, 즉 데이터베이스 사용 또는 맵 사용을 제공합니다. 통계가 데이터베이스에 저장되어 지속적인 방식으로 유지되면 실패 시 발생할 수 있는 문제를 분석하기 위해 시간이 지남에 따라 배치를 지속적으로 모니터링할 수 있습니다. 반대로 맵에 있는 경우 각 배치 실행 인스턴스가 끝나면 지속된 통계가 손실됩니다. 모든 경우에 둘 중 하나를 구성해야 합니다.
자세한 내용은 봄 홈페이지를 참고하시기 바랍니다.
스프링 배치 아키텍처에 대한 간단한 설명을 마친 후, 이제 나중에 데이터베이스에 삽입할 CSV 파일에서 데이터를 읽는 스프링 배치 작업을 설정하는 방법을 보여드리겠습니다." 코딩을 시작해보자".
Spring Boot 프로젝트를 생성하는 가장 쉬운 방법은 아래 단계에 따라 Spring Boot 도구를 사용하는 것입니다.
프로젝트가 생성되면 압축을 풀고 IDE로 가져와야 합니다.
사용된 기술:
모든 프로젝트 종속성은 pom.xml 파일에 있습니다. 세 글자 POM은 Project Object Model의 약어입니다. XML 표현은 Maven에 의해 프로젝트 모델을 나타내는 데이터 구조로 변환됩니다.
<?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>
프로젝트 구성은 다음과 같습니다.
일괄 처리를 활성화하려면 @EnableBatchProcessing으로 구성 클래스에 주석을 달아야 합니다. 그런 다음 CSV 파일을 읽기 위한 판독기를 생성하고, 쓰기 전에 입력 데이터를 처리하기 위한 프로세서를 생성하고, 데이터베이스에 쓰기 위한 기록기를 생성해야 합니다.
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(); } }
첫 번째 방법은 작업을 정의하고 두 번째 방법은 단일 단계를 정의합니다. 작업은 단계를 통해 생성되며 각 단계에는 리더, 프로세서 및 작성자가 포함될 수 있습니다. 단계 정의에서는 한 번에 쓸 데이터의 양을 정의하고, 우리의 경우에는 한 번에 최대 5개의 레코드를 씁니다. 그런 다음 앞서 주입한 Bean을 사용하여 리더, 프로세서 및 라이터를 구성합니다. 작업을 정의할 때 정확한 순서를 통해 실행 내의 다양한 단계를 정의할 수 있습니다. StudentStep 단계는 작업 목록StudentsJob에 의해 실행됩니다.
@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(); }
일괄 구성에서 Reader는 데이터 소스를 읽고 한 단계 내에서 연속적으로 호출되며 정의된 개체를 반환합니다(우리의 경우 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; }
FlatFileItemReader 클래스는 DelimitedLineTokenizer 클래스를 사용하는 DefaultLineMapper 클래스를 사용합니다. DelimitedLineTokenizer의 역할은 각 줄을 FieldSet 개체로 분해하는 것이며 이름 속성은 파일 헤더의 형식을 제공하고 각 줄의 데이터를 식별할 수 있도록 해줍니다. 이 이름 속성은 FieldSet 개체를 통해 비즈니스 개체로의 데이터 변환 구현 클래스에서 사용됩니다. fieldSetMapper(StudentFieldSetMapper) 속성으로 표시되는 클래스입니다.
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(); } }
LineMapper 인터페이스는 파일에서 읽은 줄을 매핑하는 데 일반적으로 사용되는 개체에 줄(문자열)을 매핑하는 데 사용됩니다.
<?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>
리더와 달리 프로세서의 구현은 기능적 요구에 더 가깝습니다. 필수 사항은 아니며 처리 시 기능적 필요가 예상되지 않으면 이 예제 없이도 수행할 수 있습니다. 예제에서는 학생 객체의 몇 가지 속성만 대문자로 변환하는 간단한 프로세서를 작성했으며 다음을 사용하여 이 예제를 뛰어넘을 수 있습니다. 좀 더 구체적인 기능적 사례를 살펴보세요.
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(); } }
작성기는 프로세서에서 오는 데이터를 씁니다(또는 리더가 직접 읽음). 우리의 경우 프로세서로부터 변환된 개체를 수신하고 각 개체는 이후 데이터베이스에 유지되며 트랜잭션이 검증됩니다.
@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(); } }
일괄 구성 설정을 마쳤으면 이제 위에서 설명한 모든 내용이 작동하는지 확인해 보겠습니다.
애플리케이션을 실행하려면 애플리케이션의 주요 부분인 @SpringBootApplication 주석이 포함된 파일을 찾아야 합니다.
@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; }
위의 메인을 실행하면 작업이 시작되고 배치 실행기는 다음과 같습니다.
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; } }
일괄 처리가 자동으로 실행되도록 스케줄러가 설정되었습니다. 이 예에서 일단 시작된 배치는 8초마다 실행됩니다. fixedDelay값을 밀리초 단위로 변경하여 사용해 볼 수 있습니다.
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); }); } }
위의 기본 파일을 실행하여 배치를 시작하는 것 외에도 명령 프롬프트를 사용하는 동안 mvn spring-boot:run 명령을 실행할 수도 있습니다.
JAR 아카이브 파일을 사용하여 애플리케이션을 시작할 수도 있으며 이 경우 다음을 수행해야 합니다.
명령 프롬프트를 사용하여 프로젝트의 상위 폴더로 이동하고 mvn clean package 명령을 실행하여 프로젝트를 패키징합니다.
대상 폴더에 jar 파일이 생성됩니다.
애플리케이션을 실행하려면 java -jar target/generated_file_name-0.0.1-SNAPSHOT.jar
또한 스프링 배치 애플리케이션을 시작할 때 H2 콘솔이 이미 시작되었는지, 데이터베이스가 자동으로 생성되고 Student 테이블이 생성되는지 확인하세요.
파일이 데이터베이스에 잘 통합되었음을 확실히 알 수 있습니다.
주의:설정에 따라 실행되는 스케줄러를 전달하지 않고 수동으로 배치를 시작하려면 컨트롤러를 사용하여 호출하는 API를 노출했습니다. 채용 봄 배치
<?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>
URL: http://localhost:8080/load를 실행하면 배치가 실행됩니다.
Spring 프레임워크를 사용한 배치 프로그래밍에 대한 첫 번째 학습이 끝났습니다. 궁금한 점이나 의견을 남겨주세요!
모두들 즐거운 학습이 되셨기를 바랍니다. 이 첫 번째 튜토리얼이 여러분에게 도움이 되기를 바랍니다.
여기에서 소스 코드를 확인할 수 있습니다
위 내용은 SPRING BATCH로 프로그래밍 시작의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!