我有一个文件,其中第一行包含字段名称作为标题,如下所示:
Id;ToyName;ToyType;ToyColor
1;abc;abc;red
2;pqr;pqr;blue
3;xyz;xyz;orange
我的读者如下:
<beans:bean id="MyFileItemReader" class="org.springframework.batch.item.file.FlatFileItemReader" scope="step">
<beans:property name="linesToSkip" value="1"/>
<beans:property name="skippedLinesCallback" ref="headerSkipCallback" />
<beans:property name="resource" ref="MyInputFileResource" />
<beans:property name="lineMapper">
<beans:bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
<beans:property name="lineTokenizer">
<beans:bean class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
<beans:property name="delimiter" value=";"/>
<beans:property name="names" value="#{jobExecutionContext['columnsFromFileHeader']}" />
</beans:bean>
</beans:property>
<beans:property name="fieldSetMapper">
<beans:bean class="mypackage.MyFieldSetMapper">
</beans:bean>
</beans:property>
</beans:bean>
</beans:property>
</beans:bean>
因此,我实现了一个标题行回调,以读取跳过的标题行。
<beans:bean id="headerSkipCallback" class="mypackage.HeaderLineHandler" scope="step">
</beans:bean>
和班级:
public class HeaderLineHandler implements LineCallbackHandler {
public void handleLine(final String headerLine) {
System.out.println(headerLine);
}}
这样可以正常工作,并打印文件中的标题行。
现在我想在names
DefaultLineTokenizer
属性中使用文件头中的这些字段名称
因此,为了将标题行放在上下文中,我实现了一个上下文注入类,如下所示:
public class StepExecutionListenerCtxInjector {
private ExecutionContext stepExecutionCtx;
private ExecutionContext jobExecutionCtx;
@BeforeStep
public void beforeStep(final StepExecution stepExecution) {
this.stepExecutionCtx = stepExecution.getExecutionContext();
this.jobExecutionCtx = stepExecution.getJobExecution().getExecutionContext();
}
public ExecutionContext getStepExecutionCtx() {
return this.stepExecutionCtx;
}
public ExecutionContext getJobExecutionCtx() {
return this.jobExecutionCtx;
}
}
并将我的标题行处理程序更改为:
<beans:bean id="headerSkipCallback" class="mypackage.HeaderLineHandler" scope="step">
<beans:property name="stepExecutionListener" ref="stepExecutionListener" />
</beans:bean>
和班级:
public class HeaderLineHandler implements LineCallbackHandler {
private StepExecutionListenerCtxInjector stepExecutionListener;
public void handleLine(final String headerLine) {
this.stepExecutionListener.getJobExecutionCtx().put("columnsFromFileHeader", headerLine.replaceAll(";", ","));
}
// getter setters
}
这里我将标题行保存为作业执行上下文中的columnsFromFile
键。
但是,当我尝试在DefaultLineTokenizer
中访问它时:
<beans:property name="names" value="#{jobExecutionContext['columnsFromFileHeader']}" />
我得到空指针异常:
org.springframework.batch.item.file.FlatFileParseException: Parsing error at line: 2 in resource=[file [C:\myFile.dat]], input=[1;abc;abc;red]
at org.springframework.batch.item.file.FlatFileItemReader.doRead(FlatFileItemReader.java:182)
Caused by:
java.lang.NullPointerException
at org.springframework.batch.item.file.transform.AbstractLineTokenizer.tokenize(AbstractLineTokenizer.java:113)
如何将属性中文件的标题行用于DefaultLineTokenizer
?
答案 0 :(得分:0)
将DelimitedLineTokenizer
设为非匿名bean并将其注入HeaderLineHandler
;在HeaderLineHandler.handleLine()
使用DelimitedLineTokenizer.names
输入参数设置handleLine()
我无法测试它,但应该可行。