Spring Batch介绍以及以springboot整合

Spring Batch介绍和使用

  • 什么是Spring Batch?
    • 核心名词解释
    • 如何与springboot整合
      • 依赖

什么是Spring Batch?

  • 高效的批处理应用
  • 能够支持简单的、复杂的和大数据量的批处理作业
  • 提供了大量可重用的组件,包括了日志、追踪、事务、任务作业统计、任务重启、跳过、重复、资源管理
  • 提供了高级功能和特性来支持,比如分区功能、远程功能

核心名词解释

  • Spring Batch运行的基本单位是一个Job,一个Job就做一件批处理的事情。
    一个Job包含很多Step,step就是每个job要执行的单个步骤
  • Step里面,会有Tasklet,Tasklet是一个任务单元,它是属于可以重复利用的东西。然后是Chunk,chunk就是数据块,你需要定义多大的数据量是一个chunk,Chunk里面就是不断循环的一个流程,读数据,处理数据,然后写数据。Spring Batch会不断的循环这个流程,直到批处理数据完成.
  • Spring batch在配置Step时采用的是基于Chunk的机制,即每次读取一条数据,再处理一条数据,累积到一定数量后再一次性交给writer进行写入操作。这样可以最大化的优化写入效率,整个事务也是基于Chunk来进行

比如我们定义chunk size是50,那就意味着,spring batch处理了50条数据后,再统一向数据库写入。
这里有个很重要的点,chunk前面需要定义数据输入类型和输出类型,由于我们输入是Message,输出也是Message,所以两个都直接写Message了。
如果不定义这个类型,会报错。.chunk(CHUNK_SIZE)

  • Reader顾名思义就是从数据源读取数据。
    Spring Batch给我们提供了很多好用实用的reader,基本能满足我们所有需求。比如FlatFileItemReader,JdbcCursorItemReader,JpaPagingItemReader等。也可以自己实现Reader

Spring Batch介绍以及以springboot整合_第1张图片
-jobRepository:定义Job时,需要指定一个JobRepository,用来存储Job在运行过程中的状态信息,对于存储状态信息的原因为:如果Job运行失败了,Spring支持从失败的地方重新运行,而不是从头开始;

  • JobLauncher:很好理解launchuer是用来执行Job的,如果不设置,系统也会默认给Job配置默认的Launcher;
    Spring Batch介绍以及以springboot整合_第2张图片

如何与springboot整合

依赖

		
		org.springframework.boot
		spring-boot-starter-parent
		2.0.2.RELEASE
		 
	
	注意以下依赖
	
			org.springframework.boot
			spring-boot-starter-batch
		
			
			mysql
			mysql-connector-java
		
```	
			org.springframework.boot
			spring-boot-starter-data-jpa
		

 - 配置文件需要配置

>  spring.datasource.url=jdbc:mysql://localhost:3306/springbatch?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&useSSL=false
spring.datasource.username=root
spring.datasource.password=qitao1996
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
>  spring.batch.job.names = job1,job2 #启动时要执行的Job,默认执行全部Job
spring.batch.job.enabled=true #是否自动执行定义的Job,默认是
spring.batch.initializer.enabled=true #是否初始化Spring Batch的数据库,默认为是
spring.batch.table-prefix=batch_  #设置SpringBatch的数据库表的前缀
#JPA
spring.jpa.properties.hibernate.hbm2ddl.auto = update
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
spring.jpa.database = MYSQL
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.show-sql = true
 - 开启batch,@EnableBatchProcessing是打开Batch。如果要实现多Job的情况,需要把EnableBatchProcessing注解的modular设置为true,让每个Job使用自己的ApplicationConext。 

  • 构建Job,
  • 以上配置完后,spring会自动为我们注入以下对象
    @Autowired
    public JobBuilderFactory jobBuilderFactory;

    @Autowired
    public StepBuilderFactory stepBuilderFactory;
    //主要负责从JobRepository中获取执行的信息,包括获取作业实例、获取作业执行器、获取作恶步执行器、获取正在运行的作业执行器、获取作业列表等操作;
    @Autowired
    public JobExplorer jobExplorer;

    @Autowired
    public JobRepository jobRepository;

    @Autowired
    ApplicationContext applicationContext;

    @Autowired
    JobLauncher jobLauncher;

    @Autowired
    EntityManagerFactory entityManagerFactory;


@Bean
public Step messageMigrationStep(@Qualifier("jsonMessageReader") FlatFileItemReader jsonMessageReader,
                                 @Qualifier("messageItemWriter") JpaItemWriter messageItemWriter,
                                 @Qualifier("errorWriter") Writer errorWriter) {
    return stepBuilderFactory.get("messageMigrationStep")
            .chunk(CHUNK_SIZE)
            .reader(jsonMessageReader).faultTolerant().skip(JsonParseException.class).skipLimit(SKIP_LIMIT)
            .listener(new MessageItemReadListener(errorWriter))
            .writer(messageItemWriter).faultTolerant().skip(Exception.class).skipLimit(SKIP_LIMIT)
            .listener(new MessageWriteListener())
            .build();
}
#我们的Step中可以构建很多东西,比如reader,processer,writer,listener等等。

解释以上代码

  • chunk前面需要定义数据输入类型和输出类型
  • FlatFileItemReader是从文件里面一行一行的读取数据,首先需要设置文件路径,也就是设置resource
  • 需要把一行文本映射为Message类,所以我们需要自己设置并实现LineMapper

@Bean
public FlatFileItemReader jsonMessageReader() {
FlatFileItemReader reader = new FlatFileItemReader<>();
reader.setResource(new FileSystemResource(new File(MESSAGE_FILE)));
reader.setLineMapper(new MessageLineMapper());
return reader;
}

  • LineMapper的输入就是获取一行文本,和行号,然后转换成Message。
    在本例子里面,一行文本就是一个json对象,所以我们使用JsonParser来转换成Message。
public class MessageLineMapper implements LineMapper {
    private MappingJsonFactory factory = new MappingJsonFactory();

    @Override
    public Message mapLine(String line, int lineNumber) throws Exception {   
        JsonParser parser = factory.createParser(line);
        Map map = (Map) parser.readValueAs(Map.class);
        Message message = new Message();
        ... // 转换逻辑
        return message;
    }
}
  • 这里给出一个列子,Processor就是对读出的数据再进行处理
@Service
public class MyProcessorItem implements ItemProcessor {

    Logger logger = LoggerFactory.getLogger(MyProcessorItem.class);

    @Override
    public Article process(Article article)throws Exception{
       logger.info("【{}】经过处理器",article.getTitle());
        return article;
    }
}
  • Spring Batch同样给我们提供很多好用实用的writer。比如JpaItemWriter,FlatFileItemWriter,HibernateItemWriter,JdbcBatchItemWriter等。同样也可以自定义。
@Autowired
private EntityManagerFactory entityManager;

@Bean
public JpaItemWriter messageItemWriter() {
    JpaItemWriter writer = new JpaItemWriter<>();
    writer.setEntityManagerFactory(entityManager);
    return writer;
}
  • Spring Batch同样实现了非常完善全面的listener,listener很好理解,就是用来监听每个步骤的结果。比如可以有监听step的,有监听job的,有监听reader的,有监听writer的。没有你找不到的listener,只有你想不到的listener。
public class MessageItemReadListener implements ItemReadListener {
    private Writer errorWriter;

    public MessageItemReadListener(Writer errorWriter) {
        this.errorWriter = errorWriter;
    }

    @Override
    public void beforeRead() {
    }

    @Override
    public void afterRead(Message item) {
    }

    @Override
    public void onReadError(Exception ex) {
         errorWriter.write(format("%s%n", ex.getMessage()));
    }
}
  • Spring Batch提供了skip的机制,也就是说,如果出错了,可以跳过。如果你不设置skip,那么一条数据出错了,整个job都会挂掉。
    设置skip的时候一定要设置什么Exception才需要跳过,并且跳过多少条数据。如果失败的数据超过你设置的skip limit,那么job就会失败。
writer(messageItemWriter).faultTolerant().skip(Exception.class).skipLimit(SKIP_LIMIT)
  • Retry这个和Skip是一样的原理,就是失败之后可以重试,你同样需要设置重试的次数。同样可以分别给reader,writer等设置retry机制。
    如果同时设置了retry和skip,会先重试所有次数,然后再开始skip。比如retry是10次,skip是20,会先重试10次之后,再开始算第一次skip。
  • 运行Job
  • 运行就是JobLauncher去运行你制定的job。
  • 首先我们通过运行起来的Spring application得到jobRegistry,然后通过job的名字找到对应的job。接着,我们就可以用jobLauncher去运行这个job了,运行的时候会传一些参数,比如你job里面需要的文件路径或者文件日期等,就可以通过这个jobParameters传进去。如果没有参数,可以默认传当前时间进去。
JobRegistry jobRegistry = context.getBean(JobRegistry.class);
        Job job = jobRegistry.getJob(jobName);
        JobLauncher jobLauncher = context.getBean(JobLauncher.class);
        JobExecution jobExecution = jobLauncher.run(job, createJobParams());
  • 数据库查看会自动生成相关表
    Spring Batch介绍以及以springboot整合_第3张图片
    参考:参考1

你可能感兴趣的:(Spring)