如何在spring批处理中读取ini文件(key = value) [英] How to read ini file in spring batch (key=value)

查看:378
本文介绍了如何在spring批处理中读取ini文件(key = value)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个使用Spring批处理从一个ini文件读取批处理,并保存在数据库中的数据,但当我chekced org.springframework.batch.item.file.FlatFileItemReader 类我没有找到一种方法来解析我的数据从ini文件,我试图将 ini4j API与spring批处理,但没有结果



我的ini文件:

  [Cat] 
a = 1
b = 2
c = 3
d = 4
e = 5
f = 6
[Cat2]
a = 11
b = 21
c = 31
d = 41
e = 51
f = 61


解决方案

你可以做的是定义你自己的 ItemStreamReader 来包装一个委托 ItemStreamReader ,它只是一个使用 PatternMatchingCompositeLineMapper 作为线映射器的 FlatFileItemReader 。在你的 ItemStreamReader 中,循环读取委托中的行,如果行是 Property 域对象的实例,将它添加到 Section 域对象的列表中。 PatternMatchingCompositeLineMapper 允许你做的是检查模式匹配的行,并把它传递给正确的标记器和fieldSetMapper作业。



通过这种方式,可以将多行读入一个 Section 域对象,该对象包含 List< Property> / code>。

  public class Section {

private String name;
私人列表<属性>性能;
// getters和setters
$ b $ @覆盖
public String toString(){
StringBuilder sb = new StringBuilder(name);
for(Property prop:properties){
sb.append(,+ prop.getKey()+=+ prop.getValue());
}
return sb.toString();


$ b $ public class Property {

private String key;
私有字符串值;
// getters and setters
}

为您定制 ItemStreamReader 你可以这样做。你可以看到,阅读是委托给另一个读者,你将在稍后定义

  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.NonTransientResourceException;
import org.springframework.batch.item.ParseException;
import org.springframework.batch.item.UnexpectedInputException;

public class IniFileItemReader实现了ItemStreamReader< Object> {

private Object curItem = null;
private ItemStreamReader< Object>代表;
$ b $ @Override
public Object read()throws Exception,UnexpectedInputException,
ParseException,NonTransientResourceException {$ b $ if(curItem == null){
curItem = (Section)delegate.read();
}

Section section =(Section)curItem;
curItem = null;

if(section!= null){
section.setProperties(new ArrayList< Property>()); $($)
$ b while(peek()instanceof Property){
section.getProperties()。add((Property)curItem);
curItem = null;
}
}
return section;

$ b $ private Object peek()throws Exception {
if(curItem == null){
curItem = delegate.read();
}
return curItem;


public void setDelegate(ItemStreamReader< Object> delegate){
this.delegate = delegate;
}

@Override
public void close()throws ItemStreamException {
delegate.close();
}

@Override
public void open(ExecutionContext arg0)throws ItemStreamException {
delegate.open(arg0);

$ b @Override
public void update(ExecutionContext arg0)throws ItemStreamException {
delegate.update(arg0);






$ b然后在你的配置中定义了带有 PatternMatchingCompositeLineMapper

 < bean id =inputFileclass =org .springframework.core.io.FileSystemResource
scope =step>
< constructor-arg value =#{jobParameters [inputFile]}>< / constructor-arg>
< / bean>

< bean id =sectionFileReader
class =com.underdogdevs.springbatch.reader.IniFileItemReader>
< property name =delegateref =trueSectionFileReader>< / property>
< / bean>
< bean id =trueSectionFileReader
class =org.springframework.batch.item.file.FlatFileItemReader>
< property name =lineMapper>
< bean
class =org.springframework.batch.item.file.mapping.PatternMatchingCompositeLineMapper>
< property name =tokenizers>
< map>
< entry key =[*value-ref =sectionLineTokenizer>
< / entry>
< entry key =*value-ref =propertyLineTokenizer>< / entry>
< / map>
< / property>
< property name =fieldSetMappers>
< map>
< entry key =[*value-ref =sectionFieldSetMapper>
< / entry>
< entry key =*value-ref =propertyFieldSetMapper>
< / entry>
< / map>
< / property>
< / bean>
< / property>
< property name =resourceref =inputFile>< / property>
< / bean>

< bean id =sectionLineTokenizer
class =com.underdogdevs.springbatch.tokenizer.SectionLineTokenizer>
< / bean>

< bean id =sectionFieldSetMapper
class =org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper>
< property name =prototypeBeanNamevalue =section>< / property>
< / bean>

< bean id =sectionclass =com.underdogdevs.springbatch.domain.Section$ b $ scope =prototype>
< / bean>

< bean id =propertyLineTokenizer
class =org.springframework.batch.item.file.transform.DelimitedLineTokenizer>
< property name =delimitervalue ==>< / property>
< property name =namesvalue =key,value>< / property>
< / bean>

< bean id =propertyFieldSetMapper
class =org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper>
< property name =prototypeBeanNamevalue =property>< / property>
< / bean>

< bean id =propertyclass =com.underdogdevs.springbatch.domain.Property$ b $ scope =prototype>
< / bean>

您看到我也使用了自定义 LineTozenizer 。我可能可以使用一个 DelimitedLineTokenizer ,但是当我意识到它的时候,我已经定义了类

  import org.springframework.batch.item.file.transform.DefaultFieldSetFactory; 
import org.springframework.batch.item.file.transform.FieldSet;
import org.springframework.batch.item.file.transform.FieldSetFactory;
import org.springframework.batch.item.file.transform.LineTokenizer;

public class SectionLineTokenizer实现LineTokenizer {

private final String nameField =name;
private final FieldSetFactory fieldSetFactory = new DefaultFieldSetFactory();
$ b $ @Override
public FieldSet tokenize(String line){
String name = line.replaceAll(\\[,).replaceAll(\ \],).trim();

return fieldSetFactory.create(new String [] {name},
new String [] {nameField});




$ b $ p $使用下面的作者和作业

 < bean id =outputFile
class =org.springframework.core.io.FileSystemResourcescope =step> ;
< constructor-arg value =#{jobParameters [outputFile]}>< / constructor-arg>
< / bean>

< bean id =outputFileWriter
class =org.springframework.batch.item.file.FlatFileItemWriter>
< property name =resourceref =outputFile>< / property>
< property name =lineAggregator>
< bean
class =org.springframework.batch.item.file.transform.PassThroughLineAggregator>
< / bean>
< / property>
< / bean>

< batch:step id =outputStep>
< batch:tasklet>
< batch:chunk commit-interval =10reader =sectionFileReader
writer =outputFileWriter>
< batch:streams>
< batch:stream ref =sectionFileReader/>
< batch:stream ref =trueSectionFileReader/>
< / batch:streams>
< / batch:chunk>
< / batch:tasklet>

< batch:job id =iniJob>
< / batch:job>

并使用这个ini文件

  [Cat] 
a = 1
b = 2
c = 3
d = 4
e = 5
f = 6
[Cat2]
a = 11
b = 21
c = 31
d = 41
e = 51
f = 61

我得到下面的输出,这是我的 toString() code> Section class

  Cat,a = 1,b = 2,c = 3,d = 4,e = 5,f = 6 
Cat2,a = 11,b = 21,c = 31,d = 41,e = 51,f = 61


I want to create a batch using Spring batch to read from an ini file and save the data in database but when I chekced the org.springframework.batch.item.file.FlatFileItemReader class I didn't find a way to parse my data from the ini file , I tried to combine the ini4j API with the spring batch but no result

my ini file :

 [Cat]
    a=1
    b= 2
    c= 3
    d= 4
    e= 5
    f= 6
    [Cat2]
     a=11
    b= 21
    c= 31
    d= 41
    e= 51
    f= 61

解决方案

What you can do is define your own ItemStreamReader that wraps a delegate ItemStreamReader, which is just a FlatFileItemReader that uses a PatternMatchingCompositeLineMapper as the line mapper. In your ItemStreamReader, loop to read lines from your delegate and if the line is an instance of a Property domain object then add it to a list in a Section domain object. What the PatternMatchingCompositeLineMapper allows you do do is check the line for a pattern match, and pass it to the right tokenizer and fieldSetMapper for the job.

Doing it this way will allow you to read multiple lines into one Section domain object that holds a List<Property>.

public class Section {

    private String name;
    private List<Property> properties;
    // getters and setters

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder(name);
        for (Property prop: properties) {
            sb.append("," + prop.getKey() + "=" + prop.getValue());
        }
        return sb.toString();
    }
}

public class Property {

    private String key;
    private String value;
    // getters and setters
}

For you custom ItemStreamReader you would do this. You can see that the reading is delegated to another reader, which you will define later

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.NonTransientResourceException;
import org.springframework.batch.item.ParseException;
import org.springframework.batch.item.UnexpectedInputException;

public class IniFileItemReader implements ItemStreamReader<Object> {

    private Object curItem = null;
    private ItemStreamReader<Object> delegate;

    @Override
    public Object read() throws Exception, UnexpectedInputException,
            ParseException, NonTransientResourceException {
        if (curItem == null) {
            curItem = (Section) delegate.read();
        }

        Section section = (Section) curItem;
        curItem = null;

        if (section != null) {
            section.setProperties(new ArrayList<Property>());

            while (peek() instanceof Property) {
                section.getProperties().add((Property) curItem);
                curItem = null;
            }
        }
        return section;
    }

    private Object peek() throws Exception {
        if (curItem == null) {
            curItem = delegate.read();
        }
        return curItem;
    }

    public void setDelegate(ItemStreamReader<Object> delegate) {
        this.delegate = delegate;
    }

    @Override
    public void close() throws ItemStreamException {
        delegate.close();
    }

    @Override
    public void open(ExecutionContext arg0) throws ItemStreamException {
        delegate.open(arg0);
    }

    @Override
    public void update(ExecutionContext arg0) throws ItemStreamException {
        delegate.update(arg0);
    }
}

Then in your config you define the deleagte reader with the PatternMatchingCompositeLineMapper

<bean id="inputFile" class="org.springframework.core.io.FileSystemResource"
    scope="step">
    <constructor-arg value="#{jobParameters[inputFile]}"></constructor-arg>
</bean>

<bean id="sectionFileReader"
    class="com.underdogdevs.springbatch.reader.IniFileItemReader">
    <property name="delegate" ref="trueSectionFileReader"></property>
</bean>
<bean id="trueSectionFileReader"
    class="org.springframework.batch.item.file.FlatFileItemReader">
    <property name="lineMapper">
        <bean
            class="org.springframework.batch.item.file.mapping.PatternMatchingCompositeLineMapper">
            <property name="tokenizers">
                <map>
                    <entry key="[*" value-ref="sectionLineTokenizer">
                    </entry>
                    <entry key="*" value-ref="propertyLineTokenizer"></entry>
                </map>
            </property>
            <property name="fieldSetMappers">
                <map>
                    <entry key="[*" value-ref="sectionFieldSetMapper">
                    </entry>
                    <entry key="*" value-ref="propertyFieldSetMapper">
                    </entry>
                </map>
            </property>
        </bean>
    </property>
    <property name="resource" ref="inputFile"></property>
</bean>

<bean id="sectionLineTokenizer"
    class="com.underdogdevs.springbatch.tokenizer.SectionLineTokenizer">
</bean>

<bean id="sectionFieldSetMapper"
    class="org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper">
    <property name="prototypeBeanName" value="section"></property>
</bean>

<bean id="section" class="com.underdogdevs.springbatch.domain.Section"
    scope="prototype">
</bean>

<bean id="propertyLineTokenizer"
    class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
    <property name="delimiter" value="="></property>
    <property name="names" value="key,value"></property>
</bean>

<bean id="propertyFieldSetMapper"
    class="org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper">
    <property name="prototypeBeanName" value="property"></property>
</bean>

<bean id="property" class="com.underdogdevs.springbatch.domain.Property"
    scope="prototype">
</bean>

You see that I also used a custom LineTozenizer. I probably could've just used a DelimitedLineTokenizer, but by the time I realized it, I had already defined the class

import org.springframework.batch.item.file.transform.DefaultFieldSetFactory;
import org.springframework.batch.item.file.transform.FieldSet;
import org.springframework.batch.item.file.transform.FieldSetFactory;
import org.springframework.batch.item.file.transform.LineTokenizer;

public class SectionLineTokenizer implements LineTokenizer {

    private final String nameField = "name";
    private final FieldSetFactory fieldSetFactory = new DefaultFieldSetFactory();

    @Override
    public FieldSet tokenize(String line) {
        String name = line.replaceAll("\\[", "").replaceAll("\\]", "").trim();

        return fieldSetFactory.create(new String[] { name },
                new String[] { nameField });
    }
}

Using the following writer and job

<bean id="outputFile"
    class="org.springframework.core.io.FileSystemResource" scope="step">
    <constructor-arg value="#{jobParameters[outputFile]}"></constructor-arg>
</bean>

<bean id="outputFileWriter"
    class="org.springframework.batch.item.file.FlatFileItemWriter">
    <property name="resource" ref="outputFile"></property>
    <property name="lineAggregator">
        <bean
            class="org.springframework.batch.item.file.transform.PassThroughLineAggregator">
        </bean>
    </property>
</bean>

<batch:step id="outputStep">
    <batch:tasklet>
        <batch:chunk commit-interval="10" reader="sectionFileReader"
            writer="outputFileWriter">
        <batch:streams>
            <batch:stream ref="sectionFileReader" />
            <batch:stream ref="trueSectionFileReader" />
        </batch:streams>
        </batch:chunk>
    </batch:tasklet>
</batch:step>

<batch:job id="iniJob">
    <batch:step id="step1" parent="outputStep"></batch:step>
</batch:job>

And using this ini file

[Cat]
a=1
b=2
c=3
d=4
e=5
f=6
[Cat2]
a=11
b=21
c=31
d=41
e=51
f=61

I get the following output, which is the format in my toString() of the Section class

Cat,a=1,b=2,c=3,d=4,e=5,f=6
Cat2,a=11,b=21,c=31,d=41,e=51,f=61

这篇关于如何在spring批处理中读取ini文件(key = value)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆