Spring Batch Tasklet, Chunks 차이 및 예제
1. 소개
스프링 배치 는 작업을 구현하기위한 두 가지 다른 방법을 제공합니다 : 태스크 릿과 청크 사용 .
이 기사에서는 간단한 실제 예제를 사용하여 두 가지 방법을 구성하고 구현하는 방법을 배웁니다.
2. 의존성
필요한 의존성 을 추가하여 시작하자 :
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-core</artifactId>
<version>4.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-test</artifactId>
<version>4.2.0.RELEASE</version>
<scope>test</scope>
</dependency>
스프링 배치 코어 및 스프링 배치 테스트 의 최신 버전을 얻으려면 Maven Central을 참조하십시오.
3. 우리의 사용 사례
다음 내용이 포함 된 CSV 파일을 고려하십시오.
Mae Hodges,10/22/1972
Gary Potter,02/22/1953
Betty Wise,02/17/1968
Wayne Rose,04/06/1977
Adam Caldwell,09/27/1995
Lucille Phillips,05/14/1992
각 줄 의 첫 번째 위치는 사람의 이름을 나타내고 두 번째 위치는 그 / 그녀의 생년월일을 나타냅니다 .
우리의 사용 사례는 각 사람의 이름과 나이를 포함하는 다른 CSV 파일 을 생성하는 것입니다 .
Mae Hodges,45
Gary Potter,64
Betty Wise,49
Wayne Rose,40
Adam Caldwell,22
Lucille Phillips,25
도메인이 명확 해지면 두 가지 방법을 모두 사용하여 솔루션을 구축해 보겠습니다. 태스크 릿부터 시작하겠습니다.
4. Tasklets 방식
4.1. 소개 및 디자인
태스크 릿은 단계 내에서 단일 태스크를 수행하기위한 것입니다. 우리의 임무는 차례대로 실행되는 여러 단계로 구성됩니다. 각 단계는 하나의 정의 된 작업 만 수행해야합니다 .
우리의 일은 세 단계로 구성됩니다.
- 입력 CSV 파일에서 행을 읽습니다.
- 입력 CSV 파일에서 모든 사람의 나이를 계산하십시오.
- 각 사람의 이름과 나이를 새 출력 CSV 파일에 씁니다.
큰 그림이 준비되었으므로 단계 당 하나의 클래스를 만들어 봅시다.
LinesReader 는 입력 파일에서 데이터 읽기를 담당합니다.
public class LinesReader implements Tasklet {
// ...
}
LinesProcessor 는 파일에있는 모든 사람의 나이를 계산합니다.
public class LinesProcessor implements Tasklet {
// ...
}
마지막으로 LinesWriter 는 출력 파일에 이름과 연령을 기록 할 책임이 있습니다.
public class LinesWriter implements Tasklet {
// ...
}
이 시점에서 모든 단계는 Tasklet 인터페이스를 구현 합니다. 이를 통해 우리는 execute 메소드 를 구현 해야 합니다.
@Override
public RepeatStatus execute(StepContribution stepContribution,
ChunkContext chunkContext) throws Exception {
// ...
}
이 방법은 각 단계에 대한 논리를 추가하는 곳입니다. 해당 코드로 시작하기 전에 작업을 구성하겠습니다.
4.2. 구성
Spring의 애플리케이션 컨텍스트에 구성 을 추가 해야합니다 . 이전 섹션에서 생성 된 클래스에 대한 표준 Bean 선언을 추가 한 후 작업 정의를 작성할 준비가되었습니다.
@Configuration
@EnableBatchProcessing
public class TaskletsConfig {
@Autowired
private JobBuilderFactory jobs;
@Autowired
private StepBuilderFactory steps;
@Bean
protected Step readLines() {
return steps
.get("readLines")
.tasklet(linesReader())
.build();
}
@Bean
protected Step processLines() {
return steps
.get("processLines")
.tasklet(linesProcessor())
.build();
}
@Bean
protected Step writeLines() {
return steps
.get("writeLines")
.tasklet(linesWriter())
.build();
}
@Bean
public Job job() {
return jobs
.get("taskletsJob")
.start(readLines())
.next(processLines())
.next(writeLines())
.build();
}
// ...
}
이는 *"taskletsJob"* 이 세 단계로 구성됨을 의미 합니다. 첫 번째 ( readLines )는 Bean linesReader에 정의 된 태스크 릿을 실행 하고 다음 단계 인 processLines 로 이동합니다 . ProcessLines 는 Bean linesProcessor에 정의 된 태스크 릿을 수행하고 마지막 단계 인 writeLines 로 이동합니다 .
작업 흐름이 정의되었으며 로직을 추가 할 준비가되었습니다!
4.3. 모델과 활용
CSV 파일에서 줄을 조작 할 때 클래스 줄 을 만들 것입니다 .
public class Line implements Serializable {
private String name;
private LocalDate dob;
private Long age;
// standard constructor, getters, setters and toString implementation
}
제발 참고 라인이 구현 직렬화합니다. 이는 Line 이 단계간에 데이터를 전송하기위한 DTO 역할을 하기 때문 입니다. 스프링 배치에 따르면, 단계 사이에 전송되는 객체는 직렬화 가능해야합니다 .
반면에, 우리는 글을 읽고 쓰는 것에 대해 생각할 수 있습니다.
이를 위해 OpenCSV를 사용합니다.
<dependency>
<groupId>com.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>4.1</version>
</dependency>
Maven Central에서 최신 OpenCSV 버전을 찾으십시오 .
OpenCSV가 포함되면 FileUtils 클래스도 만들 것 입니다. CSV 행을 읽고 쓰는 방법을 제공합니다.
public class FileUtils {
public Line readLine() throws Exception {
if (CSVReader == null)
initReader();
String[] line = CSVReader.readNext();
if (line == null)
return null;
return new Line(
line[0],
LocalDate.parse(
line[1],
DateTimeFormatter.ofPattern("MM/dd/yyyy")));
}
public void writeLine(Line line) throws Exception {
if (CSVWriter == null)
initWriter();
String[] lineStr = new String[2];
lineStr[0] = line.getName();
lineStr[1] = line
.getAge()
.toString();
CSVWriter.writeNext(lineStr);
}
// ...
}
공지 사항 것을 내의 readLine는 OpenCSV의에 대한 래퍼 역할을 readNext의 방법 및 반환 라인 개체를.
같은 방법으로, writeLine은 OpenCSV의 writeNext 를 Line 객체로받습니다. 이 클래스의 전체 구현은 GitHub 프로젝트 에서 찾을 수 있습니다 .
이 시점에서 우리는 모든 단계 구현으로 시작하도록 설정되었습니다.
4.4. Tasklet Lines Reader구성
계속해서 LinesReader 클래스를 완성 해 봅시다 :
public class LinesReader implements Tasklet, StepExecutionListener {
private final Logger logger = LoggerFactory
.getLogger(LinesReader.class);
private List<Line> lines;
private FileUtils fu;
@Override
public void beforeStep(StepExecution stepExecution) {
lines = new ArrayList<>();
fu = new FileUtils(
"taskletsvschunks/input/tasklets-vs-chunks.csv");
logger.debug("Lines Reader initialized.");
}
@Override
public RepeatStatus execute(StepContribution stepContribution,
ChunkContext chunkContext) throws Exception {
Line line = fu.readLine();
while (line != null) {
lines.add(line);
logger.debug("Read line: " + line.toString());
line = fu.readLine();
}
return RepeatStatus.FINISHED;
}
@Override
public ExitStatus afterStep(StepExecution stepExecution) {
fu.closeReader();
stepExecution
.getJobExecution()
.getExecutionContext()
.put("lines", this.lines);
logger.debug("Lines Reader ended.");
return ExitStatus.COMPLETED;
}
}
LinesReader의 execute 메소드 는 입력 파일 경로를 통해 FileUtils 인스턴스를 작성합니다 . 그런 다음 읽을 행이 더 이상 없을 때까지 목록에 행을 추가합니다 .
우리 클래스 는 또한 StepStepuumentListener 를 구현 하여 두 가지 추가 메소드 인 beforeStep 과 afterStep을 제공 합니다. 우리는이 메소드를 사용하여 실행 실행 전후에 초기화하고 닫습니다 .
afterStep 코드 를 살펴보면 다음 단계에서 사용할 수 있도록 결과 목록 ( 행) 이 작업 컨텍스트에있는 행을 확인할 수 있습니다.
stepExecution
.getJobExecution()
.getExecutionContext()
.put("lines", this.lines);
이 시점에서 첫 번째 단계는 이미 책임을 수행했습니다. CSV 행을 메모리 의 목록 에 로드 합니다. 두 번째 단계로 이동하여 처리하겠습니다.
4.5. Tasklet Lines Processor 구성
LinesProcessor 는 StepExecutionListener 와 Tasklet 도 구현할 것 입니다. 즉, beforeStep , execute 및 afterStep 메소드도구현합니다.
public class LinesProcessor implements Tasklet, StepExecutionListener {
private Logger logger = LoggerFactory.getLogger(
LinesProcessor.class);
private List<Line> lines;
@Override
public void beforeStep(StepExecution stepExecution) {
ExecutionContext executionContext = stepExecution
.getJobExecution()
.getExecutionContext();
this.lines = (List<Line>) executionContext.get("lines");
logger.debug("Lines Processor initialized.");
}
@Override
public RepeatStatus execute(StepContribution stepContribution,
ChunkContext chunkContext) throws Exception {
for (Line line : lines) {
long age = ChronoUnit.YEARS.between(
line.getDob(),
LocalDate.now());
logger.debug("Calculated age " + age + " for line " + line.toString());
line.setAge(age);
}
return RepeatStatus.FINISHED;
}
@Override
public ExitStatus afterStep(StepExecution stepExecution) {
logger.debug("Lines Processor ended.");
return ExitStatus.COMPLETED;
}
}
작업 컨텍스트에서 행 목록을 로드 하고 각 사람의 나이를 계산 한다는 것을 이해하는 것은 쉽지 않습니다.
이전 단계에서 온 동일한 오브젝트에서 수정이 발생하므로 컨텍스트에 다른 결과 목록을 넣을 필요가 없습니다.
그리고 우리는 마지막 단계에 대한 준비가되었습니다.
4.6. Tasklet LinesWriter 구성
LinesWriter 의 임무는 행 목록 을 살펴 보고 출력 파일에 이름과 나이를 쓰는 것입니다 .
public class LinesWriter implements Tasklet, StepExecutionListener {
private final Logger logger = LoggerFactory
.getLogger(LinesWriter.class);
private List<Line> lines;
private FileUtils fu;
@Override
public void beforeStep(StepExecution stepExecution) {
ExecutionContext executionContext = stepExecution
.getJobExecution()
.getExecutionContext();
this.lines = (List<Line>) executionContext.get("lines");
fu = new FileUtils("output.csv");
logger.debug("Lines Writer initialized.");
}
@Override
public RepeatStatus execute(StepContribution stepContribution,
ChunkContext chunkContext) throws Exception {
for (Line line : lines) {
fu.writeLine(line);
logger.debug("Wrote line " + line.toString());
}
return RepeatStatus.FINISHED;
}
@Override
public ExitStatus afterStep(StepExecution stepExecution) {
fu.closeWriter();
logger.debug("Lines Writer ended.");
return ExitStatus.COMPLETED;
}
}
우리는 작업 구현을 마쳤습니다! 테스트를 실행하고 결과를 봅시다.
4.7. Tasklet방식 실행 하기
작업을 실행하기 위해 테스트를 작성합니다.
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TaskletsConfig.class)
public class TaskletsTest {
@Autowired
private JobLauncherTestUtils jobLauncherTestUtils;
@Test
public void givenTaskletsJob_whenJobEnds_thenStatusCompleted()
throws Exception {
JobExecution jobExecution = jobLauncherTestUtils.launchJob();
assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus());
}
}
ContextConfiguration 주석은 작업 정의가있는 Spring 컨텍스트 구성 클래스를 가리키고 있습니다.
테스트를 실행하기 전에 두 개의 추가 Bean을 추가해야합니다.
@Bean
public JobLauncherTestUtils jobLauncherTestUtils() {
return new JobLauncherTestUtils();
}
@Bean
public JobRepository jobRepository() throws Exception {
MapJobRepositoryFactoryBean factory
= new MapJobRepositoryFactoryBean();
factory.setTransactionManager(transactionManager());
return (JobRepository) factory.getObject();
}
@Bean
public PlatformTransactionManager transactionManager() {
return new ResourcelessTransactionManager();
}
@Bean
public JobLauncher jobLauncher() throws Exception {
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
jobLauncher.setJobRepository(jobRepository());
return jobLauncher;
}
다 준비 됐어! 계속해서 테스트를 실행하십시오!
작업이 완료되면 output.csv 에 예상 내용이 있으며 로그에 실행 흐름이 표시됩니다.
[main] DEBUG o.b.t.tasklets.LinesReader - Lines Reader initialized.
[main] DEBUG o.b.t.tasklets.LinesReader - Read line: [Mae Hodges,10/22/1972]
[main] DEBUG o.b.t.tasklets.LinesReader - Read line: [Gary Potter,02/22/1953]
[main] DEBUG o.b.t.tasklets.LinesReader - Read line: [Betty Wise,02/17/1968]
[main] DEBUG o.b.t.tasklets.LinesReader - Read line: [Wayne Rose,04/06/1977]
[main] DEBUG o.b.t.tasklets.LinesReader - Read line: [Adam Caldwell,09/27/1995]
[main] DEBUG o.b.t.tasklets.LinesReader - Read line: [Lucille Phillips,05/14/1992]
[main] DEBUG o.b.t.tasklets.LinesReader - Lines Reader ended.
[main] DEBUG o.b.t.tasklets.LinesProcessor - Lines Processor initialized.
[main] DEBUG o.b.t.tasklets.LinesProcessor - Calculated age 45 for line [Mae Hodges,10/22/1972]
[main] DEBUG o.b.t.tasklets.LinesProcessor - Calculated age 64 for line [Gary Potter,02/22/1953]
[main] DEBUG o.b.t.tasklets.LinesProcessor - Calculated age 49 for line [Betty Wise,02/17/1968]
[main] DEBUG o.b.t.tasklets.LinesProcessor - Calculated age 40 for line [Wayne Rose,04/06/1977]
[main] DEBUG o.b.t.tasklets.LinesProcessor - Calculated age 22 for line [Adam Caldwell,09/27/1995]
[main] DEBUG o.b.t.tasklets.LinesProcessor - Calculated age 25 for line [Lucille Phillips,05/14/1992]
[main] DEBUG o.b.t.tasklets.LinesProcessor - Lines Processor ended.
[main] DEBUG o.b.t.tasklets.LinesWriter - Lines Writer initialized.
[main] DEBUG o.b.t.tasklets.LinesWriter - Wrote line [Mae Hodges,10/22/1972,45]
[main] DEBUG o.b.t.tasklets.LinesWriter - Wrote line [Gary Potter,02/22/1953,64]
[main] DEBUG o.b.t.tasklets.LinesWriter - Wrote line [Betty Wise,02/17/1968,49]
[main] DEBUG o.b.t.tasklets.LinesWriter - Wrote line [Wayne Rose,04/06/1977,40]
[main] DEBUG o.b.t.tasklets.LinesWriter - Wrote line [Adam Caldwell,09/27/1995,22]
[main] DEBUG o.b.t.tasklets.LinesWriter - Wrote line [Lucille Phillips,05/14/1992,25]
[main] DEBUG o.b.t.tasklets.LinesWriter - Lines Writer ended.
그것은 Tasklet을위한 것입니다. 이제 Chunks 접근법으로 넘어갈 수 있습니다.
5 . 청크 방식
5.1. 소개 및 디자인
이름에서 알 수 있듯이이 방법 은 데이터 청크에 대해 작업을 수행합니다 . 즉, 한 번에 모든 행을 읽고 처리하고 쓰는 대신 한 번에 고정 된 양의 레코드 (청크)를 읽고 처리하고 씁니다.
그런 다음 파일에 더 이상 데이터가 없을 때까지주기를 반복합니다.
결과적으로 흐름이 약간 다릅니다.
- 선이있는 동안 :
- X 줄의 행에 대해 :
- 한 줄을 읽으십시오
- 한 줄 처리
- X 라인을 씁니다.
- X 줄의 행에 대해 :
따라서 청크 지향 접근 방식 을 위해 3 개의 빈 을 생성해야합니다 .
public class LineReader {
// ...
}
public class LineProcessor {
// ...
}
public class LinesWriter {
// ...
}
구현으로 이동하기 전에 작업을 구성 해 봅시다.
5.2. 구성
작업 정의도 다르게 보입니다 :
@Configuration
@EnableBatchProcessing
public class ChunksConfig {
@Autowired
private JobBuilderFactory jobs;
@Autowired
private StepBuilderFactory steps;
@Bean
public ItemReader<Line> itemReader() {
return new LineReader();
}
@Bean
public ItemProcessor<Line, Line> itemProcessor() {
return new LineProcessor();
}
@Bean
public ItemWriter<Line> itemWriter() {
return new LinesWriter();
}
@Bean
protected Step processLines(ItemReader<Line> reader,
ItemProcessor<Line, Line> processor, ItemWriter<Line> writer) {
return steps.get("processLines").<Line, Line> chunk(2)
.reader(reader)
.processor(processor)
.writer(writer)
.build();
}
@Bean
public Job job() {
return jobs
.get("chunksJob")
.start(processLines(itemReader(), itemProcessor(), itemWriter()))
.build();
}
}
이 경우 하나의 작업 만 수행하는 단계는 하나뿐입니다.
그러나이 태스크 릿 은 데이터 청크에 대해 작동하는 리더, 라이터 및 프로세서를 정의합니다 .
(가)주의 간격 커밋 데이터의 양이 하나 개의 덩어리로 처리 될 나타낸다 . 우리의 일은 한 번에 두 줄씩 읽고 처리하고 쓸 것입니다.
이제 청크 로직을 추가 할 준비가되었습니다!
5.3. 청크 LineReader 구성
LineReader 는 하나의 레코드를 읽고 그 내용으로 Line 인스턴스를 리턴합니다 .
독자가 되려면 클래스에서 ItemReader 인터페이스 를 구현해야합니다 .
public class LineReader implements ItemReader<Line> {
@Override
public Line read() throws Exception {
Line line = fu.readLine();
if (line != null)
logger.debug("Read line: " + line.toString());
return line;
}
}
코드는 간단하며 한 줄만 읽고 반환합니다. 또한 이 클래스의 최종 버전에 대해 StepExecutionListener 를 구현합니다 .
public class LineReader implements
ItemReader<Line>, StepExecutionListener {
private final Logger logger = LoggerFactory
.getLogger(LineReader.class);
private FileUtils fu;
@Override
public void beforeStep(StepExecution stepExecution) {
fu = new FileUtils("taskletsvschunks/input/tasklets-vs-chunks.csv");
logger.debug("Line Reader initialized.");
}
@Override
public Line read() throws Exception {
Line line = fu.readLine();
if (line != null) logger.debug("Read line: " + line.toString());
return line;
}
@Override
public ExitStatus afterStep(StepExecution stepExecution) {
fu.closeReader();
logger.debug("Line Reader ended.");
return ExitStatus.COMPLETED;
}
}
것으로 나타났습니다해야 beforeStep 및 애프터이 전에 각각 전체 단계 이후에 실행합니다.
5.4. 청크 LineProcessor 구성
LineProcessor 는 LineReader 와 거의 동일한 논리를 따릅니다 .
그러나이 경우 ItemProcessor 및 해당 메소드 process ()를 구현합니다 .
public class LineProcessor implements ItemProcessor<Line, Line> {
private Logger logger = LoggerFactory.getLogger(LineProcessor.class);
@Override
public Line process(Line line) throws Exception {
long age = ChronoUnit.YEARS
.between(line.getDob(), LocalDate.now());
logger.debug("Calculated age " + age + " for line " + line.toString());
line.setAge(age);
return line;
}
}
프로세스 () 메소드는, 입력 라인을 얻어이를 처리 및 출력 라인을 반환한다 . 다시 StepExecutionListener 도 구현 합니다.
public class LineProcessor implements
ItemProcessor<Line, Line>, StepExecutionListener {
private Logger logger = LoggerFactory.getLogger(LineProcessor.class);
@Override
public void beforeStep(StepExecution stepExecution) {
logger.debug("Line Processor initialized.");
}
@Override
public Line process(Line line) throws Exception {
long age = ChronoUnit.YEARS
.between(line.getDob(), LocalDate.now());
logger.debug(
"Calculated age " + age + " for line " + line.toString());
line.setAge(age);
return line;
}
@Override
public ExitStatus afterStep(StepExecution stepExecution) {
logger.debug("Line Processor ended.");
return ExitStatus.COMPLETED;
}
}
5.5. 청크 LinesWriter 구성
리더 및 프로세서와 달리 LinesWriter 는 전체 행 청크를 작성하여 행 목록 을 수신합니다 .
public class LinesWriter implements
ItemWriter<Line>, StepExecutionListener {
private final Logger logger = LoggerFactory
.getLogger(LinesWriter.class);
private FileUtils fu;
@Override
public void beforeStep(StepExecution stepExecution) {
fu = new FileUtils("output.csv");
logger.debug("Line Writer initialized.");
}
@Override
public void write(List<? extends Line> lines) throws Exception {
for (Line line : lines) {
fu.writeLine(line);
logger.debug("Wrote line " + line.toString());
}
}
@Override
public ExitStatus afterStep(StepExecution stepExecution) {
fu.closeWriter();
logger.debug("Line Writer ended.");
return ExitStatus.COMPLETED;
}
}
LinesWriter 코드는 스스로를 말합니다. 그리고 다시, 우리는 우리의 직업을 시험 할 준비가되었습니다.
5.6. 청크방식 잡 실행
우리는 태스크 릿 접근 방식을 위해 만든 것과 동일한 새로운 테스트를 만들 것입니다.
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ChunksConfig.class)
public class ChunksTest {
@Autowired
private JobLauncherTestUtils jobLauncherTestUtils;
@Test
public void givenChunksJob_whenJobEnds_thenStatusCompleted()
throws Exception {
JobExecution jobExecution = jobLauncherTestUtils.launchJob();
assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus());
}
}
구성한 후 ChunksConfig을 위해 위의 설명에 따라 TaskletsConfig , 우리는 테스트를 실행하기위한 모든 준비!
작업이 완료되면 output.csv 에 예상 결과가 다시 포함되고 로그에 흐름이 설명되어 있음을 알 수 있습니다 .
[main] DEBUG o.b.t.chunks.LineReader - Line Reader initialized.
[main] DEBUG o.b.t.chunks.LinesWriter - Line Writer initialized.
[main] DEBUG o.b.t.chunks.LineProcessor - Line Processor initialized.
[main] DEBUG o.b.t.chunks.LineReader - Read line: [Mae Hodges,10/22/1972]
[main] DEBUG o.b.t.chunks.LineReader - Read line: [Gary Potter,02/22/1953]
[main] DEBUG o.b.t.chunks.LineProcessor - Calculated age 45 for line [Mae Hodges,10/22/1972]
[main] DEBUG o.b.t.chunks.LineProcessor - Calculated age 64 for line [Gary Potter,02/22/1953]
[main] DEBUG o.b.t.chunks.LinesWriter - Wrote line [Mae Hodges,10/22/1972,45]
[main] DEBUG o.b.t.chunks.LinesWriter - Wrote line [Gary Potter,02/22/1953,64]
[main] DEBUG o.b.t.chunks.LineReader - Read line: [Betty Wise,02/17/1968]
[main] DEBUG o.b.t.chunks.LineReader - Read line: [Wayne Rose,04/06/1977]
[main] DEBUG o.b.t.chunks.LineProcessor - Calculated age 49 for line [Betty Wise,02/17/1968]
[main] DEBUG o.b.t.chunks.LineProcessor - Calculated age 40 for line [Wayne Rose,04/06/1977]
[main] DEBUG o.b.t.chunks.LinesWriter - Wrote line [Betty Wise,02/17/1968,49]
[main] DEBUG o.b.t.chunks.LinesWriter - Wrote line [Wayne Rose,04/06/1977,40]
[main] DEBUG o.b.t.chunks.LineReader - Read line: [Adam Caldwell,09/27/1995]
[main] DEBUG o.b.t.chunks.LineReader - Read line: [Lucille Phillips,05/14/1992]
[main] DEBUG o.b.t.chunks.LineProcessor - Calculated age 22 for line [Adam Caldwell,09/27/1995]
[main] DEBUG o.b.t.chunks.LineProcessor - Calculated age 25 for line [Lucille Phillips,05/14/1992]
[main] DEBUG o.b.t.chunks.LinesWriter - Wrote line [Adam Caldwell,09/27/1995,22]
[main] DEBUG o.b.t.chunks.LinesWriter - Wrote line [Lucille Phillips,05/14/1992,25]
[main] DEBUG o.b.t.chunks.LineProcessor - Line Processor ended.
[main] DEBUG o.b.t.chunks.LinesWriter - Line Writer ended.
[main] DEBUG o.b.t.chunks.LineReader - Line Reader ended.
우리는 같은 결과와 다른 흐름을 가지고 있습니다. 로그는이 접근 방식에 따라 작업이 어떻게 실행되는지를 분명하게 보여줍니다.
6. 결론
상황에 따라 다른 접근 방식이 필요하다는 것을 알 수 있습니다. Tasklet은 '다른 작업 후 하나의 작업'시나리오에 대해 더 자연 스럽지만 청크는 페이지에 읽은 읽기 또는 메모리에 많은 양의 데이터를 유지하고 싶지 않은 상황을 처리 할 수있는 간단한 솔루션을 제공합니다.
이 예제의 완전한 구현은 GitHub 프로젝트 에서 찾을 수 있습니다 .
참고
'Spring' 카테고리의 다른 글
Spring batch 로 CSV(액셀) 만들기 (0) | 2020.06.27 |
---|---|
Spring batch 재시도 (0) | 2020.06.25 |
Spring Boot 란 (0) | 2020.06.22 |
Spring boot web filter 예제 (0) | 2020.06.21 |
Spring, Spring boot mybatis 예제 (0) | 2020.06.21 |