반응형

이번 포스트에서는 스프링 배치를 활용하여 파일을 읽어 보겠습니다.

 

1. sample 파일을 하나 만들어주세요.

ID,lastName,firstName,position,birthYear,debutYear
AbduKa00,Abdul-Jabbar,Karim,rb,1974,1996
AbduRa00,Abdullah,Rabih,rb,1975,1999
AberWa00,Abercrombie,Walter,rb,1959,1982
AbraDa00,Abramowicz,Danny,wr,1945,1967
AdamBo00,Adams,Bob,te,1946,1969
AdamCh00,Adams,Charlie,wr,1979,2003

파일 구성은 csv 형태로 되어 있으며 첫줄 은 제목이 작성이 되어 있습니다.

 

2. 잡을 생성 하겠습니다.

private final JobBuilderFactory jobBuilderFactory;
private final StepBuilderFactory stepBuilderFactory;

@Bean
public Job flatFileJob(Step flatFileStep) {
    return jobBuilderFactory.get("flatFileJob")
            .incrementer(new RunIdIncrementer())
            .start(flatFileStep)
            .build();
}

잡을 만드는 방법은 앞에서의 학습과 동잉ㄹ합니다. 잡 / 스텝 빌더 팩도리를 주입 받고, flatFileJob이라는 잡을 생성하였습니다.

start 부분에는 스텝을 생성하였는데, 아직 스텝은 만들지 않았으니 스텝을 생성하겠습니다.

3. 스텝 코드 작성

@JobScope
@Bean
public Step flatFileStep(FlatFileItemReader<PlayerDto> playerFileItemReader) {
    return stepBuilderFactory.get("flatFileStep")
            .<PlayerDto, PlayerDto>chunk(5)
            .reader(playerFileItemReader)
            .writer(new ItemWriter<>() {
                @Override
                public void write(List<? extends PlayerDto> items) throws Exception {
                    items.forEach(System.out::println);
                }
            })
            .build();
}

chunk는 작업을 처리하는 개수입니다. 스텝에서는 chunk단위로 작업을 처리하게 되는데 현재 5개 단위로 작업을 처리 하겠습니다. 즉, 5개 아이템을 읽고, 이렇게 읽은 5개 아이템을 처리 한 다음에 5개 아이템을 기록 하겠습니다. 5개 작업 단위로 커밋이 쳐지는 걸 알 수 있습니다.

<PlayerDto, PlyerDto>는  PlayerDto 타입으로 읽어 드리고, PlayerDto 타입으로 쓰여지겠습니다.

reader()에는 파일을 읽어 들일 수 있는 FlatFileItemReader을 등록 하였고, writer()에는 이렇게 읽은 파일 내용을 콘솔에 출력하는 모습입니다.

이번 시간에는 파일을 읽어 들이는 학습을 진행하기 때문에 출력은 단순 출력을 진행합니다.

 

4. playerFileItemReader작성

@StepScope
@Bean
public FlatFileItemReader<PlayerDto> playerFileItemReader() {
    return new FlatFileItemReaderBuilder<PlayerDto>()
            .name("playerFileItemReader")
            .lineTokenizer(new DelimitedLineTokenizer())
            .linesToSkip(1)
            .fieldSetMapper(new PlayerFieldSetMapper())
            .resource(new FileSystemResource("player-list.txt"))
            .build();
}

DelimitedLineTokenizer을 작성하면 디폴트로 콤마로 파일을 나눌 수 있습니다. 첫번째 줄은 제목임으로 스킵을 하고 읽어들인 데이터를 매퍼를 통해서 PlayerDto로 만들게 됩니다.

 

DTO)

@Data
public class PlayerDto {
    private String ID;
    private String lastName;
    private String firstName;
    private String position;
    private int birthYear;
    private int debutYear;
}

 

5. 매퍼 함수 작성

public class PlayerFieldSetMapper implements FieldSetMapper<PlayerDto> {
    @Override
    public PlayerDto mapFieldSet(FieldSet fieldSet) throws BindException {
        PlayerDto dto = new PlayerDto();
        dto.setID(fieldSet.readString(0));
        dto.setLastName(fieldSet.readString(1));
        dto.setFirstName(fieldSet.readString(2));
        dto.setPosition(fieldSet.readString(3));
        dto.setBirthYear(fieldSet.readInt(4));
        dto.setDebutYear(fieldSet.readInt(5));

        return dto;
    }
}

읽어들인 파일 내용을 객체로 변경하기 위해서 FieldSetMapper를 구현한 매퍼를 작성하였습니다.

 

스프링 배치 파일 읽기

 

스프링 배치를 사용하지 않고 파일을 읽어들이는 것은 A부터 Z까지 개발을 해야 되지만, 스프링 배치를 사용하면 주어진 기능을 사용하면 되겠습니다. 또한 형식이 정형화가 되어 있기 때문에 장기적으로 본다면 유지보수에도 유리 하겠습니다.

 

공식문서)

https://docs.spring.io/spring-batch/docs/current/reference/html/readersAndWriters.html#flatFileItemReader

 

ItemReaders and ItemWriters

So far, only delimited files have been discussed in much detail. However, they represent only half of the file reading picture. Many organizations that use flat files use fixed length formats. An example fixed length file follows: The following example sho

docs.spring.io

반응형

+ Recent posts