SpringBatch文件读写ItemWriter,ItemReader使用详解

SpringBatch文件读写ItemWriter,ItemReader使用详解

  • 1. ItemReaders 和 ItemWriters
    • 1.1. ItemReader
    • 1.2. ItemWriter
    • 1.3. ItemProcessor
  • 2.FlatFileItemReader 和 FlatFileItemWriter
    • 2.1.平面文件
      • 2.1.1. FieldSet
    • 2.2. FlatFileItemReader
    • 2.3. FlatFileItemWriter
  • 3.FlatFileItemReader 和 FlatFileItemWriter 使用案例

1. ItemReaders 和 ItemWriters

所有批处理都可以以其最简单的形式描述为读取大量数据,执行某种类型的计算或转换并写出结果。 Spring Batch 提供了三个关键接口来帮助执行批量读取和写入:ItemReader,ItemProcessor 和 ItemWriter。

1.1. ItemReader

注:内容来源于springbatch官网: https://docs.spring.io/spring-batch/reference/readers-and-writers/item-reader.html

尽管是一个简单的概念,但ItemReader是用于从许多不同类型的 Importing 中提供数据的方法。最一般的示例包括:

  • 平面文件:平面文件 Item 读取器从平面文件中读取数据行,该文件通常描述记录,这些记录的数据字段由文件中的固定位置定义或由某些特殊字符(例如逗号)分隔。

  • XML:XML ItemReaders独立于用于解析,Map 和验证对象的技术来处理 XML。Importing 数据允许根据 XSD 模式验证 XML 文件。

  • 数据库:访问数据库资源以返回结果集,该结果集可以 Map 到对象以进行处理。默认的 SQL ItemReader实现调用RowMapper来返回对象,如果需要重新启动,则跟踪当前行,存储基本统计信息,并提供一些事务增强功能,这些将在后面进行说明。

ItemReader是通用 Importing 操作的基本接口,如以下接口定义所示:

public interface ItemReader<T> {T read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException;
}

read方法定义ItemReader的最基本 Contract。调用它会返回一个 Item;如果没有更多 Item,则返回null。一个 Item 可能代表文件中的一行,数据库中的一行或 XML 文件中的元素。通常希望将它们 Map 到可用的域对象(例如Trade,Foo或其他),但是 Contract 中没有要求这样做。

1.2. ItemWriter

ItemWriter在功能上与ItemReader类似,但是具有相反的运算。资源仍然需要定位,打开和关闭,但是它们的区别在于ItemWriter是写出而不是读入。对于数据库或队列,这些操作可能是插入,更新或发送。输出序列化的格式特定于每个批处理作业。

与ItemReader一样,ItemWriter是一个相当通用的接口,如以下接口定义所示:

public interface ItemWriter<T> {void write(List<? extends T> items) throws Exception;
}

与ItemReader上的read一样,write提供ItemWriter的基本 Contract。只要打开,它就会尝试写出传入 Item 的列表。因为通常期望将 Item“分批”在一起,然后输出,所以接口接受 Item 列表,而不是 Item 本身。写入列表后,可以执行任何必要的刷新操作,然后再从 write 方法返回。例如,如果写入一个 Hibernate DAO,则可以进行多个写入操作,每个 Item 一个。然后,Writer 可以在休眠会话上调用flush,然后再返回。

1.3. ItemProcessor

ItemReader和ItemWriter接口对于它们的特定任务都非常有用,但是如果要在编写之前插入业务逻辑怎么办?读写的一种选择是使用复合模式:创建包含另一个ItemWriter的ItemWriter或包含另一个ItemReader的ItemReader。以下代码显示了一个示例:

public class CompositeItemWriter<T> implements ItemWriter<T> {ItemWriter<T> itemWriter;public CompositeItemWriter(ItemWriter<T> itemWriter) {this.itemWriter = itemWriter;}public void write(List<? extends T> items) throws Exception {//Add business logic hereitemWriter.write(items);}public void setDelegate(ItemWriter<T> itemWriter){this.itemWriter = itemWriter;}
}

上一类包含另一个ItemWriter,它在提供了一些业务逻辑后将其委托给该ItemWriter。该模式也可以很容易地用于ItemReader,也许可以基于主ItemReader提供的 Importing 来获取更多参考数据。如果您需要自己控制对write的调用,它也很有用。但是,如果您只想在实际写入之前“转换”传递给写入的 Item,则无需自己write。您可以只修改 Item。对于这种情况,Spring Batch 提供了ItemProcessor接口,如以下接口定义所示:

public interface ItemProcessor<I, O> {O process(I item) throws Exception;
}

ItemProcessor很简单。给定一个对象,对其进行转换,然后返回另一个。提供的对象可以是或可以不是相同的类型。关键是可以在流程中应用业务逻辑,并且完全由开发人员来创建该逻辑。 ItemProcessor可以直接连接到步骤中。例如,假设ItemReader提供了Foo类型的类,并且在将其写出之前需要将其转换为Bar类型。以下示例显示了执行转换的ItemProcessor:

public class Foo {}public class Bar {public Bar(Foo foo) {}
}public class FooProcessor implements ItemProcessor<Foo,Bar>{public Bar process(Foo foo) throws Exception {//Perform simple transformation, convert a Foo to a Barreturn new Bar(foo);}
}public class BarWriter implements ItemWriter<Bar>{public void write(List<? extends Bar> bars) throws Exception {//write bars}
}

在前面的示例中,存在一个类Foo,一个类Bar和一个FooProcessor,它们坚持ItemProcessor接口。转换很简单,但是任何类型的转换都可以在这里完成。 BarWriter写入Bar对象,如果提供任何其他类型,则抛出异常。同样,如果提供了Foo以外的内容,则FooProcessor引发异常。然后可以将FooProcessor注入到Step中,如以下示例所示:

@Bean
public Job ioSampleJob() {return this.jobBuilderFactory.get("ioSampleJOb").start(step1()).end().build();
}@Bean
public Step step1() {return this.stepBuilderFactory.get("step1").<String, String>chunk(2).reader(fooReader()).processor(fooProcessor()).writer(barWriter()).build();
}

2.FlatFileItemReader 和 FlatFileItemWriter

注:内容来源springbatch官网链接: https://docs.spring.io/spring-batch/reference/readers-and-writers/flat-files/field-set.html

2.1.平面文件

交换批量数据的最常见机制之一一直是平面文件。与 XML 具有定义其结构化(XSD)的公认标准不同,任何阅读平面文件的人都必须提前了解文件的结构。通常,所有平面文件都分为两种:定界文件和定长文件。分隔文件是指用逗号分隔分隔符的字段。固定长度文件具有设置长度的字段。

2.1.1. FieldSet

在 Spring Batch 中使用平面文件时,无论是用于 Importing 还是输出,最重要的类之一是FieldSet。许多体系结构和库都包含用于帮助您从文件读入的抽象,但是它们通常返回String或String对象的数组。这真的只会让您半途而废。 FieldSet是 Spring Batch 的抽象,用于启用文件资源中字段的绑定。它使开发人员可以像处理数据库 Importing 一样使用文件 Importing。 FieldSet在概念上与 JDBC ResultSet类似。 FieldSet仅需要一个参数:String令牌数组。 (可选)您还可以配置字段的名称,以便可以按ResultSet之后的模式通过索引或名称来访问字段,如以下示例所示:

String[] tokens = new String[]{"foo", "1", "true"};
FieldSet fs = new DefaultFieldSet(tokens);
String name = fs.readString(0);
int value = fs.readInt(1);
boolean booleanValue = fs.readBoolean(2);

FieldSet界面上还有更多选项,例如Date,long,BigDecimal等等。 FieldSet的最大优点是它提供了平面文件 Importing 的一致解析。在处理由格式异常引起的错误或进行简单的数据转换时,它可以保持一致,而不是使每个批处理作业以潜在的意外方式进行不同的解析。

2.2. FlatFileItemReader

平面文件是最多包含二维(表格)数据的任何类型的文件。名为FlatFileItemReader的类有助于在 Spring Batch 框架中读取平面文件,该类提供了用于读取和解析平面文件的基本功能。 FlatFileItemReader的两个最重要的必需依存关系是Resource和LineMapper。 LineMapper接口将在下一部分中进行详细介绍。 resource 属性表示一个 Spring Core Resource。可以在Spring 框架资源中找到说明如何创建此类 bean 的文档。

Resource resource = new FileSystemResource("resources/trades.csv");

FlatFileItemReader中的其他属性使您可以进一步指定数据的解释方式,如下表所述:

在这里插入图片描述
LineMapper
与RowMapper一样,它采用诸如ResultSet之类的低级构造并返回Object,平面文件处理需要相同的构造才能将String行转换为Object,如以下接口定义所示:

public interface LineMapper<T> {T mapLine(String line, int lineNumber) throws Exception;
}

基本约定是,给定当前行及其关联的行号,Map 器应返回结果域对象。这类似于RowMapper,因为每一行都与其行号相关联,就像ResultSet中的每一行都与其行号绑定一样。这允许将行号绑定到结果域对象,以进行身份比较或提供更多信息。但是,与RowMapper不同,LineMapper被赋予了原始行,如上所述,该原始行只会使您到达中间。该行必须标记为FieldSet,然后可以将其 Map 到一个对象

LineTokenizer
必须将 Importing 行转换为FieldSet的抽象,因为可能需要将多种格式的平面文件数据转换为FieldSet。在 Spring Batch 中,此接口是LineTokenizer:

public interface LineTokenizer {FieldSet tokenize(String line);
}

LineTokenizer的约定是这样的:给定 Importing 行(理论上String可以包含多条线),则返回代表该行的FieldSet。然后可以将此FieldSet传递给FieldSetMapper。 Spring Batch 包含以下LineTokenizer实现:

  • DelimitedLineTokenizer:用于 Logging 的字段由定界符分隔的文件。最常见的定界符是逗号,但是也经常使用竖线或分号。

  • FixedLengthTokenizer:用于 Logging 的字段均为“固定宽度”的文件。必须为每种记录类型定义每个字段的宽度。

  • PatternMatchingCompositeLineTokenizer:通过检查模式,确定应在特定行上使用标记器列表中的哪个LineTokenizer。

- FieldSetMapper
FieldSetMapper接口定义单个方法mapFieldSet,该方法采用FieldSet对象并将其内容 Map 到对象。根据作业的需要,此对象可以是自定义 DTO,域对象或数组。 FieldSetMapper与LineTokenizer结合使用,可将一行数据从资源转换为所需类型的对象,如以下接口定义所示:

public interface FieldSetMapper<T> {T mapFieldSet(FieldSet fieldSet) throws BindException;
}

使用的模式与JdbcTemplate使用的RowMapper相同。

DefaultLineMapper
既然已经定义了读取平面文件的基本接口,那么很明显,需要三个基本步骤:

  • 从文件中读取一行。
  • 将String行传递到LineTokenizer#tokenize()方法中以检索FieldSet。
  • 将标记化返回的FieldSet传递给FieldSetMapper,并从ItemReader#read()方法返回结果。

上述两个接口代表两个单独的任务:将线转换为FieldSet并将FieldSetMap 到域对象。因为LineTokenizer的 Importing 与LineMapper的 Importing(一条线)匹配,并且FieldSetMapper的输出与LineMapper的输出匹配,所以提供了同时使用LineTokenizer和FieldSetMapper的默认实现。下列类定义中显示的DefaultLineMapper表示大多数用户需要的行为:

public class DefaultLineMapper<T> implements LineMapper<>, InitializingBean {private LineTokenizer tokenizer;private FieldSetMapper<T> fieldSetMapper;public T mapLine(String line, int lineNumber) throws Exception {return fieldSetMapper.mapFieldSet(tokenizer.tokenize(line));}public void setLineTokenizer(LineTokenizer tokenizer) {this.tokenizer = tokenizer;}public void setFieldSetMapper(FieldSetMapper<T> fieldSetMapper) {this.fieldSetMapper = fieldSetMapper;}
}

以上功能是默认实现中提供的,而不是内置于 Reader 本身中(如在框架的先前版本中所做的那样),以使用户在控制解析过程时具有更大的灵 Active,尤其是在需要访问原始行的情况下。

2.3. FlatFileItemWriter

写入平面文件具有相同的问题和必须从文件中读取的问题。步骤必须能够以事务方式编写定界或定长格式。

LineAggregator
就像需要LineTokenizer接口来获取一项并将其变成String一样,文件写入必须具有一种将多个字段聚合到单个字符串中以写入文件的方法。在 Spring Batch 中,这是LineAggregator,如以下接口定义所示:

public interface LineAggregator<T> {public String aggregate(T item);
}

LineAggregator与LineTokenizer逻辑相反。 LineTokenizer取String并返回FieldSet,而LineAggregator取item并返回String。

PassThroughLineAggregator
LineAggregator接口的最基本实现是PassThroughLineAggregator,它假定对象已经是一个字符串或它的字符串表示形式可以接受写入,如以下代码所示:

public class PassThroughLineAggregator<T> implements LineAggregator<T> {public String aggregate(T item) {return item.toString();}
}

如果需要直接控制创建字符串,但是FlatFileItemWriter的优点(例如事务和重新启动支持)是必需的,则上述实现很有用。

简化文件编写示例
既然已经定义了LineAggregator接口及其最基本的实现PassThroughLineAggregator,那么可以说明基本的编写流程:

  • 要写入的对象被传递到LineAggregator以获得String。
  • 返回的String将被写入配置的文件。

FlatFileItemWriter的以下摘录用代码表示:

public void write(T item) throws Exception {write(lineAggregator.aggregate(item) + LINE_SEPARATOR);
}

一个简单的配置可能如下所示:

@Bean
public FlatFileItemWriter itemWriter() {return  new FlatFileItemWriterBuilder<Foo>().name("itemWriter").resource(new FileSystemResource("target/test-outputs/output.txt")).lineAggregator(new PassThroughLineAggregator<>()).build();
}

FieldExtractor
前面的示例对于写入文件的最基本用途可能很有用。但是,FlatFileItemWriter的大多数用户都有一个域对象,需要将该域对象写出,因此必须将其转换为一行。在读取文件时,需要满足以下条件:

  • 从文件中读取一行。
  • 将行传递到LineTokenizer#tokenize()方法中,以便检索FieldSet。
    将标记化返回的FieldSet传递给FieldSetMapper,并从ItemReader#read()方法返回结果。

文件写入具有相似但相反的步骤:

  • 将要写入的 Item 传递给 Writer。
  • 将 Item 上的字段转换为数组。
  • 将结果数组聚合为一行。

因为框架没有办法知道需要写出对象中的哪些字段,所以必须写一个FieldExtractor来完成将 Item 变成数组的任务,如以下接口定义所示:

public interface FieldExtractor<T> {Object[] extract(T item);
}

FieldExtractor接口的实现应从提供的对象的字段中创建一个数组,然后可以使用元素之间的分隔符将其写出,也可以将其写为固定宽度的行的一部分。

PassThroughFieldExtractor
在许多情况下,需要写出集合,例如数组Collection或FieldSet。从这些集合类型之一中“提取”数组非常简单。为此,请将集合转换为数组。因此,在这种情况下应使用PassThroughFieldExtractor。应当注意,如果传入的对象不是集合的类型,则PassThroughFieldExtractor返回仅包含要提取的 Item 的数组。

BeanWrapperFieldExtractor
与在文件读取部分中介绍的BeanWrapperFieldSetMapper一样,通常最好配置如何将域对象转换为对象数组,而不是自己编写转换。 BeanWrapperFieldExtractor提供了此功能,如以下示例所示:

BeanWrapperFieldExtractor<Name> extractor = new BeanWrapperFieldExtractor<Name>();
extractor.setNames(new String[] { "first", "last", "born" });String first = "Alan";
String last = "Turing";
int born = 1912;Name n = new Name(first, last, born);
Object[] values = extractor.extract(n);assertEquals(first, values[0]);
assertEquals(last, values[1]);
assertEquals(born, values[2]);

此提取器实现只有一个必需的属性:要 Map 的字段的名称。就像BeanWrapperFieldSetMapper需要字段名称将FieldSet上的字段 Map 到所提供对象上的 setter 一样,BeanWrapperFieldExtractor也需要名称 Map 到 getter 来创建对象数组。值得注意的是,名称的 Sequences 决定了数组中字段的 Sequences。

3.FlatFileItemReader 和 FlatFileItemWriter 使用案例

下一篇: FlatFileItemReader 和 FlatFileItemWriter 使用案例

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

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

相关文章

AI 绘画|Midjourney设计Logo提示词

你是否已经看过许多别人分享的 MJ 咒语&#xff0c;却仍无法按照自己的想法画图&#xff1f;通过学习 MJ 的提示词逻辑后&#xff0c;你将能够更好地理解并创作自己的“咒语”。本文将详细拆解使用 MJ 设计 Logo 的逻辑&#xff0c;让你在阅读后即可轻松上手&#xff0c;制作出…

打包一个自己的Vivado IP核

写在前面 模块复用是逻辑设计人员必须掌握的一个基本功&#xff0c;通过将成熟模块打包成IP核&#xff0c;可实现重复利用&#xff0c;避免重复造轮子&#xff0c;大幅提高我们的开发效率。 接下来将之前设计的串口接收模块和串口发送模块打包成IP核&#xff0c;再分别调用…

【深度学习】FaceChain-SuDe,免训练,AI换脸

https://arxiv.org/abs/2403.06775 FaceChain-SuDe: Building Derived Class to Inherit Category Attributes for One-shot Subject-Driven Generation 摘要 最近&#xff0c;基于主体驱动的生成技术由于其个性化文本到图像生成的能力&#xff0c;受到了广泛关注。典型的研…

深度学习入门——神经网络

前言 神经网络可以帮助自动化设定权重 具体地讲&#xff0c;神经网络的一个重要性质是它可以自动地从数据中学习到合适的权重参数 从感知机到神经网络 神经网络的例子 中间层aka隐藏层 复习感知机 偏置b 并没有被画出来。如果要明确地表示出b&#xff0c;可以像图3-3那样做…

Large Language Model系列之一:语言模型与表征学习(Language Models and Representation Learning)

语言模型与表征学习&#xff08;Language Models and Representation Learning&#xff09; 1 语言模型 N-Gram模型 from collections import defaultdictsentences [The swift fox jumps over the lazy dog.,The swift river flows under the ancient bridge.,The swift br…

华为1000人校园实验记录

在这里插入代码片1000人校园区网设计 1、配置Eth-trunk实现链路冗余 vlan 900 管理WLAN #接入SW8 操作&#xff1a;sys undo in en sysname JR-SW8 int Eth-Trunk 1 mode lacp-static trunkport g0/0/1 0/0/2 port link-type trunk port trunk allow-pass vlan 200 900 qu vla…

模拟器小程序/APP抓包(Reqable+MUMU模拟器)

一、使用adb连接上MUMU模拟器 打开多开器点击ADB图标 连接模拟器端口&#xff1a; adb connect 127.0.0.1:16384列出已连接的设备&#xff1a; adb devices正常会显示MuMu的设备已连接 二、下载Reqable 1.下载链接&#xff1a;客户端下载 | Reqable 2.文档链接&#xff1a;…

redis基本类型和订阅

redis-cli -h <host> -p <port> -a <password> 其中&#xff0c;< host>是Redis服务器的主机名或IP地址&#xff0c;< port>是Redis服务器的端口号&#xff0c;< password>是Redis服务器的密码&#xff08;如果有的话&#xff09;。 set …

LLM基础模型系列:Prompt-Tuning

------->更多内容&#xff0c;请移步“鲁班秘笈”&#xff01;&#xff01;<------ 大型预训练语言模型的规模不断扩大&#xff0c;在许多自然语言处理 &#xff08;NLP&#xff09; 基准测试中取得了最先进的结果。自GPT和BERT开发以来&#xff0c;标准做法一直是在下游…

数字化教育资源如何适应人工智能时代

01 教育资源应动态适应一线教学需求 用好数字化教育资源是一项系统工程&#xff0c;涉及教育教学的各个方面&#xff0c;包括教师和学生的教育观念与技术观念、信息技术素养&#xff0c;以及课程教学改革、教师培训等。还涉及数字化教育资源提供方的服务&#xff0c;如技术支持…

【STM32嵌入式系统设计与开发---拓展】——1_9_1上拉输入和下拉输入

在使用GPIO引脚时&#xff0c;上拉输入和下拉输入的选择取决于外部电路的特性和应用需求。以下是它们各自的应用场景&#xff1a; 1、上拉输入&#xff08;Pull-up Input&#xff09; 用途: 当默认状态需要为高电平时。 避免引脚悬空&#xff08;floating&#xff09;导致的…

计算机网络——网络层(路由选择协议、路由器工作原理、IP多播、虚拟专用网和网络地址转换)

目录 路由选择协议 因特网的路由选择协议特点 路由信息协议RIP RIP衡量目的网络距离 RIP选择路由器的方式 RIP具有以下三个重要特点 RIP的基本工作流程 RIP的距离向量算法 ​编辑 ​编辑 RIP存在的问题——“坏消息传播得慢” RIP的封装 开放最短路径优先协议OSPF…

昇思25天学习打卡营第23天|基于MindSpore的Pix2Pix实现图像转换

Pix2Pix实现图像转换 Pix2Pix概述 Pix2Pix是基于条件生成对抗网络&#xff08;cGAN, Condition Generative Adversarial Networks &#xff09;实现的一种深度学习图像转换模型&#xff0c;该模型是由Phillip Isola等作者在2017年CVPR上提出的&#xff0c;可以实现语义/标签到…

【贪心算法】贪心算法30题

一、贪心算法简介 证明贪心策略正确性的常用方法&#xff1a;直接证明、交换论证法、反证法、分类讨论… 二、相关编程题 2.1 柠檬水找零 题目链接 860. 柠檬水找零 - 力扣&#xff08;LeetCode&#xff09; 题目描述 算法原理 提示&#xff1a;最优解和贪心解唯一可能不同…

《昇思25天学习打卡营第19天|Diffusion扩散模型》

什么是Diffusion Model&#xff1f; 什么是Diffusion Model? 如果将Diffusion与其他生成模型&#xff08;如Normalizing Flows、GAN或VAE&#xff09;进行比较&#xff0c;它并没有那么复杂&#xff0c;它们都将噪声从一些简单分布转换为数据样本&#xff0c;Diffusion也是从…

共建特色基地 协同互促育人

作为芯片和集成电路、人工智能、智能网联车等临港重点产业布局的知识密集型相关企业&#xff0c;核心技术人才和技术骨干是公司参与全球竞争的重要核心竞争力之一。 知从科技通过不断的创新和规范&#xff0c;在深化产教融合、校企合作、“双师型”、联合办学协同育人、产业人…

git回退分支版本git reset --hard HEAD

git回退分支版本git reset --hard HEAD git reset --hard HEAD 上面命令清除本地所有修改&#xff0c;与下面相似&#xff1a; git reset --hard origin/master 等同于&#xff1a; git reset --hard HEAD~0 说明&#xff1a; HEAD 当前版本 HEAD^ 上一个版本 HEAD^^ 上上…

Linux - 冯-诺依曼体系结构、初始操作系统

目录 冯•诺依曼体系 结构推导 内存提高效率的方法 数据的流动过程 体系结构相关知识 初始操作系统 定位 设计目的 操作系统之上之下分别有什么 管理精髓&#xff1a;先描述&#xff0c;再组织 冯•诺依曼体系 结构推导 计算机基本工作流程图大致如下&#xff1a; 输入设备&a…

支付宝低代码搭建电商小程序,无需编程,可视化操作

大家好&#xff0c;我是小悟 在数字化浪潮的推动下&#xff0c;为了更快速、高效地搭建电商小程序&#xff0c;支付宝低代码平台凭借其独特优势&#xff0c;为商家提供了便捷的解决方案。 支付宝低代码平台犹如一座精心打造的智慧工坊&#xff0c;让电商小程序的搭建变得轻而易…

Excel办公技巧:制作二级联动下拉菜单

分享制作二级联动下拉菜单的方法&#xff0c;即使数据有增删&#xff0c;菜单也能自动更新&#xff01; 可以通过先定义名称&#xff0c;再结合数据验证&#xff0c;来做二级联动下拉菜单。 1. 准备数据 首先&#xff0c;我们需要准备好要进行二级联动下拉菜单的数据&#xff…