Spring Batch启动时读取CSV存入HashMap的实现咨询
Spring Batch 读取CSV到全局可用HashMap的实现方案
核心结论
Spring Batch没有专门内置的ItemWriter用于写入内存HashMap,但你可以自定义实现ItemWriter<T>接口来完成这个需求,同时通过Spring Bean将HashMap配置为全局可用。
实现步骤与代码示例
1. 定义CSV对应的实体类
先创建与CSV字段匹配的POJO:
public class User { private String id; private String name; // 生成getter、setter方法 // 可选:生成toString()方便调试 }
2. 配置全局可用的HashMap Bean
用ConcurrentHashMap保证线程安全(Spring Batch可能多线程处理任务),并注册为Spring Bean:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @Configuration public class GlobalBeanConfig { @Bean public Map<String, User> userGlobalMap() { return new ConcurrentHashMap<>(); } }
3. 自定义ItemWriter写入HashMap
实现ItemWriter<User>接口,注入全局HashMap,批量写入数据:
import org.springframework.batch.item.ItemWriter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.List; import java.util.Map; @Component public class HashMapItemWriter implements ItemWriter<User> { private final Map<String, User> userGlobalMap; // 构造方法注入全局HashMap @Autowired public HashMapItemWriter(Map<String, User> userGlobalMap) { this.userGlobalMap = userGlobalMap; } @Override public void write(List<? extends User> items) throws Exception { // 批量将数据存入HashMap,这里用id作为key items.forEach(user -> userGlobalMap.put(user.getId(), user)); } }
4. 配置Spring Batch作业
组装Reader(读取CSV)、Writer(写入HashMap),构建完整作业:
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.file.FlatFileItemReader; import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper; import org.springframework.batch.item.file.mapping.DefaultLineMapper; import org.springframework.batch.item.file.transform.DelimitedLineTokenizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; @Configuration @EnableBatchProcessing public class BatchJobConfig { private final JobBuilderFactory jobBuilderFactory; private final StepBuilderFactory stepBuilderFactory; private final HashMapItemWriter hashMapItemWriter; public BatchJobConfig(JobBuilderFactory jobBuilderFactory, StepBuilderFactory stepBuilderFactory, HashMapItemWriter hashMapItemWriter) { this.jobBuilderFactory = jobBuilderFactory; this.stepBuilderFactory = stepBuilderFactory; this.hashMapItemWriter = hashMapItemWriter; } // 配置CSV读取器 @Bean public FlatFileItemReader<User> csvUserReader() { FlatFileItemReader<User> reader = new FlatFileItemReader<>(); // 指定CSV文件路径(这里放在resources目录下) reader.setResource(new ClassPathResource("users.csv")); // 配置行映射:分割字段并映射到User类 reader.setLineMapper(new DefaultLineMapper<User>() {{ setLineTokenizer(new DelimitedLineTokenizer() {{ // CSV的列名,要和User类的属性名对应 setNames("id", "name"); }}); setFieldSetMapper(new BeanWrapperFieldSetMapper<User>() {{ setTargetType(User.class); }}); }}); return reader; } // 配置处理步骤 @Bean public Step csvToHashMapStep() { return stepBuilderFactory.get("csvToHashMapStep") .<User, User>chunk(100) // 按100条为一批处理,可根据文件大小调整 .reader(csvUserReader()) .writer(hashMapItemWriter) .build(); } // 配置完整作业 @Bean public Job csvToHashMapJob() { return jobBuilderFactory.get("csvToHashMapJob") .start(csvToHashMapStep()) .build(); } }
5. 让作业在应用启动时自动执行
Spring Boot默认会自动执行所有注册的Batch Job(通过spring.batch.job.enabled=true,默认开启)。如果有多个Job,可在application.properties中指定要执行的Job:
spring.batch.job.names=csvToHashMapJob
全局使用HashMap
在其他Spring组件中,直接通过@Autowired注入全局HashMap即可使用:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.Map; @Service public class UserService { private final Map<String, User> userGlobalMap; @Autowired public UserService(Map<String, User> userGlobalMap) { this.userGlobalMap = userGlobalMap; } public User getUserById(String id) { return userGlobalMap.get(id); } }
内容的提问来源于stack exchange,提问作者ppb
相关产品推荐
相关产品推荐

