【Spring Batch学习笔记】2:Reader-Processor-Writer操作csv文件的例子

参考:1,2

程序结构

这里写图片描述

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.lzh</groupId>
    <artifactId>testSpringBatch</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework.batch/spring-batch-core -->
        <dependency>
            <groupId>org.springframework.batch</groupId>
            <artifactId>spring-batch-core</artifactId>
            <version>3.0.7.RELEASE</version>
        </dependency>
    </dependencies>

</project>

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--jobLauncher负责batch的启动工作-->
    <bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
        <!--注入jobRepository-->
        <property name="jobRepository" ref="jobRepository"/>
    </bean>
    <!--jobRepository负责job的整个运行过程中的CRUD操作-->
    <bean id="jobRepository" class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean"/>
    <!--transactionManager负责事务的管理操作-->
    <bean id="transactionManager" class="org.springframework.batch.support.transaction.ResourcelessTransactionManager"/>
</beans>

batch.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:batch="http://www.springframework.org/schema/batch"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/batch
        http://www.springframework.org/schema/batch/spring-batch.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!--导入前面的Spring配置文件-->
    <import resource="applicationContext.xml"/>

    <!--===================================================================================================-->

    <batch:job id="csvJob">
        <!--仅有这一个作业步-->
        <batch:step id="csvstep">
            <!--这个tasklet不直接指定ref,在其内部配置chunk来作为其实现内容-->
            <batch:tasklet transaction-manager="transactionManager">
                <!--chunk,ChunkOrientedTasklet类实现类"块处理(chunk processing)"-->
                <!--[reader,processor,writer属性]分别是对三种处理bean的ref,它们必须是特定接口的实现类及其子类对象-->
                <!--[commit-interval属性]是事务提交一次处理的items的数量,即是chunk的大小-->
                <batch:chunk reader="csvItemReader" processor="csvItemProcessor" writer="csvItemWriter"
                             commit-interval="1"/>
            </batch:tasklet>
        </batch:step>
    </batch:job>

    <!--===================================================================================================-->

    <!--Reader的bean,使用Spring Batch自带的一个实现类-->
    <bean id="csvItemReader" class="org.springframework.batch.item.file.FlatFileItemReader" scope="step">
        <!--该类的[resource成员]注入要读取的文件位置-->
        <property name="resource" value="classpath:inputFile.csv"/>
        <!--该类的[lineMapper成员]是行处理器,用对文件的每行具体处理-->
        <property name="lineMapper">
            <!--这里使用Spring Batch自带的DefaultLineMapper来作为行处理器-->
            <bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
                <!--lineTokenizer是一个属性标记器,定义了对象转换的结构,表征了每行记录如何分割成对象的属性-->
                <property name="lineTokenizer" ref="lineTokenizer"/>
                <!--fieldSetMapper定义了转换结果映射,即具体映射到哪个Java类对象-->
                <property name="fieldSetMapper" ref="fieldSetMapper"/>
            </bean>
        </property>
    </bean>

    <!--行处理器=>属性标记器;使用Spring Batch自带的DelimitedLineTokenizer(可以切割行字符串形成一个个属性)-->
    <bean id="lineTokenizer" class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
        <!--按","符号对行进行切割-->
        <property name="delimiter" value=","/>
        <!--属性名称列表,将切割后的行按顺序投入-->
        <property name="names">
            <list>
                <value>id</value>
                <value>name</value>
                <value>age</value>
                <value>score</value>
            </list>
        </property>
    </bean>

    <!--行处理器=>结果集映射;使用Spring Batch自带的BeanWrapperFieldSetMapper-->
    <bean id="fieldSetMapper" class="org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper">
        <!--注入行处理的结果集是哪个Java类的bean[[为什么这里用value而不是ref?]]-->
        <property name="prototypeBeanName" value="student"/>
    </bean>

    <!--行转换结果的实体类-->
    <bean id="student" class="org.lzh.Student"/>

    <!--===================================================================================================-->

    <!--csvItemProcessor用注解的方式加入Spring容器管理,见CsvItemProcessor类-->
    <!--这里扫描它所在的包,该类已经打上了@Component注解,将被扫描并注册为指定id的bean-->
    <context:component-scan base-package="org.lzh"/>

    <!--===================================================================================================-->

    <!--Writer的bean,使用Spring Batch自带的一个实现类-->
    <bean id="csvItemWriter" class="org.springframework.batch.item.file.FlatFileItemWriter">
        <!--要写入的文件位置,因为[classpath:]不是一个具体的目录,这里应当用[file:](从项目根目录开始)指明输出位置-->
        <property name="resource" value="file:src/main/resources/outputFile.csv"/>
        <!--[lineAggregator成员]指明行聚合器,用来将对象输出到文件时构造文件中的每行的格式-->
        <property name="lineAggregator">
            <!--这里使用Spring Batch自带的DelimitedLineAggregator来作为行聚合器(可以拼接一个个属性形成行)-->
            <bean class="org.springframework.batch.item.file.transform.DelimitedLineAggregator">
                <!--使用","拼接-->
                <property name="delimiter" value=","/>
                <!--fieldExtractor成员用来将Java类的属性组成的数组拼接成行字符串-->
                <property name="fieldExtractor">
                    <bean class="org.springframework.batch.item.file.transform.BeanWrapperFieldExtractor">
                        <!--这里不妨只输出后三个属性,不输出id-->
                        <property name="names" value="name,age,score"/>
                    </bean>
                </property>
            </bean>
        </property>
    </bean>

</beans>

CsvItemProcessor类

package org.lzh;

//注意不是这个ItemProcessor
//import javax.batch.api.chunk.ItemProcessor;

import org.springframework.batch.item.ItemProcessor;
import org.springframework.stereotype.Component;

//自定义的处理类,需要实现ItemProcessor泛型接口,并实现其process方法
@Component("csvItemProcessor")
public class CsvItemProcessor implements ItemProcessor<Student,Student> {

    //对Reader获取的数据进行处理,传入的是Reader以后的Java对象,返回的是处理之后的Java对象,在这里都是Student对象
    public Student process(Student student) throws Exception {
        //对Reader读取来的POJO对象做一些简单处理
        student.setName("SB"+student.getName());
        student.setAge(20);
        student.setScore(student.getScore()+20);
        //处理后的结果将传递给Writer
        return student;
    }
}

Student类

package org.lzh;

public class Student {
    private int id;
    private String name;
    private int age;
    private double score;

    //getter和setter
}

Main类

package org.lzh;

import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersInvalidException;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
import org.springframework.batch.core.repository.JobRestartException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

    public static void main(String[] args) {
        //batch.xml导入了applicationConext.xml,所以只写batch.xml就可以一并加入上下文
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("batch.xml");
        //Spring Batch的作业启动器,在applicationContext.xml中配置为了bean
        JobLauncher jobLauncher = (JobLauncher) applicationContext.getBean("jobLauncher");
        //在batch.xml中配置的一个作业
        Job job = (Job) applicationContext.getBean("csvJob");


        try {
            //开始执行这个作业,获得处理结果(要运行的job,job参数对象)
            JobExecution result = jobLauncher.run(job, new JobParameters());
            //输出处理结果看一下
            System.out.println("处理结果:" + result.toString());
        } catch (JobExecutionAlreadyRunningException e) {
            e.printStackTrace();
        } catch (JobRestartException e) {
            e.printStackTrace();
        } catch (JobInstanceAlreadyCompleteException e) {
            e.printStackTrace();
        } catch (JobParametersInvalidException e) {
            e.printStackTrace();
        }

    }
}

inputFile.csv

1,刘知昊,21,40
2,lzh,10,33

运行结果

这里写图片描述
这里写图片描述

猜你喜欢

转载自blog.csdn.net/shu15121856/article/details/81328811
今日推荐