首页 文章

使用Spring Batch将日期从文件解析为LocalDateTime

提问于
浏览
2

我正在尝试使用Spring Batch读取带有日期的CSV文件,但是我在将日期解析为 LocalDateTime 对象时遇到问题:

字段'date'上对象'target'中的字段错误:被拒绝的值[2017-07-20 04:15:25.0];代码[typeMismatch.target.date,typeMismatch.date,typeMismatch.java.time.LocalDateTime,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable:codes [target.date,date];参数[];默认消息[日期]];默认消息[无法将类型'java.lang.String'的属性值转换为属性'date'的必需类型'java.time.LocalDateTime';嵌套异常是java.lang.IllegalStateException:无法将类型'java.lang.String'的值转换为属性'date'所需的类型'java.time.LocalDateTime':找不到匹配的编辑器或转换策略]

Main.java

public class Main {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(SpringBatchDateParseConfig.class);

        JobLauncher jobLauncher = context.getBean(JobLauncher.class);
        Job job = context.getBean("job", Job.class);

        JobParameters jobParameters = new JobParametersBuilder().toJobParameters();

        try {
            JobExecution jobExecution = jobLauncher.run(job, jobParameters);
        }
        catch (Exception e) {
            e.printStackTrace();
        }

    }
}

SpringBatchDateParseConfig.java

@Configuration
@EnableBatchProcessing
public class SpringBatchDateParseConfig {
    @Inject
    private JobBuilderFactory jobBuilderFactory;

    @Inject
    private StepBuilderFactory stepBuilderFactory;

    @Bean
    public Step step1() {
        return stepBuilderFactory.get("step1")
                                 .<TestClass, TestClass>chunk(2)
                                 .reader(testClassItemReader())
                                 .writer(testClassItemWriter())
                                 .build();
    }

    @Bean
    public Job job(Step step1) {
        return jobBuilderFactory.get("job")
                .start(step1)
                .build();
    }

    @Bean
    FlatFileItemReader<TestClass> testClassItemReader() {
        FlatFileItemReader<TestClass> flatFileItemReader = new FlatFileItemReader<>();
        flatFileItemReader.setResource(new ClassPathResource("test.csv"));
        flatFileItemReader.setLinesToSkip(1);
        DefaultLineMapper defaultLineMapper = new DefaultLineMapper();
        DelimitedLineTokenizer delimitedLineTokenizer = new DelimitedLineTokenizer();
        delimitedLineTokenizer.setNames(new String[]{"foo", "bar", "date"});

        BeanWrapperFieldSetMapper<TestClass> fieldSetMapper = new BeanWrapperFieldSetMapper<>();
        fieldSetMapper.setTargetType(TestClass.class);

        defaultLineMapper.setLineTokenizer(delimitedLineTokenizer);
        defaultLineMapper.setFieldSetMapper(fieldSetMapper);
        flatFileItemReader.setLineMapper(defaultLineMapper);

        return flatFileItemReader;

    }

    @Bean
    ItemWriter<TestClass> testClassItemWriter() {
        return new ItemWriter<TestClass>() {
            @Override
            public void write(List<? extends TestClass> items) throws Exception {
                for (TestClass TestClass : items) {
                    System.out.println(TestClass.toString());
                }
            }
        };
    }
}

TestClass.java

public class TestClass {

    private String foo;
    private String bar;
    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME, pattern = "yyyy-MM-dd H:m:s.S")
    private LocalDateTime date;

    public String getFoo() {
        return foo;
    }

    public void setFoo(String foo) {
        this.foo = foo;
    }

    public String getBar() {
        return bar;
    }

    public void setBar(String bar) {
        this.bar = bar;
    }

    public LocalDateTime getDate() {
        return date;
    }

    public void setDate(LocalDateTime date) {
        this.date = date;
    }
}

test.csv

foo,bar,date
asdf,fdsa,2017-07-20 04:15:25.0
qwerty,ytrewq,2017-07-20 04:15:25.0

我错过了什么吗?

1 回答

  • 3

    您可以覆盖BeanWrapperFieldSetMapper的方法initBinder:

    public class BeanWrapperFieldSetMapperCustom<T> extends BeanWrapperFieldSetMapper<T> {
    
        @Override
        protected void initBinder(DataBinder binder) {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
            binder.registerCustomEditor(LocalDate.class, new PropertyEditorSupport() {
                @Override
                public void setAsText(String text) throws IllegalArgumentException {
                    if (StringUtils.isNotEmpty(text)) {
                        setValue(LocalDate.parse(text, formatter));
                    } else {
                        setValue(null);
                    }
                }
    
                @Override
                public String getAsText() throws IllegalArgumentException {
                    Object date = getValue();
                    if (date != null) {
                        return formatter.format((LocalDate) getValue());
                    } else {
                        return "";
                    }
                }
            });
        }
    }
    

相关问题