手把手教你搭建第一个Spring Batch项目

写在前面:

我是「沸羊羊_」,昵称来自于姓名的缩写 fyy ,之前呕心沥血经营的博客因手残意外注销,现经营此账号。
本人是个小菜,正向着全栈工程师的方向努力着,文章可能并不高产,也很基础,但每写一篇都在用心总结,请大佬勿喷。
如果您对编程有兴趣,请关注我的动态,一起学习研究。
感谢每位读者!

一、概述

Spring Batch是一个轻量级,全面的批处理框架。

一个典型的批处理过程可能是:

  • 从数据库,文件或队列中读取大量记录。
  • 以某种方式处理数据。
  • 以修改之后的形式写回数据

Spring Batch 应用架构图:

在这里插入图片描述
一个Batch(批处理)过程由一个Job(作业)组成。这个实体封装了整个批处理过程。

一个Job(作业)可以由一个或多个Step(步骤)组成。在大多数情况下,一个步骤将读取数据(通过ItemReader),处理数据(使用ItemProcessor),然后写入数据(通过ItemWriter)。

JobLauncher处理启动一个Job(作业)。

最后,JobRepository存储关于配置和执行的Job(作业)的元数据。

二、实例

1、新建 springboot项目

创建项目传送门
选择配置,添加依赖,GENERATE 后导入到你的IDE

2、springboot 项目配置

2.1 在新建项目时添加依赖了,就会发现pom中引入了 spring-barch的相关依赖,如新建项目时没有添加依赖,则需要手动添加。

//pom.xml
<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-batch</artifactId>
	</dependency>

	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
		<scope>test</scope>
		<exclusions>
			<exclusion>
				<groupId>org.junit.vintage</groupId>
				<artifactId>junit-vintage-engine</artifactId>
			</exclusion>
		</exclusions>
	</dependency>
	<dependency>
		<groupId>org.springframework.batch</groupId>
		<artifactId>spring-batch-test</artifactId>
		<scope>test</scope>
	</dependency>
</dependencies>
<build>
	<plugins>
		<plugin>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-maven-plugin</artifactId>
		</plugin>
	</plugins>
</build>

2.2 为主程序的@SpringBootApplication注解添加exclude属性,可以防止 SpringBoot 为数据库连接自动配置 DataSource

//主程序
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class Springbatch2020829Application {
    
    
	public static void main(String[] args) {
    
    
		SpringApplication.run(Springbatch2020829Application.class, args);
	}
}

2.3 新建实体model

//Person.java
public class Person {
    
    
    private String firstName;
    private String lastName;
}
//构造函数,get,set方法, toString()方法略

2.4 配置 Spring Batch Job
2.4.1 新建 BatchConfig 类,重写父类 setDataSource 方法

//BatchConfig.java
@Configuration
@EnableBatchProcessing
public class BatchConfig extends DefaultBatchConfigurer {
    
    
  @Override
  public void setDataSource(DataSource dataSource) {
    
    
  }
}

2.4.2 新建 HelloWorldJobConfig 类,配置 job ,step

//HelloWorldJobConfig.java
@Configuration
public class HelloWorldJobConfig {
    
    
  //新建 Job,Spring 将自动注入 jobBuilders ,stepBuilders两个 beans
  @Bean
  public Job helloWorlJob(JobBuilderFactory jobBuilders,
      StepBuilderFactory stepBuilders) {
    
    
    return jobBuilders.get("helloWorldJob")
        .start(helloWorldStep(stepBuilders)).build();
  }
  //新建 Step,使用 StepBuilderFactory 创建
  @Bean
  public Step helloWorldStep(StepBuilderFactory stepBuilders) {
    
    
    return stepBuilders.get("helloWorldStep")
        .<Person, String>chunk(10).reader(reader())
        .processor((Function<? super Person, ? extends String>) processor()).writer(writer()).build();
  }
  //读取数据,指定需要读取的资源
  @Bean
  public FlatFileItemReader<Person> reader() {
    
    
    return new FlatFileItemReaderBuilder<Person>()
        .name("personItemReader")
        .resource(new ClassPathResource("csv/persons.csv"))
        .delimited().names(new String[] {
    
    "firstName", "lastName"})
        .targetType(Person.class).build();
  }
  //处理数据
  @Bean
  public PersonItemProcessor processor() {
    
    
    return new PersonItemProcessor();
  }
  //写入数据,指定写入路径文件
  @Bean
  public FlatFileItemWriter<String> writer() {
    
    
    return new FlatFileItemWriterBuilder<String>()
        .name("greetingItemWriter")
        .resource(new FileSystemResource(
            "target/test-outputs/greetings.txt"))
        .lineAggregator(new PassThroughLineAggregator<>()).build();
  }
}

2.5 处理数据

//PersonItemProcessor.java
public class PersonItemProcessor
    implements ItemProcessor<Person, String> {
    
    

  private static final Logger LOGGER =
      LoggerFactory.getLogger(PersonItemProcessor.class);
  //打印日志信息	
  @Override
  public String process(Person person) throws Exception {
    
    
    String greeting = "Hello " + person.getFirstName() + " "
        + person.getLastName() + "!";
	
    LOGGER.info("converting '{}' into '{}'", person, greeting);
    return greeting;
  }
}

2.6 测试 Spring Batch 示例

//测试类
package com.fyy.springbatch;
import static org.assertj.core.api.Assertions.assertThat;

@RunWith(SpringRunner.class)
@SpringBootTest(
        classes = {
    
    Springbatch2020829ApplicationTests.BatchTestConfig.class})
public class Springbatch2020829ApplicationTests {
    
    
    @Autowired
    private JobLauncherTestUtils jobLauncherTestUtils;

    @Test
    public void testHelloWorldJob() throws Exception {
    
    
        JobExecution jobExecution = jobLauncherTestUtils.launchJob();
        assertThat(jobExecution.getExitStatus().getExitCode())
                .isEqualTo("COMPLETED");
    }

    @Configuration
    @Import({
    
    BatchConfig.class, HelloWorldJobConfig.class})
    static class BatchTestConfig {
    
    

        @Autowired
        private Job helloWorlJob;

        @Bean
        JobLauncherTestUtils jobLauncherTestUtils()
                throws NoSuchJobException {
    
    
            JobLauncherTestUtils jobLauncherTestUtils =
                    new JobLauncherTestUtils();
            jobLauncherTestUtils.setJob(helloWorlJob);

            return jobLauncherTestUtils;
        }
    }
}

2.7 启动项目,在 target/test-outputs/greetings.txt 文件中找到结果。
在这里插入图片描述

三、理解

JobRepository

从字面上可以理解为"任务仓库",如果把一个批处理比作一个任务的话,这个仓库存储了很多这种任务。JobRepository 会将任务包括其状态等数据持久化,存储到许多数据库中。Spring Batch 默认会提供一个 SimpleJobRepository 仓库,方便我们开启批处理。

Job

“任务”。每个批处理都是一个任务,除了任务本身之外,任务也存在成功和失败等等状态,所以可以引出两个概念 JobInstance 与 JobExecution 。job 是一个接口,JobInstance 是其实现,代表了“任务”本身,提供了 getJobName、getInstanceId 等方法供我们获取任务本身的一些属性。JobExecution 代表任务的状态,如创建时间、结束时间、结束状态、抛出的异常等等。

Step

“步骤”。批处理任务肯定有非常多的步骤,如一个最基本的数据库同步,从 A 数据库读取数据,存入到 B 数据库中,这里就分为了两个步骤。在 Spring Batch 中,一个任务可以有很多个步骤,每个步骤大致分为三步:读、处理、写,其对应的类分别就是 Item Reader,Item Processor,Item Writer。

JobLauncher

“任务装置”。如火箭发射装置就是用来操作火箭发射的,这里的任务装置就是用来执行任务的。

猜你喜欢

转载自blog.csdn.net/weixin_42653522/article/details/108298597