You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Spring Batch的Item Reader和Writer实现独立类拆分

实现Spring Batch Reader/Writer的组件化拆分

步骤1:创建独立的Item Reader组件

新建FFItemReader类,标记为@Component并实现ItemReader<Product>接口,把原配置类中的FlatFileItemReader初始化逻辑迁移过来:

import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.mapping.DefaultLineMapper;
import org.springframework.batch.item.file.transform.DelimitedLineTokenizer;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;

@Component
public class FFItemReader implements ItemReader<Product> {

    private final FlatFileItemReader<Product> delegateReader;

    // 构造方法完成Reader配置初始化
    public FFItemReader() {
        delegateReader = new FlatFileItemReader<>();
        delegateReader.setLinesToSkip(1); // 跳过CSV表头行
        delegateReader.setResource(new ClassPathResource("/data/Product_Details.csv"));

        // 配置行映射规则
        DefaultLineMapper<Product> lineMapper = new DefaultLineMapper<>();
        DelimitedLineTokenizer lineTokenizer = new DelimitedLineTokenizer();
        lineTokenizer.setNames("product_id", "product_name", "product_category", "product_price");

        lineMapper.setLineTokenizer(lineTokenizer);
        lineMapper.setFieldSetMapper(new ProductFieldSetMapper()); // 复用你已有的字段映射器
        delegateReader.setLineMapper(lineMapper);
    }

    @Override
    public Product read() throws Exception {
        return delegateReader.read();
    }
}

步骤2:创建独立的Item Writer组件

新建FFItemWriter类,标记为@Component并实现ItemWriter<Product>接口,注入DataSource并完成JdbcBatchItemWriter的初始化:

import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.database.JdbcBatchItemWriter;
import org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.util.List;

@Component
public class FFItemWriter implements ItemWriter<Product> {

    private final JdbcBatchItemWriter<Product> delegateWriter;

    // 构造方法注入DataSource
    public FFItemWriter(DataSource dataSource) {
        delegateWriter = new JdbcBatchItemWriter<>();
        delegateWriter.setDataSource(dataSource);
        delegateWriter.setSql("insert into product_details_output values (:productId, :productName, :productCategory, :productPrice)");
        delegateWriter.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider());

        // 调用afterPropertiesSet验证配置(JdbcBatchItemWriter要求必须执行此方法)
        try {
            delegateWriter.afterPropertiesSet();
        } catch (Exception e) {
            throw new RuntimeException("初始化JdbcBatchItemWriter失败", e);
        }
    }

    @Override
    public void write(List<? extends Product> items) throws Exception {
        delegateWriter.write(items);
    }
}

步骤3:修改Batch配置类,注入组件并配置Job/Step

删除原配置类中flatFileItemReader()和jdbcBatchItemWriter()的@Bean方法,改为通过@Autowired注入上述两个组件:

import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.job.builder.JobBuilder;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;

@Configuration
public class BatchConfiguration {

    @Autowired
    private FFItemReader ffItemReader;
    @Autowired
    private FFItemWriter ffItemWriter;

    @Bean
    public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
        return new StepBuilder("chunkBasedStep1", jobRepository)
                .<Product, Product>chunk(3, transactionManager) // 修正原代码泛型不一致问题
                .reader(ffItemReader)
                .writer(ffItemWriter)
                .build();
    }

    @Bean
    public Job firstJob(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
        return new JobBuilder("job1", jobRepository)
                .start(step1(jobRepository, transactionManager))
                .build();
    }

    // 如需配置多个Job,直接新增对应Job/Step的@Bean方法,注入不同的Reader/Writer即可
    // 示例:
    /*
    @Autowired
    private AnotherItemReader anotherItemReader;
    @Autowired
    private AnotherItemWriter anotherItemWriter;

    @Bean
    public Step step2(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
        return new StepBuilder("chunkBasedStep2", jobRepository)
                .<Product, Product>chunk(5, transactionManager)
                .reader(anotherItemReader)
                .writer(anotherItemWriter)
                .build();
    }

    @Bean
    public Job secondJob(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
        return new JobBuilder("job2", jobRepository)
                .start(step2(jobRepository, transactionManager))
                .build();
    }
    */
}

关键注意事项

  • 组件化拆分后,每个Reader/Writer都是Spring容器中的单例Bean,可被多个Job/Step复用。
  • 若需要不同配置的Reader/Writer,只需新建对应的@Component类即可,无需在配置类中重复编写Bean定义。
  • JdbcBatchItemWriter必须调用afterPropertiesSet()完成初始化,否则会抛出配置未完成的异常。
  • 确保ProductFieldSetMapper类已被Spring管理(可标记@Component),或在Reader中直接实例化(如原代码所示)。

内容的提问来源于stack exchange,提问作者Shahrukh Ali

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 18:04:50