- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我目前正在为应用程序设置文件导入服务,允许用户通过 REST 上传 csv 文件。根据 future 的处理要求和检查,作业的导入将通过 Spring Batch 完成,因为这些作业可能会长时间运行。
根据我的说法,以下设置对于 Spring Boot 和 Spring Batch 是正确的,但代码无法编译。
主要的 BatchConfiguration 文件:
@Configuration
@EnableBatchProcessing
public class PatientBatchConfiguration {
@Autowired
private JobBuilderFactory jobBuilders;
@Autowired
private StepBuilderFactory stepBuilders;
@Autowired
private PatientFieldSetMapper fieldSetMapper;
@Autowired
private PatientItemWriter writer;
@Bean
public Job importPatientsFromUpload(){
return jobBuilders.get("importPatientsFromUpload")
.start(step())
.build();
}
@Bean
public Step step(){
return stepBuilders.get("step")
.<Patient,Patient>chunk(1)
.reader(reader(null))
.writer(writer)
.build();
}
@Bean
@StepScope
public ItemReader<Patient> reader(@Value("#{jobParameters['fileName']}") String filePath) {
FlatFileItemReader<Patient> itemReader = new FlatFileItemReader<Patient>();
itemReader.setLineMapper(lineMapper());
itemReader.setResource(new FileSystemResource(filePath));
return itemReader;
}
private LineMapper<Patient> lineMapper() {
DefaultLineMapper<Patient> lineMapper = new DefaultLineMapper<Patient>();
DelimitedLineTokenizer lineTokenizer = new DelimitedLineTokenizer();
lineTokenizer.setNames(new String[]{"name","surname","idNumber","dob", "email", "cell"});
lineMapper.setLineTokenizer(lineTokenizer);
lineMapper.setFieldSetMapper(fieldSetMapper);
return lineMapper;
}
}
FieldSetMapper代码:
@Component
public class PatientFieldSetMapper implements FieldSetMapper<Patient> {
@Override
public Patient mapFieldSet(FieldSet fieldSet) throws BindException {
if(fieldSet == null){
return null;
}
Patient patient = new Patient();
patient.setName(fieldSet.readString("name"));
patient.setSurname(fieldSet.readString("surname"));
patient.setIdNo(fieldSet.readString("idNumber"));
patient.setDob(0L);
patient.setEmail(fieldSet.readString("email"));
patient.setCell(fieldSet.readString("cell"));
return patient;
}
}
PatientItemWriter 代码:
@Component
public class PatientItemWriter implements ItemWriter<Patient> {
@Autowired
PatientRepository patientRepository;
@Override
public void write(List<? extends Patient> list) throws Exception {
for(Patient patient: list) {
patientRepository.save(patient);
}
}
}
堆栈跟踪:
Caused by: java.lang.IllegalArgumentException: Path must not be null
at org.springframework.util.Assert.notNull(Assert.java:115) ~[spring-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.core.io.FileSystemResource.<init>(FileSystemResource.java:75) ~[spring-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at com.example.batch.patient.PatientBatchConfiguration.reader(PatientBatchConfiguration.java:59) ~[classes/:na]
at com.example.batch.patient.PatientBatchConfiguration.step(PatientBatchConfiguration.java:49) ~[classes/:na]
最后是 application.properties 文件
spring.batch.job.enabled=false
spring.batch.job.enabled=false 位于属性文件中的原因是,作业 importPatientsFromUpload 将在用户上传文件后从 Controller 调用,如果没有它,作业将在启动时运行。
我遇到的问题是无法创建 FileSystemResource,因为路径不能为空。但是我知道,一旦有人用@StepScope 注释一个方法,就会创建一个代理 bean,这将允许我使用在运行时传递的 jobParameter 来创建一个新的文件系统资源。我在网上看到过各种以这种方式使用 jobParameters 的例子,但由于某种原因,bean 似乎没有被正确创建。我不确定这是否与我使用的是 Spring Boot 或其他一些错误有关。
如有任何帮助,我们将不胜感激。提前致谢。
更新回复 Gaël
PatientItemReader 代码:
@Component
@StepScope
public class PatientItemReader implements ItemReader<Patient> {
@Autowired
private PatientFieldSetMapper fieldSetMapper;
private FlatFileItemReader<Patient> itemReader;
@Override
public Patient read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
return itemReader.read();
}
public PatientItemReader(@Value("#{jobParameters[filePath]}") String filePath) {
itemReader = new FlatFileItemReader<Patient>();
DefaultLineMapper<Patient> lineMapper = new DefaultLineMapper<Patient>();
DelimitedLineTokenizer lineTokenizer = new DelimitedLineTokenizer();
lineTokenizer.setNames(new String[]{"name","surname","idNumber","dob", "email", "cell"});
lineMapper.setLineTokenizer(lineTokenizer);
lineMapper.setFieldSetMapper(fieldSetMapper);
itemReader.setLineMapper(lineMapper);
itemReader.setResource(new FileSystemResource(filePath));
}
}
最佳答案
我想问题是您在 Spring 之外创建读取器并在执行此操作时将其传递给 null
值:
@Bean
public Step step(){
...
.reader(reader(null))
...
}
为了使用像后期绑定(bind)这样的 Spring 功能,你应该做这样的事情:
@Autowired
private ItemReader<Patient> reader;
@Bean
public Step step(){
...
.reader(reader)
...
}
就像你为你的作家所做的那样。
关于java - Spring Boot + Spring Batch + @StepScope = 没有代理 Bean?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34744355/
如何准确定义步骤范围 bean 的生命周期,特别是当我有分区范围时? 例如: 网格大小= 4 SimplePartitioner 用作分区程序(将创建 4 个分区定义) RepositoryItemR
我正在使用 Spring Batch 版本 2.2.4.RELEASE我尝试用有状态的 ItemReader、ItemProcessor 和 ItemWriter bean 编写一个简单的示例。 pu
编辑 我创建了一个测试项目来复制这个问题。可以在 https://github.com/tomverelst/test-batch 找到它. 先运行maven命令exec:java启动 HSQL 数据
我尝试将 @Conditional 条件与 Spring Batch 的 @StepScope 一起使用,以在 Condition 中使用 jobParameter,但在条件初始化期间,JobScop
我正在使用 Spring Batch 设置作业服务器。我的 JdbcCursorItemReader 需要使用在每个作业运行时更改的 sql 配置。因为sql改变了,我希望读者有@StepScope这
我想将 Spring Batch 中的 JobParameter 传递到我的 PoiItemReader,以定位 Excelfilepath。所以我必须使用注释 @StepScope @StepSco
我目前正在为应用程序设置文件导入服务,允许用户通过 REST 上传 csv 文件。根据 future 的处理要求和检查,作业的导入将通过 Spring Batch 完成,因为这些作业可能会长时间运行。
我是一名优秀的程序员,十分优秀!