ItemReaders 与 ItemWriters
所有批处理都可以用其最简单的形式描述为:读取大量数据,执行某种类型的计算或转换,然后写出结果。Spring Batch 提供了三个关键接口来帮助执行批量读写操作:ItemReader、ItemProcessor 和 ItemWriter。
章节总结
📄️ ItemReader
尽管概念简单,但ItemReader是从多种不同类型的输入中提供数据的手段。最常见的示例包括:
📄️ ItemWriter
ItemWriter 在功能上与 ItemReader 相似,但执行的是相反的操作。资源仍然需要定位、打开和关闭,但不同之处在于 ItemWriter 是写出数据,而不是读入数据。对于数据库或队列,这些操作可能是插入、更新或发送。输出序列化的格式因每个批处理作业而异。
📄️ ItemStream
ItemReader和ItemWriter各自都能很好地完成其特定任务,但两者存在一个共同需求,这催生了另一个接口。通常,在批处理作业的范畴内,读写器需要具备打开、关闭以及持久化状态保存机制。ItemStream接口正是为此目的而设计,如下例所示:
📄️ 委托模式与步骤注册
请注意,CompositeItemWriter 是委托模式的一个示例,这在 Spring Batch 中很常见。委托者本身可能实现回调接口,例如 StepListener。如果它们确实实现了此类接口,并且与 Spring Batch Core 结合使用,作为作业中某个步骤的一部分,那么几乎肯定需要手动将它们注册到该步骤中。直接连接到步骤的读取器、写入器或处理器如果实现了 ItemStream 或 StepListener 接口,则会自动注册。然而,由于步骤不知道这些委托者,因此需要将它们作为监听器或流(或两者,如果适用)注入。
🗃️ 平面文件
3 个项目
📄️ XML 项目读取器与写入器
Spring Batch 为读取XML记录并将其映射到Java对象,以及将Java对象写入为XML记录提供了事务性基础设施。
📄️ JSON 项目读取器与写入器
Spring Batch 为读取和写入以下格式的JSON资源提供了支持:
📄️ 多文件输入
在单个步骤中处理多个文件是一种常见需求。假设所有文件都具有相同的格式,MultiResourceItemReader 支持这种类型的输入,可用于 XML 和平面文件处理。考虑目录中的以下文件:
📄️ 数据库
与大多数企业应用风格一样,数据库是批处理的核心存储机制。然而,批处理与其他应用风格的不同之处在于系统必须处理的数据集规模极其庞大。如果一条 SQL 语句返回 100 万行数据,结果集可能会将所有返回结果保存在内存中,直到所有行都被读取完毕。Spring Batch 为这个问题提供了两种类型的解决方案:
📄️ 复用现有服务
批处理系统通常与其他应用风格结合使用。最常见的是在线系统,但也可以通过移动每种应用风格使用的必要批量数据来支持集成甚至富客户端应用。因此,许多用户希望在批处理作业中重用现有的DAO或其他服务是很常见的。Spring容器本身通过允许注入任何必要的类使这变得相当容易。然而,在某些情况下,现有服务可能需要充当 ItemReader 或 ItemWriter,要么是为了满足另一个 Spring Batch 类的依赖,要么是因为它确实是某个步骤的主要 ItemReader。为每个需要包装的服务编写适配器类是相当简单的,但由于这是一个常见问题,Spring Batch 提供了实现:ItemReaderAdapter 和 ItemWriterAdapter。这两个类都通过调用委托模式实现了标准的 Spring 方法,并且设置起来相当简单。
📄️ 防止状态持久化
默认情况下,所有 ItemReader 和 ItemWriter 实现都会在提交前将其当前状态存储在 ExecutionContext 中。然而,这并非总是期望的行为。例如,许多开发者选择通过使用处理指示器使其数据库读取器具备\"可重新运行\"的能力。他们会在输入数据中添加一个额外列来指示记录是否已被处理。当读取(或写入)特定记录时,已处理标志会从 false 翻转为 true。随后 SQL 语句的 where 子句中可以包含额外条件,例如 where PROCESSED\_IND = false,从而确保在重启时仅返回未处理的记录。在此场景中,最好不存储任何状态(例如当前行号),因为重启时这些状态无关紧要。因此,所有读取器和写入器都包含 'saveState' 属性。
📄️ 创建自定义 ItemReader 和 ItemWriter
到目前为止,本章已经讨论了Spring Batch中读取和写入的基本契约以及一些常见的实现方式。然而,这些内容都相当通用,许多潜在场景可能无法通过开箱即用的实现来覆盖。本节将通过一个简单示例,展示如何创建自定义的ItemReader和ItemWriter实现,并正确实现它们的契约。该ItemReader还实现了ItemStream接口,以说明如何使读取器或写入器具备可重启能力。
📄️ Item Reader 和 Writer 实现
在本节中,我们将向您介绍之前章节中尚未讨论过的读取器和写入器。