Springbatch从文件读取数据处理后写入数据库

使用Springboot  + mybatis框架

4.1.1 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>com.mlsama</groupId>

   <artifactId>batchPay</artifactId>

   <version>1.0.0-SNAPSHOT</version>

   <packaging>jar</packaging>



   <name>batchPay</name>

   <description>Demo project for Spring Boot</description>



   <parent>

      <groupId>org.springframework.boot</groupId>

      <artifactId>spring-boot-starter-parent</artifactId>

      <version>2.0.3.RELEASE</version>

      <relativePath/> <!-- lookup parent from repository -->

   </parent>



   <properties>

      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

      <java.version>1.8</java.version>

      <mybatis.version>1.3.2</mybatis.version>

   </properties>



   <build>

      <plugins>

         <plugin>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-maven-plugin</artifactId>

         </plugin>

      </plugins>

   </build>



   <dependencies>

      <dependency>

         <groupId>org.springframework.boot</groupId>

         <artifactId>spring-boot-starter-batch</artifactId>

      </dependency>

      <!--Spring batch与Quartz的整合包-->

      <dependency>

         <groupId>org.springframework</groupId>

         <artifactId>spring-context-support</artifactId>

      </dependency>

      <!--Quartz-->

      <dependency>

         <groupId>org.quartz-scheduler</groupId>

         <artifactId>quartz</artifactId>

         <version>2.3.0</version>

      </dependency>

      <dependency>

         <groupId>org.springframework.boot</groupId>

         <artifactId>spring-boot-starter-web</artifactId>

      </dependency>

      <dependency>

         <groupId>org.springframework.boot</groupId>

         <artifactId>spring-boot-starter-test</artifactId>

         <scope>test</scope>

      </dependency>

      <dependency>

         <groupId>org.springframework.batch</groupId>

         <artifactId>spring-batch-test</artifactId>

         <scope>test</scope>

      </dependency>

      <dependency>

         <groupId>org.springframework.boot</groupId>

         <artifactId>spring-boot-starter-jdbc</artifactId>

      </dependency>

      <!--使用MySQL作为数据库-->

      <dependency>

         <groupId>mysql</groupId>

         <artifactId>mysql-connector-java</artifactId>

         <scope>runtime</scope>

      </dependency>

      <!--lombok约束-->

      <dependency>

         <groupId>org.projectlombok</groupId>

         <artifactId>lombok</artifactId>

      </dependency>

      <!--日记-->

      <dependency>

         <groupId>org.slf4j</groupId>

         <artifactId>log4j-over-slf4j</artifactId>

      </dependency>

      <!--c3p0连接池-->

      <dependency>

         <groupId>com.mchange</groupId>

         <artifactId>c3p0</artifactId>

         <version>0.9.5.2</version>

      </dependency>

      <dependency>

         <groupId>org.apache.commons</groupId>

         <artifactId>commons-lang3</artifactId>

         <version>3.5</version>

      </dependency>

      <dependency>

         <groupId>org.mybatis.spring.boot</groupId>

         <artifactId>mybatis-spring-boot-starter</artifactId>

         <version>${mybatis.version}</version>

      </dependency>

   </dependencies>

</project>

 

4.1.2 application.properties

server.port=8888

#关闭项目启动job自动执行

spring.batch.job.enabled = false

#整合c3p0,要自定义配置类,如:DataSourceConfiguration

spring.datasource.c3p0.driverClass=com.mysql.jdbc.Driver

spring.datasource.c3p0.jdbcUrl=jdbc:mysql://localhost:3306/springbatch

spring.datasource.c3p0.user=root

spring.datasource.c3p0.password=mlsama

spring.datasource.c3p0.maxPoolSize=30

spring.datasource.c3p0.minPoolSize=10

spring.datasource.c3p0.initialPoolSize=10



#mybatis配置

#别名包扫描

mybatis.typeAliasesPackage=com.mlsama.hellospringbatch.pojo

#引入*Mapper.xml文件

mybatis.mapperLocations=classpath:mappers/**/*Mapper.xml

# 引入mybatis主配置文件

mybatis.configLocation=classpath:mybatis-config.xml

4.1.3 整合c3p0,自定义数据源

@Configuration      //声明为配置类

public class DataSourceConfiguration {



    @Bean(name = "dataSource")  //对象及名称

    @Primary        //主要的候选者

    //配置属性,prefix : 前缀 spring.datasource固定

    @ConfigurationProperties(prefix = "spring.datasource.c3p0")

    public DataSource createDataSource(){

        return DataSourceBuilder.create() // 创建数据源构建对象

                .type(ComboPooledDataSource.class) // 设置数据源类型

                .build(); // 构建数据源对象



    }

}

 

4.1.4 mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE configuration

        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"

        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>

    <!-- 全局的设置-->

    <settings>

        <!-- 开启缓存 -->

        <setting name="cacheEnabled" value="true"/>

        <!-- 启用延迟加载功能 -->

        <setting name="lazyLoadingEnabled" value="true"/>

        <!-- 按需要延迟加载-->

        <setting name="aggressiveLazyLoading" value="false"/>

        <!-- 开启驼峰映射 (方便自动映射) -->

        <setting name="mapUnderscoreToCamelCase" value="true"/>

    </settings>

</configuration>

 

4.1.5 job的配置

<?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"

       xsi:schemaLocation="http://www.springframework.org/schema/batch

                            http://www.springframework.org/schema/batch/spring-batch.xsd

                            http://www.springframework.org/schema/beans

                            http://www.springframework.org/schema/beans/spring-beans.xsd">



    <!--<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">

        <property name="driverClass" value="com.mysql.jdbc.Driver"></property>

        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/springbatch"></property>

        <property name="user" value="root"></property>

        <property name="password" value="mlsama"></property>

    </bean>-->



    <!--DataSource在DataSourceConfiguration中定义-->

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

        <property name="dataSource" ref="dataSource"></property>

    </bean>

    <!-- 配置spring batch的jobRepository,负责与数据库打交道 -->

    <bean id="jobRepository" class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean">

        <property name="dataSource" ref="dataSource"></property>

        <property name="transactionManager" ref="transactionManager"></property>

    </bean>

    <!-- 配置spring batch的 jobLauncher,用来启动Job-->

    <bean id="batchJobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">

        <property name="jobRepository" ref="jobRepository"></property>

    </bean>

    <!-- 注册job,把job注入到容器中,在jobLauncher启动job时才能从容器中获取要启动的Job -->

    <bean id="jobRegistry" class="org.springframework.batch.core.configuration.support.MapJobRegistry"/>



    <bean class="org.springframework.batch.core.configuration.support.JobRegistryBeanPostProcessor">

        <property name="jobRegistry" ref="jobRegistry"/>

    </bean>

    <!--“任务浏览器(JObExplorer)”是“任务存储器(JobRepository)”的只读版本,

                像后者一样,它可以通过工厂bean简单的配置生成-->

    <bean id="jobExplorer" class="org.springframework.batch.core.explore.support.JobExplorerFactoryBean">

        <property name="dataSource" ref="dataSource"></property>

    </bean>

    <!--读取数据-->

    <bean id="reader" class="org.springframework.batch.item.file.FlatFileItemReader">

        <property name="resource" value="classpath:/batchFiles/86000041-20181008.csv"></property>

        <property name="lineMapper" ref="lineMapper"></property>

        <property name="linesToSkip" value="1"></property>

    </bean>

    <bean id="lineMapper" class="org.springframework.batch.item.file.mapping.DefaultLineMapper">

        <property name="lineTokenizer" ref="lineTokenizer"></property>

        <property name="fieldSetMapper" ref="fieldSetMapper"></property>

    </bean>

    <bean id="lineTokenizer" class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">

        <property name="names" value="procCode,account,accountName,amount,payType,reserve"></property>

    </bean>

    <bean id="fieldSetMapper" class="com.mlsama.hellospringbatch.reader.BatchPayReader"></bean>

    <!--核心业务处理-->

    <bean id="process" class="com.mlsama.hellospringbatch.processor.BatchPayItemProcessor"></bean>

    <!--持久化处理-->

    <bean id="write" class="com.mlsama.hellospringbatch.writer.BatchPayWriter"></bean>



    <!-- 配置job工作 -->

    <batch:job id="batchPayJob" restartable="true">

        <batch:step id="batchPayJobStep">

            <batch:tasklet transaction-manager="transactionManager">

                <batch:chunk reader="reader"

                             processor="process"

                             writer="write"

                             commit-interval="10">

                </batch:chunk>

            </batch:tasklet>

        </batch:step>

    </batch:job>



</beans>

 

 

4.1.6 数据源(.csv文件)

86000041-20181008.csv

procCode,account,accountName,amount,payType,reserve

86000041,612565688853252536,df,203000,DS,转账

86000041,813565678853252533,ds,240000,DS,转账

86000041,615465688853252531,ed,203000,DS,转账

86000041,614565688853252532,de,200600,DS,转账

86000041,687565688853252534,er,200050,DS,转账


4.1.7 实体类

@Data

public class BatchPay {

    /**

     * 流水号

     */

    private String logSeq;

    /**

     * 支付机构编码

     */

    private String procCode;

    /**

     * 账号

     */

    private String account;

    /**

     * 户名

     */

    private String accountName;

    /**

     * 金额

     */

    private BigDecimal amount;

    /**

     * 支付类型

     */

    private String paySeq;

    /**

     * 支付类型

     */

    private String payType;

    /**

     * 交易日期

     */

    private String tradeDate;

    /**

     * 交易时间

     */

    private String tradeTime;

    /**

     * 交易结果

     */

    private String resultCode;

    /**

     * 交易返回码

     */

    private String respCode;

    /**

     * 交易返回码描述

     */

    private String respMsg;

    /**

     * 自定义域1

     */

    private String reserve;



    public BatchPay(String procCode, String account, String accountName, BigDecimal amount, String payType, String reserve) {

        this.procCode = procCode;

        this.account = account;

        this.accountName = accountName;

        this.amount = amount;

        this.payType = payType;

        this.reserve = reserve;

    }



    @Override

    public String toString() {

        return "BatchPay{" +

                "logSeq='" + logSeq + '\'' +

                ", procCode='" + procCode + '\'' +

                ", account='" + account + '\'' +

                ", accountName='" + accountName + '\'' +

                ", amount=" + amount +

                ", payType='" + payType + '\'' +

                ", paySeq='" + paySeq + '\'' +

                ", tradeDate='" + tradeDate + '\'' +

                ", tradeTime='" + tradeTime + '\'' +

                ", resultCode='" + resultCode + '\'' +

                ", respCode='" + respCode + '\'' +

                ", respMsg='" + respMsg + '\'' +

                ", reserve1='" + reserve + '\'' +

                '}';

    }

}

 

4.1.8 读取数据源

使用FlatFileItemReader类,其实已经在job的配置文件中有了配置:

<!--读取数据-->

<bean id="reader" class="org.springframework.batch.item.file.FlatFileItemReader">

    <!--数据源文件-->

    <property name="resource" value="classpath:/batchFiles/86000041-20181008.csv"></property>

    <!--将一行映射成一个对象-->

    <property name="lineMapper" ref="lineMapper"></property>

    <!--跳过第一行-->

    <property name="linesToSkip" value="1"></property>

</bean>

<!--行映射器-->

<bean id="lineMapper" class="org.springframework.batch.item.file.mapping.DefaultLineMapper">

    <!--设置行字段-->

    <property name="lineTokenizer" ref="lineTokenizer"></property>

    <!--进行行对象映射-->

    <property name="fieldSetMapper" ref="fieldSetMapper"></property>

</bean>

<bean id="lineTokenizer" class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">

    <property name="names" value="procCode,account,accountName,amount,payType,reserve"></property>

</bean>

<bean id="fieldSetMapper" class="com.mlsama.hellospringbatch.reader.BatchPayReader"></bean>

 

将行映射为对象的类需要自定义:

BatchPayReader.java

public class BatchPayReader implements FieldSetMapper<BatchPay>{

    @Override

    public BatchPay mapFieldSet(FieldSet fieldSet) throws BindException {

        return new BatchPay(

                //fieldSet里有每一行的数据,从0开始

                fieldSet.readString(0),

                fieldSet.readString(1),

                fieldSet.readString(2),

                new BigDecimal(fieldSet.readString(3)),

                fieldSet.readString(4),

                fieldSet.readString(5)

        );

    }

}

4.1.9 业务处理

在配置文件中也有了定义

<!--核心业务处理-->

<bean id="process" class="com.mlsama.hellospringbatch.processor.BatchPayItemProcessor"></bean>

 

BatchPayItemProcessor.Java如下:

@Slf4j

public class BatchPayItemProcessor implements ItemProcessor<BatchPay,BatchPay>{

    @Override

    public BatchPay process(BatchPay batchPay) throws Exception {

        String logSeq = CommonUtil.getLogSeq();

        batchPay.setLogSeq(logSeq);

        batchPay.setPaySeq(logSeq);

        batchPay.setTradeDate(new SimpleDateFormat(CommonConstants.DATA_FORMAT).format(new Date()));

        batchPay.setTradeTime(new SimpleDateFormat(CommonConstants.Time_FORMAT).format(new Date()));

        batchPay.setResultCode(CommonConstants.RESULT_CODE_0050);

        return batchPay;

    }

}

 

4.1.10 持久化

在配置文件中的配置如下:

<!--持久化处理-->

<bean id="write" class="com.mlsama.hellospringbatch.writer.BatchPayWriter"></bean>

 

BatchPayWriter.Java如下:

@Slf4j

public class BatchPayWriter implements ItemWriter<BatchPay> {

    @Autowired

    private BatchPayManager batchPayManager;

    @Override

    public void write(List<? extends BatchPay> list) throws Exception {

        log.info("开始持久化数据.list={}",list);

        try {

            batchPayManager.batchPayInsert(list);

        }catch (Exception e){

            log.error("持久化数据异常{}.",e);

        }

    }

}

4.1.11 统一管理层

@Service

public class BatchPayManager {

    @Autowired

    private BatchPayMapper batchPayMapper;



    @Transactional(rollbackFor = Exception.class)

    public void batchPayInsert(List<? extends BatchPay> list){

        batchPayMapper.batchInsert(list);

    }

}

 

4.1.12 mybatis的mapper层

@Mapper

public interface BatchPayMapper {



    void batchInsert(List<? extends BatchPay> list);

}

 

4.1.13 mybatis的mapper配置

在resource下创建文件夹mappers,创建配置文件BatchPayMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE mapper

        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.mlsama.hellospringbatch.mapper.BatchPayMapper">



    <insert id="batchInsert" parameterType="list">

          INSERT INTO t_batch_pay

            (

            log_seq,

            proc_code,

            account,

            account_name,

            amount,

            pay_seq,

            pay_type,

            trade_date,

            trade_time,

            result_code,

            resp_code,

            resp_msg,

            reserver

            )VALUES

            <foreach collection="list" item="item" separator=",">

            (

            #{item.logSeq, jdbcType=VARCHAR},

            #{item.procCode, jdbcType=VARCHAR},

            #{item.account, jdbcType=VARCHAR},

            #{item.accountName, jdbcType=VARCHAR},

            #{item.amount, jdbcType=DECIMAL},

            #{item.paySeq, jdbcType=VARCHAR},

            #{item.payType, jdbcType=VARCHAR},

            #{item.tradeDate, jdbcType=VARCHAR},

            #{item.tradeTime, jdbcType=VARCHAR},

            #{item.resultCode, jdbcType=VARCHAR},

            #{item.respCode, jdbcType=VARCHAR},

            #{item.respMsg, jdbcType=VARCHAR},

            #{item.reserve, jdbcType=VARCHAR}

            )

        </foreach>

    </insert>



</mapper>

 

4.1.14 job调度层

用于启动job,通过配置在job配置文件中的SimpleJobLauncher启动job.

@Service

@Slf4j

public class BatchPayJobLauncher {

    @Resource(name = "batchJobLauncher")

    private SimpleJobLauncher batchJobLauncher;



    @Resource(name = "batchPayJob")

    private Job batchPayJob;



    public String doBatchPayJob(){

        try {

            JobExecution jobExecution = batchJobLauncher.run(batchPayJob,  new RunIdIncrementer().getNext(null));

            return jobExecution.getStatus().name();

        }catch (Exception e){

            log.error("执行job:batchPayJob发生异常{}",e);

        }

        return null;

    }

}

 

4.1.15 控制层

接受页面请求,调用job调度层方法,启动job

@Controller

@RequestMapping("/batchPay")

public class BatchPayController {

    @Autowired

    private BatchPayJobLauncher batchPayJobLauncher;



    @ResponseBody

    @GetMapping("/doBatchPayJob")

    public String doBatchPayJob(){

        String result = batchPayJobLauncher.doBatchPayJob();

        if (StringUtils.isBlank(result)){

            result = "调用失败.发生异常";

        }

        return result;

    }

}

 

4.1.16 项目启动类

@SpringBootApplication  //springboot启动

//@EnableBatchProcessing    //加载所有的job,这里不能有这个,否则不能调度

@ImportResource(locations = "classpath:*-config.xml")

public class Application {

   public static void main(String[] args) {

      /** 创建SpringApplication对象 */

      SpringApplication springApplication =

            new SpringApplication(Application.class);

      /** 设置横幅关闭 */

      springApplication.setBannerMode(Banner.Mode.OFF);

      /** 运行 */

      springApplication.run(args);

   }

}

 

4.1.17 项目结构

运行项目启动类,访问: http://localhost:8888/batchPay/doBatchPayJob

猜你喜欢

转载自blog.csdn.net/mlsama/article/details/83623637
今日推荐