Spring中如何使用spring-batch-excel的PoiItemReader Bean读取Excel数据?
Hey there! Let's walk through how to use that PoiItemReader bean you've configured, since you're new to Spring and Spring Batch. First off, don't call the excelReader() method directly—that would create a new instance instead of using the one Spring's container manages for you. Here's what to do instead:
1. Inject the PoiItemReader into Your Custom Class
Use Spring's dependency injection to get the pre-configured PoiItemReader bean into your own reader class. Constructor injection is the recommended approach—it's safer and easier to test:
import org.springframework.batch.item.excel.poi.PoiItemReader; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.List; @Component public class YourCustomReader { private final PoiItemReader excelReader; // Spring automatically passes the PoiItemReader bean here public YourCustomReader(PoiItemReader excelReader) { this.excelReader = excelReader; } // Methods to read Excel data will go here }
2. Read Excel Rows Using the Injected Reader
The PoiItemReader implements Spring Batch's ItemReader interface, which has a read() method. This method returns one row of data at a time (as an Object[] since you're using PassThroughRowMapper) and returns null when there are no more rows left.
To collect all rows into a list, loop through the read() method like this:
public List<Object[]> getAllExcelRows() throws Exception { List<Object[]> allRows = new ArrayList<>(); Object[] currentRow; // Keep reading until read() returns null (end of the Excel file) while ((currentRow = (Object[]) excelReader.read()) != null) { allRows.add(currentRow); } return allRows; }
Note on PassThroughRowMapper
Since you're using PassThroughRowMapper, each Excel row is converted directly into an Object[] where each element maps to a cell's value. If you later switch to a custom RowMapper that maps rows to your own entity class (e.g., Customer), the read() method will return instances of that class instead.
3. Bonus: The Spring Batch Way (Recommended for Production)
While manual read() calls work for small tasks, Spring Batch is built to handle end-to-end batch processing with Jobs and Steps. Here's a quick example of wiring your PoiItemReader into a full batch job:
import org.springframework.batch.core.Job; import org.springframework.batch.core.Step; import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; import org.springframework.batch.item.ItemWriter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.Arrays; @Configuration @EnableBatchProcessing public class BatchConfig { private final JobBuilderFactory jobBuilderFactory; private final StepBuilderFactory stepBuilderFactory; private final PoiItemReader excelReader; public BatchConfig(JobBuilderFactory jobBuilderFactory, StepBuilderFactory stepBuilderFactory, PoiItemReader excelReader) { this.jobBuilderFactory = jobBuilderFactory; this.stepBuilderFactory = stepBuilderFactory; this.excelReader = excelReader; } @Bean public Step excelProcessingStep(ItemWriter<Object[]> excelWriter) { return stepBuilderFactory.get("excelProcessingStep") .<Object[], Object[]>chunk(10) // Process 10 rows at a time .reader(excelReader) .writer(excelWriter) .build(); } @Bean public ItemWriter<Object[]> excelWriter() { return items -> { // Process rows here (e.g., save to database, transform data) for (Object[] row : items) { System.out.println("Processing row: " + Arrays.toString(row)); } }; } @Bean public Job excelImportJob(Step excelProcessingStep) { return jobBuilderFactory.get("excelImportJob") .start(excelProcessingStep) .build(); } }
You can launch this job using a JobLauncher on application start, or expose an endpoint to trigger it manually if you're using Spring Boot.
内容的提问来源于stack exchange,提问作者Avi Rudich

