这是我在这里发表的第一篇文章。如果我不遵守集团规则,我会提前道歉。
基本上我遇到了与Spring Batch相关的问题。
我需要阅读并处理包含多条记录的文件。如下所示:
HEADER
BATCH
CUST
TRANS
CUST
OPT
TRANS
CUST
OPT
TRANS
CUST
OPT
TRANS
CUST
OPT
TRANS
BATCHFOOTER
CUSTFOOTER
TRANFOOTER
我只需要读取以CUST AND TRANS开头的行并跳过所有其他行。我尝试过使用PatternMatchingCompositeLineMapper,但如果我们不映射其他人,那么我们会得到例外。如何跳过某些行?救命。提前谢谢。
此致 塔兰
答案 0 :(得分:2)
使用PatternMatchingCompositeLineMapper
标记线和映射到CUST和TRANS线的正确域bean
对于除了CUST和TRANS之外的行,写一个用于从一行到一个泛型bean的通用FieldSetMapper
(我们称之为GenericBeanToSkip
。)。
使用ClassifierCompositeItemProcessor
进程CUST和TRANS转换的bean,但跳过从GenericBeanToSkip
返回null
的{{1}}。
答案 1 :(得分:2)
Spring批处理具有读取复杂文件的能力。唯一的问题是我们必须编写自己的读者来处理复杂的文件。我们可以通过spring Batch读取具有特定模式的文件。
这是文件格式,如文件
CUST,Warren,Q,Darrow,8272 4th Street,New York,IL,76091
TRANS,1165965,2011-01-22 00:13:29,51.43
CUST,Ann,V,Gates,9247 Infinite Loop Drive,Hollywood,NE,37612
CUST,Erica,I,Jobs,8875 Farnam Street,Aurora,IL,36314
TRANS,8116369,2011-01-21 20:40:52,-14.83
TRANS,8116369,2011-01-21 15:50:17,-45.45
TRANS,8116369,2011-01-21 16:52:46,-74.6
TRANS,8116369,2011-01-22 13:51:05,48.55
TRANS,8116369,2011-01-21 16:51:59,98.53
自定义FileReader
import Java.util.ArrayList;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.item.ItemStreamException;
import org.springframework.batch.item.ItemStreamReader;
import org.springframework.batch.item.ParseException;
import org.springframework.batch.item.UnexpectedInputException;
public class CustomerFileReader implements ItemStreamReader<Object> {
private Object curItem = null;
private ItemStreamReader<Object> delegate;
public Object read() throws Exception {
if(curItem == null) {
curItem = (Customer) delegate.read();
}
Customer item = (Customer) curItem;
curItem = null;
if(item != null) {
item.setTransactions(new ArrayList<Transaction>());
while(peek() instanceof Transaction) {
curItem = null;
}
}
return item;
}
public Object peek() throws Exception, UnexpectedInputException,
ParseException {
if (curItem == null) {
curItem = delegate.read();
}
return curItem;
}
public void setDelegate(ItemStreamReader<Object> delegate) {
this.delegate = delegate;
}
public void close() throws ItemStreamException {
delegate.close();
}
public void open(ExecutionContext arg0) throws ItemStreamException {
delegate.open(arg0);
}
public void update(ExecutionContext arg0) throws ItemStreamException {
delegate.update(arg0);
}
}
配置
<beans:bean id="customerFile"
class="org.springframework.core.io.FileSystemResyource" scope="step">
<beans:constructor-arg value="#{jobParameters[customerFile]}"/>
</beans:bean>
<beans:bean id="customerFileReader"
class="com.apress.springbatch.chapter7.CustomerFileReader">
<beans:property name="delegate" ref="trueCustomerFileReader"/>
</beans:bean>
<beans:bean id="trueCustomerFileReader"
class="org.springframework.batch.item.file.FlatFileItemReader">
<beans:property name="resource" ref="customerFile" />
<beans:property name="lineMapper">
<beans:bean class="org.springframework.batch.item.file.mapping.
PatternMatchingCompositeLineMapper">
<beans:property name="tokenizers">
<beans:map>
<beans:entry key="CUST*" value-ref="customerLineTokenizer"/>
<beans:entry key="TRANS*" value-ref="transactionLineTokenizer"/>
</beans:map>
</beans:property>
<beans:property name="fieldSetMappers">
<beans:map>
<beans:entry key="CUST*" value-ref="customerFieldSetMapper"/>
<beans:entry key="TRANS*" value-ref="transactionFieldSetMapper"/>
</beans:map>
</beans:property>
</beans:bean>
</beans:property>
</beans:bean>
<beans:bean id="customerLineTokenizer"
class="org.springframework.batch.item.file.transform.
DelimitedLineTokenizer">
<beans:property name="names" value="prefix,firstName,middleInitial,
lastName,address,city,state,zip"/>
<beans:property name="delimiter" value=","/>
</beans:bean>
<beans:bean id="transactionLineTokenizer"
class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
<beans:property name="names"
value="prefix,accountNumber,transactionDate,amount"/>
<beans:property name="delimiter" value=","/>
</beans:bean>
<beans:bean id="customerFieldSetMapper"
class="org.springframework.batch.item.file.mapping.
BeanWrapperFieldSetMapper">
<beans:property name="prototypeBeanName" value="customer"/>
</beans:bean>
<beans:bean id="transactionFieldSetMapper"
class="com.apress.springbatch.chapter7.TransactionFieldSetMapper"/>
<beans:bean id="customer" class="com.apress.springbatch.chapter7.Customer"
scope="prototype"/>
Outpur Writer
<beans:bean id="outputFile"
class="org.springframework.core.io.FileSystemResyource" scope="step">
<beans:constructor-arg value="#{jobParameters[outputFile]}"/>
</beans:bean>
<beans:bean id="outputWriter"
class="org.springframework.batch.item.file.FlatFileItemWriter">
<beans:property name="resource" ref="outputFile" />
<beans:property name="lineAggregator">
<beans:bean class="org.springframework.batch.item.file.transform.
PassThroughLineAggregator"/>
</beans:property>
</beans:bean>
输出
Warren Q. Darrow has 1 transactions.
Ann V. Gates has no transactions.
Erica I. Jobs has 5 transactions.
CustomerFieldSetMapper
import org.springframework.batch.item.file.mapping.FieldSetMapper;
import org.springframework.batch.item.file.transform.FieldSet;
import org.springframework.validation.BindException;
public class CustomerFieldSetMapper implements FieldSetMapper<Customer> {
public Customer mapFieldSet(FieldSet fieldSet) throws BindException {
Customer customer = new Customer();
customer.setAddress(fieldSet.readString("addressNumber") +
" " + fieldSet.readString("street"));
customer.setCity(fieldSet.readString("city"));
customer.setFirstName(fieldSet.readString("firstName"));
customer.setLastName(fieldSet.readString("lastName"));
customer.setMiddleInitial(fieldSet.readString("middleInitial"));
customer.setState(fieldSet.readString("state"));
customer.setZip(fieldSet.readString("zip"));
return customer;
}
}
答案 2 :(得分:0)
您可以使用FlatFileItemReader
来读取每一行(您只发布了一列但我猜您在行中有更多信息,因此请使用Tokenizer
分隔每行的值)。比在ItemProcessor
中检查第一个令牌是CUST
还是TRANS
,如果它是写入者的返回值,如果不是,则返回null
,这是过滤项目的弹簧批量机制。
您可以在春季批次here
中找到有关跳过的说明