访问作业参数 Spring Batch
Posted
技术标签:
【中文标题】访问作业参数 Spring Batch【英文标题】:Accessing Job Parameters Spring Batch 【发布时间】:2017-06-15 02:51:16 【问题描述】:我一直在努力使用 Spring Batch 访问作业的作业参数。到目前为止,这是我的实现。
@Configuration
@EnableBatchProcessing
@PropertySource("classpath:batch.properties")
public class CSVBatchServiceImpl extends StepExecutionListenerSupport implements CSVBatchService
private static final Logger LOGGER = LoggerFactory.getLogger(CSVBatchServiceImpl.class);
@Autowired
public JobBuilderFactory jobBuilderFactory;
@Autowired
public StepBuilderFactory stepBuilderFactory;
private QuestionReader questionReader = new QuestionReader();
@Bean(name = "importQuestionsJob")
public Job importQuestionsJob()
return jobBuilderFactory.get("importQuestionsJob")
.incrementer(new RunIdIncrementer())
.flow(step1())
.end()
.build();
@Bean
public Step step1()
return stepBuilderFactory.get("step1")
.<Question, Question>chunk(2)
.reader(questionReader.reader())
.processor(processor())
.build();
@Bean
public QuestionProcessor processor()
return new QuestionProcessor();
class QuestionReader extends StepExecutionListenerSupport
private static final Logger LOGGER = LoggerFactory.getLogger(QuestionReader.class);
//TODO: remove this
private static JsonNode getJsonNode(String str)
try
ObjectMapper mapper = new ObjectMapper();
return mapper.readTree(str);
catch (IOException e)
throw new RuntimeException(e);
@Bean
public FlatFileItemReader<Question> reader()
FlatFileItemReader<Question> reader = new FlatFileItemReader<>();
//TODO get this as a parameter
reader.setResource(new ClassPathResource("duplicateLabels.csv"));
reader.setLinesToSkip(1);
reader.setLineMapper(new DefaultLineMapper<Question>()
setLineTokenizer((new DelimitedLineTokenizer()
setNames(new String[]"label", "body", "real_answer");
));
setFieldSetMapper(new QuestionFieldSetMapper());
);
return reader;
private static class QuestionFieldSetMapper implements FieldSetMapper<Question>
public Question mapFieldSet(FieldSet fieldSet)
Question question = new Question();
question.setLabel(fieldSet.readString(0));
question.setBody(getJsonNode(fieldSet.readString(1)));
question.setRealAnswer(getJsonNode(fieldSet.readString(2)));
return question;
我这样称呼这份工作:
JobParameters parameters = new JobParametersBuilder()
.addLong("time", System.currentTimeMillis())
.addString("filePath", "file.csv")
.toJobParameters();
jobLauncher.run(importQuestionsJob, parameters);
如何访问 reader 函数中的 filePath 参数?
【问题讨论】:
【参考方案1】:另一个非常适用于ItemProcessors、ItemReaders、ItemWriters 等的解决方案是@BeforeStep 注释。它由StepExecutionListener 支持,就像Eugene To mentioned 一样。这是该解决方案的一种捷径。
实现可能如下所示
@BeforeStep
public void beforeStep(StepExecution stepExecution)
JobParameters jobParameters = stepExecution.getJobParameters();
Long millis = jobParameters.getLong("time");
String path = jobParameters.getString("filePath");
【讨论】:
【参考方案2】:你应该可以的,
@Value("#jobParameters['filePath']") String filePath;
如果有任何问题,您可以尝试将您的读者置于@StepScope
。
【讨论】:
设置范围是强制性的,如果没有它,它将不起作用。 如果你能告诉我我可以在哪里添加代码,我将不胜感激。 我猜,您需要在reader()
方法中使用它,以便您可以更改阅读器签名,如 reader(@Value("#jobParameters['filePath']") String filePath)
但请确保您使用 @StepScope
注释 reader
。在您的步骤定义中,您可以为此参数传递null
,例如questionReader.reader(null)
。【参考方案3】:
您可以将org.springframework.batch.core.listener.JobParameterExecutionContextCopyListener
添加到您的步骤中。
TaskletStep step = stepBuilderFactory.get("my-best-step")
.<Item, Item>chunk(10)
.reader(myBestReader)
.writer(myBestWriter)
.listener(new JobParameterExecutionContextCopyListener())
.build();
Listener 会将 JobParameters
复制到 ItemReader 的 open 和 update 方法中可用的 ExecutionContext
【讨论】:
【参考方案4】:访问作业参数的一种方法是在您的阅读器类中实现 StepExecutionListener,以利用其重写的方法 beforeStep 和 afterStep,
@Override
public void beforeStep(StepExecution stepExecution)
String filePath = (String) stepExecution.getJobExecution().getExecutionContext()
.get("filePath");
【讨论】:
以上是关于访问作业参数 Spring Batch的主要内容,如果未能解决你的问题,请参考以下文章
Spring Cloud Task 参数不会传播到 Spring Batch 作业参数
Spring Batch ORA-08177: 运行单个作业时无法序列化此事务的访问,SERIALIZED 隔离级别
从 tasklet 步骤将参数添加到作业上下文并在 Spring Batch 的后续步骤中使用
SPRING BATCH:嵌套异常是java.sql.SQLException:ORA-08177:无法序列化此事务的访问权限