Java:SpringBoot整合Spring Batch示例

news2025/2/23 12:04:51

在这里插入图片描述

目录

    • 文档
    • 基础概念
    • Tasklet方式示例
    • Chunk方式示例
    • 参考文章

文档

  • https://docs.spring.io/spring-batch/docs/4.3.9/reference/html/index.html

基础概念

  • JobLauncher:作业启动器,启动作业的入口。对应的实现类为SimpleJobLauncher。
  • Job:作业,用于配置作业的相关配置,一个作业可以配置多个步骤,步骤之间是有序的。
  • Step:步骤,作业具体执行的业务逻辑,一个Job可以配置多个Step。步骤有两种实现方式:
    • Tasklet方式:所有作业逻辑写在一个方法中。
    • Chunk方式:将一个完整的作业逻辑根据作用拆分到三个方法中
      • ItemReader:负责从数据源中读数据(如从文件、数据库等)。
      • ItemProcessor :负责对读出来的数据进行非法校验和对数据进行加工。
      • ItemWriter:将数据写到某个目标中(如文件、数据库等)。
  • JobBuilderFactory:作业构建起工厂,用于构建作业Job对象。
    • get(String name):设置作业名称。
    • start(Step step):设置作业启动的第一个步骤。
    • build():构建Job对象。
  • StepBuilderFactory:作业构建器工厂,用于构造步骤Step对象。
    • get(String name):设置步骤名称。
    • tasklet(Tasklet tasklet):设置Tasklet。
    • build():构建Step对象。
  • JobRepository:作业持久化,在执行作业的过程中用于操作spring batch相关的表,记录作业的相关状态等。

Tasklet方式示例

运行环境

$ java -version
java version "1.8.0_361"
Java(TM) SE Runtime Environment (build 1.8.0_361-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.361-b09, mixed mode)

spring-batch依赖

<!-- spring-batch -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-batch</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.batch</groupId>
    <artifactId>spring-batch-test</artifactId>
    <scope>test</scope>
</dependency>

<!-- h2、mysql... -->
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>runtime</scope>
</dependency>

备注:第一次照着网上的文章写代码运行,直接报错,原因是缺少引入的依赖;需要引入数据库驱动,如H2或mysql

项目结构

$ tree 
.
├── pom.xml
└── src
    └── main
        ├── java
        │   └── com
        │       └── example
        │           └── demo
        │               ├── HelloWorldApplication.java
        │               ├── config
        │               │   └── BatchConfig.java
        │               └── task
        │                   └── HelloWorldTasklet.java
        └── resources


完整依赖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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.7</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <mybatis-plus.version>3.5.2</mybatis-plus.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- spring-batch -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-batch</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.batch</groupId>
            <artifactId>spring-batch-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>

        <!-- test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

编写业务逻辑

package com.example.demo.task;

import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.stereotype.Component;

/**
 * 任务
 */
@Component
public class HelloWorldTasklet implements Tasklet {
    @Override
    public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
        System.out.println("Hello, World!");
        return RepeatStatus.FINISHED;
    }
}

配置作业步骤

package com.example.demo.config;

import com.example.demo.task.HelloWorldTasklet;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Spring Batch配置
 */
@Configuration
public class BatchConfig {
    @Autowired
    private JobBuilderFactory jobBuilderFactory;

    @Autowired
    private StepBuilderFactory stepBuilderFactory;

    @Autowired
    private HelloWorldTasklet helloWorldTasklet;

    @Bean
    public Step step() {
        return this.stepBuilderFactory.get("step")
                .tasklet(helloWorldTasklet)
                .build();
    }

    @Bean
    public Job job(Step step) {
        return this.jobBuilderFactory.get("job")
                .start(step)
                .build();
    }
}

启动类增加注解:@EnableBatchProcessing

package com.example.demo;

import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@EnableBatchProcessing
@SpringBootApplication
public class HelloWorldApplication {
    public static void main(String[] args) {
        SpringApplication.run(HelloWorldApplication.class, args);
    }

}

Chunk方式示例

项目结构

$ tree
.
├── pom.xml
└── src
    └── main
        ├── java
        │   └── com
        │       └── example
        │           └── demo
        │               ├── Application.java
        │               ├── config
        │               │   └── BatchConfig.java
        │               ├── dto
        │               │   └── Person.java
        │               └── processor
        │                   └── PersonItemProcessor.java
        └── resources
            └── persons.csv

依赖pom.xml 同上

package com.example.demo.dto;

import lombok.Data;

@Data
public class Person {
    private String name;
    private Integer age;
}

package com.example.demo.config;

import com.example.demo.dto.Person;
import com.example.demo.processor.PersonItemProcessor;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder;
import org.springframework.batch.item.json.JacksonJsonObjectMarshaller;
import org.springframework.batch.item.json.JsonFileItemWriter;
import org.springframework.batch.item.json.builder.JsonFileItemWriterBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;

/**
 * Spring Batch配置
 */
@Configuration
public class BatchConfig {
    @Autowired
    private JobBuilderFactory jobBuilderFactory;

    @Autowired
    private StepBuilderFactory stepBuilderFactory;


    @Bean
    public Step step() {
        return this.stepBuilderFactory.get("step")
                .<Person, Person>chunk(10)
                .reader(reader())
                .processor(processor())
                .writer(writer())
                .build();
    }

    @Bean
    public Job job(Step step) {
        return this.jobBuilderFactory.get("job")
                .start(step)
                .build();
    }

    /**
     * 读取csv文件
     * @return
     */
    @Bean
    public FlatFileItemReader<Person> reader() {
        return new FlatFileItemReaderBuilder<Person>()
                .name("personItemReader")
                .resource(new ClassPathResource("persons.csv"))
                .delimited()
                .names(new String[] {"name", "age"})
                .targetType(Person.class)
                .build();
    }

    /**
     * 处理器
     * @return
     */
    @Bean
    public PersonItemProcessor processor() {
        return new PersonItemProcessor();
    }

    /**
     * 写到json文件
     * @return
     */
    @Bean
    public JsonFileItemWriter<Person> writer() {
        return new JsonFileItemWriterBuilder<Person>()
                .jsonObjectMarshaller(new JacksonJsonObjectMarshaller<>())
                .resource(new FileSystemResource("persons.json"))
                .name("personItemWriter")
                .build();
    }

}

package com.example.demo.processor;

import com.example.demo.dto.Person;
import org.springframework.batch.item.ItemProcessor;

public class PersonItemProcessor implements ItemProcessor<Person, Person> {
    @Override
    public Person process(Person person) throws Exception {
        // 为每个对象年龄+1
        person.setAge(person.getAge() + 1);
        return person;
    }
}

启动入口

package com.example.demo;

import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@EnableBatchProcessing
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

启动SpringBoot即可运行任务

读取的persons.csv文件

Tom,18
Jack,20

生成的persons.json 文件

[
 {"name":"Tom","age":19},
 {"name":"Jack","age":21}
]

参考文章

  1. SpringBatch从入门到实战(二):HelloWorld
  2. Spring Batch 之 Hello World
  3. Spring Batch 入门级示例教程
  4. Spring Batch 批处理框架优化实践,效率嘎嘎高!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1101224.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PLC通过Modbus转Profinet网关连接变频器控制电机配置案例

在本案例中&#xff0c;通过使用Modbus转Profinet网关&#xff08;XD-MDPN100&#xff09;&#xff0c;PLC可以通过Profinet协议与变频器进行通信和控制。这样&#xff0c;PLC可以实现对电机的转速调节、启停控制等功能。 同时&#xff0c;通过Modbus转Profinet&#xff08;XD-…

你还在为协同办公烦恼吗?试试视频协同办公吧!

在这个信息化、数字化的时代&#xff0c;协同办公已经成为了企业、团队的必备工具。然而&#xff0c;尽管传统的协同办公工具有诸多优点&#xff0c;但在实际使用中&#xff0c;仍会遇到各种各样的问题。你是否还在为这些问题而烦恼&#xff1f;别担心&#xff0c;让我们一起探…

【C++】函数重载 引用 内联函数

目录 一&#xff0c;函数重载 1&#xff0c;函数重载的概念 2&#xff0c;C支持函数重载的原理 二&#xff0c;引用 1&#xff0c;引用概念 2&#xff0c;引用特性 3&#xff0c;常引用 4&#xff0c;做参数 5&#xff0c;做返回值 6&#xff0c;传值、传引用效率比较…

【LeetCode(LeetCode刷题经典一百题)】:移动零

给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作 示例 1: 输入: nums [0,1,0,3,12] 输出: [1,3,12,0,0] 示例 2: 输入: nums [0] 输出: [0] 方…

python二次开发CATIA:全约束草图

​约束的创建需要用到 Sketch 下面 Constraints 这个 Collection 的 Add 方法。该对象创建约束有三个方法&#xff1a;AddMonoEltCst&#xff0c; AddBiEltCst&#xff0c; AddTriEltCst&#xff0c;对应的功能分别为为单个元素创建约束&#xff08;如固定 a&#xff09; 、为两…

RHCE8 资料整理(一)

RHCE8 资料整理 第一篇 基本配置第1章 安装RHEL8第2章 基本命令的使用2.1 终端设置2.2 输入命令的语法2.3 介绍shell2.4 用户切换 第3章 了解linux分区及常用命令3.1 路径3.2 创建和删除目录3.3 cd3.4 拷贝和剪切3.5 常见命令归纳filewctouchlnalias/unaliascat/tac/nlmore/les…

世界粮食日:宏工科技有对策,赋能食品生产高效可持续发展

10月16日是世界粮食日。随着全球人口的增长&#xff0c;人们对高品质食品的需求也越来越大&#xff0c;如何实现“更好生产、更好营养”成为了食品生产与供应的重要话题。15年来&#xff0c;宏工科技专注物料处理自动化领域&#xff0c;提供食品物料处理一站式解决方案以提高生…

数字孪生技术如何提高化工生产安全性?

随着科技的不断进步&#xff0c;数字孪生技术已经渗透到了各个领域&#xff0c;为化工行业带来了翻天覆地的变革。这一技术的应用不仅在生产效率方面发挥了积极作用&#xff0c;还在安全性、创新、环保和可持续性等多个方面作出了巨大的贡献。 化工行业常常涉及危险品和复杂的生…

网络安全行业需要考哪些证书

一、NISP国家信息安全水平证书 国家信息安全水平考试&#xff08;National Information Security Test Program&#xff0c;简称NISP&#xff09;&#xff0c;是由中国信息安全测评中心实施培养国家网络空间安全人才的项目。由国家网络空间安全人才培养基地运营/管理&#xff…

vue3 电子签名实现

vue电子签名可以通过vue-esign插件来实现: 第一步安装&#xff1a; npm install vue-esign 引用方式&#xff1a; 全局&#xff1a; 局部&#xff1a; // .vue 文件 import vueEsign form vue-esign 使用方式&#xff1a; <template><!-- 使用这个签名组件 --&…

WampServer下载安装并结合cpolar内网穿透实现本地服务的公网访问

文章目录 前言1.WampServer下载安装2.WampServer启动3.安装cpolar内网穿透3.1 注册账号3.2 下载cpolar客户端3.3 登录cpolar web ui管理界面3.4 创建公网地址 4.固定公网地址访问 前言 Wamp 是一个 Windows系统下的 Apache PHP Mysql 集成安装环境&#xff0c;是一组常用来…

爬虫ip如何加入到代码里实现自动化数据抓取

以下是一个使用HTTP:Tiny和www.weibo.com的音频爬虫程序的示例。这个示例使用了https://www.duoip.cn/get_proxy来获取爬虫IP。请注意&#xff0c;这个示例可能需要根据你的实际需求进行调整。 #!/usr/bin/perluse strict; use warnings; use HTTP::Tiny; use LWP::UserAgent; …

智能垃圾桶丨悦享便捷生活

垃圾桶是人们日常生活所必不可少的必需品&#xff0c;它让生活中所产生的垃圾有了一个正确的存放地方。随着生产技术的迅速发展&#xff0c;垃圾桶也得以更新换代。由最初的简单式的圆筒式垃圾桶&#xff0c;到现在出现的感应式垃圾桶、智能语音控制垃圾桶&#xff0c;垃圾桶也…

紫光展锐荣评“5G技术创新力企业”,5G赋能千行百业

近日&#xff0c;2023年第十七届中国通信产业榜隆重发布&#xff0c;紫光展锐凭借多年以来在通信和芯片技术上的积累&#xff0c;从众多参选者中脱颖而出&#xff0c;荣评“5G技术创新力企业”&#xff0c;并蝉联2023年通信产业榜“中国通信设备技术服务供应商100强”。 作为一…

2023年中国求职招聘类APP行业现状及市场格局分析[图]

求职招聘类APP行业涉及互联网信息技术行业、人力资源行业&#xff0c;受到多个部门的监督管理&#xff0c;包括国家互联网信息办公室、工业与信息化部、人社部、商务部等。 中国人力资源市场正朝着信息化、数字化的方向不断发展。新兴技术赋能将大幅提升服务效率&#xff0c;我…

分享成功实施RPA(机器人流程自动化)的关键要素和经验技巧

在当今数字化时代&#xff0c;RPA&#xff08;机器人流程自动化&#xff09;已经成为企业组织提高效率、降低成本和提高竞争力的强大工具&#xff0c;各行各业都在寻找创新方式来实现业务自动化。但RPA的成功实施并非轻而易举&#xff0c;它需要精心策划和明智决策。本文&#…

list.set交换数据需要(or不需要)添加其他中间变量,两个例子告诉你

说明&#xff1a;set()方法是来修改指定位置的元素。 两个参数&#xff0c;第一个参数是要修改的元素的索引&#xff0c;第二个参数是要设置的新值。 案例一&#xff1a;当链表中传入的是字符串时&#xff1a; public static void main(String[] args) {List list new Linke…

数据库管理-第111期 Oracle Exadata 02-硬件构成(20231017)

数据库管理-第111期 Oracle Exadata 02-硬件构成&#xff08;202301017&#xff09; 新开的坑&#xff0c;感觉一般般&#xff0c;还是坚持写下去吧。 1 过去和Exadata相关的博文 这里集合汇总一下之前写过的和Exadata相关的文章&#xff1a; 数据库管理-第三十七期 我搞挂了…

【塔防】1,游戏架构

游戏架构 一&#xff0c;StoneDefence核心架构分析1&#xff0c;安装2&#xff0c;核心框架2.1创建核心核心环境2.1.1游戏中的核心元素&#xff08;GameCore&#xff09;ApawnGameInstanceGameStatePlayerStatePlayerControllerGameUserSettings 2.1.2大厅中的核心元素&#xf…

手撕Vue-数据驱动界面改变下

经过上一篇的介绍&#xff0c;已经实现了观察者模式的基本内容&#xff0c;接下来要完成的就是将上一篇的发布订阅模式运用到 Nue 中&#xff0c;实现数据驱动界面改变。 在监听数据变化的章节当中&#xff0c;根据指定的区域和数据去编译渲染界面 这个步骤处&#xff0c;我写了…