1. 개요
Spring Batch 는 강력한 배치 애플리케이션을 개발하기 위한 강력한 프레임워크입니다. 이전 예제에서 Spring Batch를 소개 했습니다.
이 예제에서는 이전 예제을 기반으로 Spring Boot 를 사용하여 기본 배치 기반 애플리케이션을 설정하고 생성하는 방법을 배웁니다 .
2. 메이븐 의존성
먼저 pom.xml 에 spring-boot-starter-batch 를 추가해 보겠습니다 .
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
<version>2.7.2</version>
</dependency>
Maven Central 에서도 사용할 수 있는 org.hsqldb 의존성 도 추가합니다 .
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>2.5.1</version>
<scope>runtime</scope>
</dependency>
3. 간단한 스프링 배치 작업 정의
CSV 파일에서 커피 List을 가져오고 사용자 정의 프로세서를 사용하여 변환하고 메모리 내 데이터베이스에 최종 결과를 저장하는 작업을 빌드할 것입니다 .
3.1. 시작하기
애플리케이션 진입점을 정의하여 시작하겠습니다.
@SpringBootApplication
public class SpringBootBatchProcessingApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootBatchProcessingApplication.class, args);
}
}
보시다시피 이것은 표준 Spring Boot 애플리케이션입니다. 가능한 경우 기본 구성 값을 사용하려고 하므로 매우 가벼운 애플리케이션 구성 속성 집합을 사용할 것입니다.
src/main/resources/application.properties 파일 에서 이러한 속성을 정의 합니다.
file.input=coffee-list.csv
이 속성에는 입력 커피 List의 위치가 포함되어 있습니다. 각 줄에는 브랜드, 산지 및 커피의 몇 가지 특성이 포함되어 있습니다.
Blue Mountain,Jamaica,Fruity
Lavazza,Colombia,Strong
Folgers,America,Smokey
앞으로 살펴보겠지만 이것은 일반 CSV 파일이므로 Spring에서 특별한 사용자 지정 없이 처리할 수 있습니다.
다음으로 SQL 스크립트 schema-all.sql 을 추가 하여 데이터를 저장할 커피 테이블을 만듭니다 .
DROP TABLE coffee IF EXISTS;
CREATE TABLE coffee (
coffee_id BIGINT IDENTITY NOT NULL PRIMARY KEY,
brand VARCHAR(20),
origin VARCHAR(20),
characteristics VARCHAR(30)
);
편리하게도 Spring Boot는 시작하는 동안 이 스크립트를 자동으로 실행합니다 .
3.2. 커피 도메인 클래스
결과적으로 커피 항목을 보관할 간단한 도메인 클래스가 필요합니다.
public class Coffee {
private String brand;
private String origin;
private String characteristics;
public Coffee(String brand, String origin, String characteristics) {
this.brand = brand;
this.origin = origin;
this.characteristics = characteristics;
}
// getters and setters
}
앞에서 언급했듯이 Coffee 개체에는 세 가지 속성이 있습니다.
- 브랜드
- 기원
- 몇 가지 추가 특성
4. 작업 구성
이제 핵심 구성 요소인 작업 구성에 대해 살펴보겠습니다. 단계별로 구성을 구축하고 그 과정에서 각 부분을 설명하겠습니다.
@Configuration
@EnableBatchProcessing
public class BatchConfiguration {
@Autowired
public JobBuilderFactory jobBuilderFactory;
@Autowired
public StepBuilderFactory stepBuilderFactory;
@Value("${file.input}")
private String fileInput;
// ...
}
먼저 표준 Spring @Configuration 클래스로 시작합니다. 다음으로 클래스에 @EnableBatchProcessing 어노테이션을 추가합니다. 특히 이것은 작업을 지원하고 다리 작업을 많이 줄여주는 많은 유용한 빈에 대한 액세스를 제공합니다.
또한 이 어노테이션을 사용하면 나중에 작업 구성 및 작업 단계를 빌드할 때 사용할 두 가지 유용한 팩토리에 대한 액세스도 제공됩니다.
초기 구성의 마지막 부분에서는 이전에 선언한 file.input 속성에 대한 참조를 포함합니다.
4.1. 우리 일을 위한 독자이자 작가
이제 구성에서 리더 빈을 정의할 수 있습니다.
@Bean
public FlatFileItemReader reader() {
return new FlatFileItemReaderBuilder().name("coffeeItemReader")
.resource(new ClassPathResource(fileInput))
.delimited()
.names(new String[] { "brand", "origin", "characteristics" })
.fieldSetMapper(new BeanWrapperFieldSetMapper() {{
setTargetType(Coffee.class);
}})
.build();
}
요컨대 위에서 정의한 리더 빈은 coffee-list.csv 라는 파일을 찾고 각 라인 항목을 Coffee 개체 로 구문 분석합니다 .
마찬가지로 writer bean을 정의합니다.
@Bean
public JdbcBatchItemWriter writer(DataSource dataSource) {
return new JdbcBatchItemWriterBuilder()
.itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>())
.sql("INSERT INTO coffee (brand, origin, characteristics) VALUES (:brand, :origin, :characteristics)")
.dataSource(dataSource)
.build();
}
이번에는 Coffee 개체의 Java bean 속성에 의해 구동되는 단일 커피 항목을 데이터베이스에 삽입하는 데 필요한 SQL 문을 포함합니다. 쉽게 dataSource 는 @EnableBatchProcessing 어노테이션 에 의해 자동으로 생성됩니다 .
4.2. 우리의 일을 하나로 모으기
마지막으로 실제 작업 단계와 구성을 추가해야 합니다.
@Bean
public Job importUserJob(JobCompletionNotificationListener listener, Step step1) {
return jobBuilderFactory.get("importUserJob")
.incrementer(new RunIdIncrementer())
.listener(listener)
.flow(step1)
.end()
.build();
}
@Bean
public Step step1(JdbcBatchItemWriter writer) {
return stepBuilderFactory.get("step1")
.<Coffee, Coffee> chunk(10)
.reader(reader())
.processor(processor())
.writer(writer)
.build();
}
@Bean
public CoffeeItemProcessor processor() {
return new CoffeeItemProcessor();
}
보시다시피 작업은 비교적 간단하며 step1 메서드에 정의된 한 단계로 구성됩니다.
이 단계가 수행하는 작업을 살펴보겠습니다.
- 먼저, chunk(10) 선언 을 사용하여 한 번에 최대 10개의 레코드를 쓰도록 단계를 구성합니다.
- 그런 다음, reader 메서드 를 사용하여 설정한 reader bean을 사용하여 커피 데이터를 읽습니다.
- 다음으로 각 커피 항목을 Custom형 비즈니스 로직을 적용하는 Custom형 프로세서로 전달합니다.
- 마지막으로 이전에 본 작성자를 사용하여 각 커피 항목을 데이터베이스에 씁니다.
반면 importUserJob 에는 내장된 RunIdIncrementer 클래스 를 사용하는 ID가 포함된 작업 정의가 포함되어 있습니다 . 또한 작업이 완료될 때 알림을 받는 데 사용 하는 JobCompletionNotificationListener 도 설정합니다 .
작업 구성을 완료하기 위해 각 단계를 나열합니다(이 작업에는 한 단계만 있음). 이제 완벽하게 구성된 작업이 있습니다!
5. 커스텀 커피 프로세서
작업 구성에서 이전에 정의한 사용자 지정 프로세서를 자세히 살펴보겠습니다.
public class CoffeeItemProcessor implements ItemProcessor<Coffee, Coffee> {
private static final Logger LOGGER = LoggerFactory.getLogger(CoffeeItemProcessor.class);
@Override
public Coffee process(final Coffee coffee) throws Exception {
String brand = coffee.getBrand().toUpperCase();
String origin = coffee.getOrigin().toUpperCase();
String chracteristics = coffee.getCharacteristics().toUpperCase();
Coffee transformedCoffee = new Coffee(brand, origin, chracteristics);
LOGGER.info("Converting ( {} ) into ( {} )", coffee, transformedCoffee);
return transformedCoffee;
}
}
특히 흥미롭게도 ItemProcessor 인터페이스는 작업 실행 중에 일부 특정 비즈니스 로직을 적용하는 메커니즘을 제공합니다.
단순하게 유지하기 위해 입력 Coffee 개체를 사용하고 각 속성을 대문자로 변환 하는 CoffeeItemProcessor 를 정의합니다 .
6. 작업 완료
또한 작업이 완료되면 몇 가지 피드백을 제공하기 위해 JobCompletionNotificationListener 를 작성할 것입니다.
@Override
public void afterJob(JobExecution jobExecution) {
if (jobExecution.getStatus() == BatchStatus.COMPLETED) {
LOGGER.info("!!! JOB FINISHED! Time to verify the results");
String query = "SELECT brand, origin, characteristics FROM coffee";
jdbcTemplate.query(query, (rs, row) -> new Coffee(rs.getString(1), rs.getString(2), rs.getString(3)))
.forEach(coffee -> LOGGER.info("Found < {} > in the database.", coffee));
}
}
위의 예에서는 afterJob 메서드를 재정의하고 작업이 성공적으로 완료되었는지 확인합니다. 또한 간단한 쿼리를 실행하여 각 커피 항목이 데이터베이스에 성공적으로 저장되었는지 확인합니다 .
7. 작업 실행
이제 우리는 작업을 실행하기 위한 모든 것을 갖추고 있으므로 재미있는 부분이 있습니다. 계속해서 작업을 실행해 보겠습니다.
...
17:41:16.336 [main] INFO c.b.b.JobCompletionNotificationListener -
!!! JOB FINISHED! Time to verify the results
17:41:16.336 [main] INFO c.b.b.JobCompletionNotificationListener -
Found < Coffee [brand=BLUE MOUNTAIN, origin=JAMAICA, characteristics=FRUITY] > in the database.
17:41:16.337 [main] INFO c.b.b.JobCompletionNotificationListener -
Found < Coffee [brand=LAVAZZA, origin=COLOMBIA, characteristics=STRONG] > in the database.
17:41:16.337 [main] INFO c.b.b.JobCompletionNotificationListener -
Found < Coffee [brand=FOLGERS, origin=AMERICA, characteristics=SMOKEY] > in the database.
...
보시다시피 작업이 성공적으로 실행되었고 각 커피 항목이 예상대로 데이터베이스에 저장되었습니다 .
8. 결론
이 기사에서는 Spring Boot를 사용하여 간단한 Spring Batch 작업을 생성하는 방법을 배웠습니다. 먼저 몇 가지 기본 구성을 정의하는 것으로 시작했습니다.
그런 다음 파일 판독기와 데이터베이스 작성기를 추가하는 방법을 살펴보았습니다. 마지막으로 일부 사용자 정의 처리를 적용하고 작업이 성공적으로 실행되었는지 확인하는 방법을 살펴보았습니다.
언제나처럼 기사의 전체 소스 코드는 GitHub에서 확인할 수 있습니다 .