Spring Batch批处理框架

Spring Batch批处理框架

批处理广泛应用于大数据场景

1、为什么需要批处理

大数据场景下,数据源的数据量一般比较大,不可能一次性将数据源数据拉到内存中,一方面硬件内存不支持,另一方面等待时间过长,在这样的背景下,批处理被提出。

2、批处理的特点

  • 批处理按照一组一组的方式从数据源拉取数据到内存中,处理完成后,批量写入目标数据源。

  • 由于是一组一组的(取数据 -> 处理数据 -> 写数据),即便是物理机内存不是很大,也能够处理大数据场景需求。

  • 一般而言,大数据处理执行时间普遍比较长,中途可能会发生各种意外,那么记录运行元数据尤为必要。当发生意外时,能够从意外处继续重启执行,避免陷入从头再来的尴尬处境。

3、操作

  1. 导入依赖

    <!--批处理-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-batch</artifactId>
    </dependency>
    
  2. 在application.yml编写配置

    # 编写批处理的配置
    spring:
      datasource:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql:///batch?useUnicode=true&characterEncoding=utf-8
        username: root
        password: 123456
      batch:
        # 在项目启动时执行建表sql
        job:
          # 禁止Spring Batch自动执行,既需要用户触发才能执行
          enabled: false
          names: parentjob
        jdbc:
          # spring batch相关表的前缀,默认为batch_
          table-prefix: batch_
          initialize-schema: always
      sql:
        init:
          schema-locations: classpath:/org/springframework/batch/core/schema-mysql.sql
    
    
  3. 编写配置类

    @Configuration
    @EnableBatchProcessing
    public class BatchConfig {
    
        /**
         * 用来读取数据
         */
        @Bean
        public ItemReader<BuUser> reader() {
            // FlatFileItemReader是一个用来加载文件的itemReader
            FlatFileItemReader<BuUser> reader = new FlatFileItemReader<>();
            // 跳过第一行的标题
            reader.setLinesToSkip(1);
            //设置csv的位置
            reader.setResource(new ClassPathResource("data.csv"));
            // 设置每一行的数据信息
            reader.setLineMapper(new DefaultLineMapper<BuUser>() {{
                setLineTokenizer(new DelimitedLineTokenizer() {{
                    // 配置字段
                    setNames("userName", "sex", "age", "address");
                    // 配置列与列之间的间隔符,会通过间隔符对每一行进行切分
                    setDelimiter(",");
                }});
                // 设置要映射的实体类属性
                setFieldSetMapper(new BeanWrapperFieldSetMapper<BuUser>() {{
                    setTargetType(BuUser.class);
                }});
            }});
            return reader;
        }
    
        /**
         * 用来输出数据
         */
    
        @Bean
        public ItemWriter<BuUser> writer(DataSource dataSource) {
            // 通过JDBC写入数据库中
            JdbcBatchItemWriter<BuUser> writer = new JdbcBatchItemWriter<>();
            writer.setDataSource(dataSource);
            // setItemSqlParameterSourceProvider表示将实体类中的属性和占位符一一映射
            writer.setItemSqlParameterSourceProvider(
                    new BeanPropertyItemSqlParameterSourceProvider<>()
            );
            // 设置要执行批处理的SQL语句,其中占位符的写法时 `:属性名`
            writer.setSql("insert into sys_user(user_name, sex, age, address)" + "values(:userName, :sex, :age, :address)");
            return writer;
        }
    
        /**
         * 配置一个step
         */
        @Bean
        public Step csvStep(
                StepBuilderFactory stepBuilderFactory,
                ItemReader<BuUser> reader,
                ItemWriter<BuUser> writer) {
            return stepBuilderFactory.get("cvsStep")
                    // 批处理每次提交10条数据,就是每请求一次,提交一次
                    .<BuUser, BuUser>chunk(10)
                    // 给step绑定 reader
                    .reader(reader)
                    // 给step绑定 writer
                    .writer(writer)
                    .faultTolerant()
                    // 设定一个我们允许的这个step跳过的异常的数量,加入我们设定为3,则当这个step运行时,只要出现的异常数目不超过3
                    .skipLimit(3)
                    // 指定我们可以跳过的异常,因为有些异常的出现,我们是可以忽略的
                    .skip(Exception.class)
                    // 出现这个异常我们不想跳过,因此这种异常出现一次时,计数器就会加一,直到达到上限
                    .noSkip(FileNotFoundException.class)
                    .build();
        }
    
        /**
         * 配置一个要执行的Job任务,包含一个或多个Step
         */
        @Bean
        public Job cvsJob(JobBuilderFactory jobBuilderFactory,Step step) {
            // 为job起名为cvsJob
            return jobBuilderFactory.get("cvsJob").start(step).build();
        }
    
    }
    
  4. 数据实体类

    @Data
    public class BuUser {
        private String userName;
        private String sex;
        private String age;
        private String address;
    }
    
  5. 编写控制器

    @RestController
    public class JobController {
        @Autowired
        private JobLauncher jobLauncher;
        @Autowired
        private Job job;
    
        @GetMapping("/doJob")
        public void doJob(){
            try {
                // 同一个job执行多次,由于job定义一样,则无法区分jobInstance,所以增加jobParameter用于区分
                JobParametersBuilder jobParametersBuilder = new JobParametersBuilder();
                jobParametersBuilder.addDate("jobDate", new Date());
    
                // 执行一个批处理任务
                jobLauncher.run(job, jobParametersBuilder.toJobParameters());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

注意:上方写的<BuUser, BuUser>chunk(10)这个每请求一次写入10行数据,需要手动请求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值