Spring Batch 快速指南



Spring Batch - 概述

批处理是一种处理模式,它涉及执行一系列无需用户交互的自动化复杂作业。批处理处理大量数据,并运行很长时间。

许多企业应用程序需要处理海量数据才能执行涉及以下操作:

  • 基于时间的事件,例如定期计算。

  • 在大型数据集上重复处理的定期应用程序。

  • 处理和验证以事务方式提供的数据的应用程序。

因此,批处理用于企业应用程序中执行此类事务。

什么是 Spring Batch?

Spring Batch 是一个轻量级框架,用于开发企业应用程序中使用的批处理应用程序

除了批量处理外,此框架还提供以下功能:

  • 包括日志记录和跟踪
  • 事务管理
  • 作业处理统计
  • 作业重启
  • 跳过和资源管理

您还可以使用其分区技术扩展 Spring Batch 应用程序。

Spring Batch 的特性

以下是 Spring Batch 的显著特性:

  • 灵活的 - Spring Batch 应用程序很灵活。您只需更改 XML 文件即可更改应用程序中的处理顺序。

  • 可维护性 - Spring Batch 应用程序易于维护。Spring Batch 作业包含步骤,每个步骤都可以解耦、测试和更新,而不会影响其他步骤。

  • 可扩展性 - 使用分区技术,您可以扩展 Spring Batch 应用程序。这些技术允许您:

    • 并行执行作业的步骤。

    • 并行执行单个线程。

  • 可靠性 - 如果发生任何故障,您可以通过解耦步骤从停止的地方重新启动作业。

  • 支持多种文件格式 - Spring Batch 支持大量读取器和写入器,例如 XML、平面文件、CSV、MYSQL、Hibernate、JDBC、Mongo、Neo4j 等。

  • 多种启动作业的方式 - 您可以使用 Web 应用程序、Java 程序、命令行等启动 Spring Batch 作业。

除此之外,Spring Batch 应用程序还支持:

  • 失败后自动重试。

  • 在批处理执行期间和完成批处理后跟踪状态和统计信息。

  • 运行并发作业。

  • 日志记录、资源管理、跳过和重新启动处理等服务。

Spring Batch - 环境配置

在本节中,我们将解释如何在 Eclipse IDE 中设置 Spring Batch 环境。在进行安装之前,请确保您已经在系统中安装了 Eclipse。如果没有,请下载并在您的系统中安装 Eclipse。

有关 Eclipse 的更多信息,请参阅我们的Eclipse 教程。

在 Eclipse 上设置 Spring Batch

按照以下步骤在 Eclipse 上设置 Spring Batch 环境。

步骤 1 - 安装 Eclipse 并创建一个新项目,如下面的屏幕截图所示。

New Project

步骤 2 - 创建一个示例 Spring Batch 项目,如下所示。

Project Name

步骤 3 - 右键单击项目,并将其转换为 Maven 项目,如下所示。将其转换为 Maven 项目后,它将为您提供一个Pom.xml 文件,您需要在其中提及所需的依赖项。之后,这些依赖项的jar 文件将自动下载到您的项目中。

Configure

步骤 4 - 现在,在项目的pom.xml 中,复制并粘贴以下内容(Spring Batch 应用程序的依赖项),然后刷新项目。

<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 
   http://maven.apache.org/maven-v4_0_0.xsd"> 
   <modelVersion>4.0.0</modelVersion> 
   <groupId>com.tutorialspoint</groupId> 
   <artifactId>SpringBatchSample</artifactId> 
   <packaging>jar</packaging> 
   <version>1.0-SNAPSHOT</version> 
   <name>SpringBatchExample</name>
   <url>http://maven.apache.org</url>  

   <properties> 
      <jdk.version>1.8</jdk.version> 
      <spring.version>5.3.14</spring.version> 
      <spring.batch.version>4.3.4</spring.batch.version> 
      <mysql.driver.version>5.1.25</mysql.driver.version> 
      <junit.version>4.11</junit.version> 
   </properties>  

   <dependencies> 
      <!-- Spring Core --> 
      <dependency> 
         <groupId>org.springframework</groupId> 
         <artifactId>spring-core</artifactId> 
         <version>${spring.version}</version> 
      </dependency>  

      <!-- Spring jdbc, for database --> 
      <dependency> 
         <groupId>org.springframework</groupId> 
         <artifactId>spring-jdbc</artifactId> 
         <version>${spring.version}</version> 
      </dependency>  

      <!-- Spring XML to/back object --> 
      <dependency> 
         <groupId>org.springframework</groupId> 
         <artifactId>spring-oxm</artifactId> 
         <version>${spring.version}</version> 
      </dependency>  

      <!-- MySQL database driver --> 
      <dependency> 
         <groupId>mysql</groupId> 
         <artifactId>mysql-connector-java</artifactId>
         <version>${mysql.driver.version}</version> 
      </dependency>  

      <!-- Spring Batch dependencies --> 
      <dependency> 
         <groupId>org.springframework.batch</groupId> 
         <artifactId>spring-batch-core</artifactId> 
         <version>${spring.batch.version}</version> 
      </dependency> 

      <dependency> 
         <groupId>org.springframework.batch</groupId> 
         <artifactId>spring-batch-infrastructure</artifactId> 
         <version>${spring.batch.version}</version> 
      </dependency>  

      <!-- Spring Batch unit test --> 
      <dependency> 
         <groupId>org.springframework.batch</groupId> 
         <artifactId>spring-batch-test</artifactId> 
         <version>${spring.batch.version}</version> 
      </dependency>  

      <!-- Junit --> 
      <dependency> 
         <groupId>junit</groupId> 
         <artifactId>junit</artifactId> 
         <version>${junit.version}</version> 
         <scope>test</scope> 
      </dependency> 
   </dependencies> 

   <build> 
      <finalName>spring-batch</finalName> 
      <plugins> 
         <plugin> 
            <groupId>org.apache.maven.plugins</groupId> 
            <artifactId>maven-eclipse-plugin</artifactId>
            <version>2.9</version> 
            <configuration> 
               <downloadSources>true</downloadSources> 
               <downloadJavadocs>false</downloadJavadocs> 
            </configuration> 
         </plugin> 
   
         <plugin> 
            <groupId>org.apache.maven.plugins</groupId> 
            <artifactId>maven-compiler-plugin</artifactId> 
            <version>2.3.2</version> 
            <configuration> 
               <source>${jdk.version}</source> 
               <target>${jdk.version}</target> 
            </configuration> 
         </plugin> 
      </plugins> 
   </build> 
</project>    

Spring Batch - 架构

以下是 Spring Batch 架构的图示。如图所示,该架构包含三个主要组件,即应用程序、批处理核心批处理基础结构

Architecture

应用程序 - 此组件包含所有作业以及我们使用 Spring Batch 框架编写的代码。

批处理核心 - 此组件包含控制和启动批处理作业所需的所有 API 类。

批处理基础结构 - 此组件包含应用程序和批处理核心组件使用的读取器、写入器和服务。

Spring Batch 的组件

下图显示了 Spring Batch 的不同组件以及它们如何相互连接。

Components

作业 (Job)

在 Spring Batch 应用程序中,作业是要执行的批处理过程。它从开始到结束无中断地运行。此作业进一步细分为步骤(或作业包含步骤)。

我们将在 Spring Batch 中使用 XML 文件或 Java 类配置作业。以下是 Spring Batch 中作业的 XML 配置。

<job id = "jobid"> 
   <step id = "step1" next = "step2"/> 
   <step id = "step2" next = "step3"/> 
   <step id = "step3"/> 
</job>

批处理作业在<job></job>标签内配置。它有一个名为id的属性。在这些标签内,我们定义步骤的定义和顺序。

可重启性 (Restartable) - 通常,当作业正在运行并且我们尝试再次启动它时,这被认为是重启,它将再次启动。为避免这种情况,您需要将restartable的值设置为false,如下所示。

<job id = "jobid" restartable = "false" >

</job>

步骤 (Step)

步骤是作业的独立部分,其中包含定义和执行作业(其部分)所需的信息。

如图所示,每个步骤都由一个 ItemReader、ItemProcessor(可选)和一个 ItemWriter 组成。一个作业可以包含一个或多个步骤

读取器、写入器和处理器

项目读取器 (Item reader) 将数据从特定来源读入 Spring Batch 应用程序,而项目写入器 (Item writer) 将数据从 Spring Batch 应用程序写入特定目标。

项目处理器 (Item processor) 是一个包含处理代码的类,该代码处理读入 Spring Batch 的数据。如果应用程序读取“n”条记录,则处理器中的代码将对每条记录执行。

如果没有提供读取器和写入器,则任务 (Tasklet) 将充当 SpringBatch 的处理器。它只处理单个任务。例如,如果我们正在编写一个包含简单步骤的作业,我们从中读取 MySQL 数据库中的数据,处理它并将其写入文件(平面文件),那么我们的步骤将使用:

  • 一个读取器,从 MySQL 数据库读取。

  • 一个写入器,写入平面文件。

  • 一个自定义处理器,根据我们的意愿处理数据。

<job id = "helloWorldJob"> 
   <step id = "step1"> 
      <tasklet> 
         <chunk reader = "mysqlReader" writer = "fileWriter" 
            processor = "CustomitemProcessor" ></chunk> 
      </tasklet> 
   </step> 
</ job>

Spring Batch 提供了很长的读取器写入器列表。使用这些预定义的类,我们可以为它们定义 bean。我们将在接下来的章节中更详细地讨论读取器写入器

作业仓库 (JobRepository)

Spring Batch 中的作业仓库为 JobLauncher、Job 和 Step 实现提供创建、检索、更新和删除 (CRUD) 操作。我们将在 XML 文件中定义作业仓库,如下所示。

<job-repository id = "jobRepository"/> 

除了id之外,还有一些其他(可选)选项可用。以下是具有所有选项及其默认值的作业仓库配置。

<job-repository id = "jobRepository" 
   data-source = "dataSource" 
   transaction-manager = "transactionManager" 
   isolation-level-for-create = "SERIALIZABLE" 
   table-prefix = "BATCH_" 
   max-varchar-length = "1000"/>

内存中仓库 (In-Memory Repository) -如果您不想将 Spring Batch 的域对象持久化到数据库中,您可以配置 jobRepository 的内存版本,如下所示。

<bean id = "jobRepository" 
   class = "org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean ">
   <property name = "transactionManager" ref = "transactionManager"/>
</bean>

作业启动器 (JobLauncher)

JobLauncher 是一个接口,它使用给定的参数集启动 Spring Batch 作业。SampleJoblauncher 是实现JobLauncher接口的类。以下是 JobLauncher 的配置。

<bean id = "jobLauncher" 
   class = "org.springframework.batch.core.launch.support.SimpleJobLauncher"> 
   <property name = "jobRepository" ref = "jobRepository" /> 
</bean>

作业实例 (JobInstance)

JobInstance 代表作业的逻辑运行;它在我们运行作业时创建。每个作业实例都通过作业的名称以及运行时传递给它的参数来区分。

如果 JobInstance 执行失败,可以再次执行相同的 JobInstance。因此,每个 JobInstance 可以有多个作业执行。

作业执行和步骤执行 (JobExecution and StepExecution)

JobExecution 和 StepExecution 是作业/步骤执行的表示。它们包含作业/步骤的运行信息,例如启动时间(作业/步骤)、结束时间(作业/步骤)。

Spring Batch - 应用

本教程中的几乎所有示例都包含以下文件:

  • 配置文件(XML 文件)
  • 任务/处理器(Java 类)
  • 带有 setter 和 getter 的 Java 类(Java 类(bean))
  • 映射器类(Java 类)
  • 启动器类(Java 类)

配置文件

配置文件(XML)包含以下内容:

  • 作业步骤定义。

  • 定义读取器写入器的 bean。

  • JobLauncher、JobRepository、事务管理器和数据源等组件的定义。

在我们的示例中,为了更好地理解,我们将其分为两个文件:job.xml 文件(定义作业、步骤、读取器和写入器)和context.xml 文件(作业启动器、作业仓库、事务管理器和数据源)。

映射器类

根据读取器,映射器类实现诸如行映射器字段集映射器等接口。它包含从读取器获取数据并将其设置为具有settergetter方法(Java Bean)的 Java 类的代码。

Java Bean 类

具有settergetter(Java bean)的 Java 类表示具有多个值的数。它充当辅助类。我们将数据从一个组件(读取器、写入器、处理器)传递到另一个组件,以该类的对象形式。

任务/处理器

Tasklet/处理器类包含 Spring Batch 应用程序的处理代码。处理器是一个类,它接受包含读取数据的对象,处理它并返回处理后的数据(以对象的形式)。

启动器类

此类(App.java)包含启动 Spring Batch 应用程序的代码。

Application

Spring Batch - 配置

在编写 Spring Batch 应用程序时,我们将使用 Spring Batch 命名空间中提供的 XML 标签配置作业、步骤、JobLauncher、JobRepository、事务管理器、读取器和写入器。因此,您需要在 XML 文件中包含此命名空间,如下所示。

<beans xmlns = "http://www.springframework.org/schema/beans" 
   xmlns:batch = "http://www.springframework.org/schema/batch" 
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" 
   xsi:schemaLocation = "http://www.springframework.org/schema/batch 

   http://www.springframework.org/schema/batch/spring-batch-2.2.xsd 
   http://www.springframework.org/schema/bean   
   http://www.springframework.org/schema/beans/spring-beans-3.2.xsd"> 

在以下部分,我们将讨论 Spring Batch 命名空间中提供的各种标签、它们的属性和示例。

作业 (Job)

此标签用于定义/配置 SpringBatch 的作业。它包含一组步骤,可以使用 JobLauncher 启动。

此标签具有如下所示的 2 个属性:

序号 属性和描述
1

Id

这是作业的 Id,必须为此属性指定值。

2

restartable

此属性用于指定作业是否可重启。此属性是可选的。

以下是 SpringBatch 作业的 XML 配置。

<job id = "jobid" restartable = "false" > 
   . . . . . . . .  
   . . . . . . . .  
   . . . . . . . . // Step definitions 
</job>

步骤 (Step)

此标签用于定义/配置Spring Batch作业的步骤。它具有以下三个属性:

序号 属性和描述
1

Id

这是作业的 Id,必须为此属性指定值。

2

next

它是指定下一步的快捷方式。

3

parent

它用于指定应从中继承配置的父bean的名称。

以下是Spring Batch步骤的XML配置。

<job id = "jobid"> 
   <step id = "step1" next = "step2"/> 
   <step id = "step2" next = "step3"/> 
   <step id = "step3"/> 
</job>

Chunk

此标签用于定义/配置tasklet的一个chunk。它具有以下四个属性:

序号 属性和描述
1

reader

它表示项目读取器bean的名称。它接受类型为org.springframework.batch.item.ItemReader的值。

2

writer

它表示项目写入器bean的名称。它接受类型为org.springframework.batch.item.ItemWriter的值。

3

processor

它表示项目处理器bean的名称。它接受类型为org.springframework.batch.item.ItemProcessor的值。

4

commit-interval

它用于指定在提交事务之前要处理的项目数量。

以下是Spring Batch的chunk的XML配置。

<batch:step id = "step1"> 
   <batch:tasklet> 
      <batch:chunk reader = "xmlItemReader" 
         writer = "mysqlItemWriter" processor = "itemProcessor" commit-interval = "10"> 
      </batch:chunk> 
   </batch:tasklet> 
</batch:step> 

作业仓库 (JobRepository)

JobRepository Bean用于使用关系数据库配置JobRepository。此bean与类型为org.springframework.batch.core.repository.JobRepository的类关联。

序号 属性和描述
1

dataSource

它用于指定定义数据源的bean名称。

2

transactionManager

它用于指定定义事务管理器的bean名称。

3

databaseType

它指定作业存储库中使用的关系数据库的类型。

以下是JobRepository的示例配置。

<bean id = "jobRepository" 
   class = "org.springframework.batch.core.repository.support.JobRepositoryFactoryBean"> 
   <property name = "dataSource" ref = "dataSource" /> 
   <property name = "transactionManager" ref="transactionManager" /> 
   <property name = "databaseType" value = "mysql" /> 
</bean> 

作业启动器 (JobLauncher)

JobLauncher bean用于配置JobLauncher。它与类org.springframework.batch.core.launch.support.SimpleJobLauncher(在我们的程序中)关联。此bean具有一个名为jobrepository的属性,它用于指定定义jobrepository的bean的名称。

以下是jobLauncher的示例配置。

<bean id = "jobLauncher" 
   class = "org.springframework.batch.core.launch.support.SimpleJobLauncher"> 
   <property name = "jobRepository" ref = "jobRepository" /> 
</bean>

TransactionManager

TransactionManager bean用于使用关系数据库配置TransactionManager。此bean与类型为org.springframework.transaction.platform.TransactionManager的类关联。

<bean id = "transactionManager"
   class = "org.springframework.batch.support.transaction.ResourcelessTransactionManager" />

DataSource

datasource bean用于配置Datasource。此bean与类型为org.springframework.jdbc.datasource.DriverManagerDataSource的类关联。

序号 属性和描述
1

driverClassName

这指定用于连接数据库的驱动程序的类名。

2

url

这指定数据库的URL。

3

username

这指定用于连接数据库的用户名。

4

password

这指定用于连接数据库的密码。

以下是datasource的示例配置。

<bean id = "dataSource" 
   class = "org.springframework.jdbc.datasource.DriverManagerDataSource"> 
   <property name = "driverClassName" value = "com.mysql.cj.jdbc.Driver" /> 
   <property name = "url" value = "jdbc:mysql://127.0.0.1:3306/details" /> 
   <property name = "username" value = "myuser" /> 
   <property name = "password" value = "password" /> 
</bean> 

Spring Batch - 读取器、写入器和处理器

Item Reader从特定来源读取数据到Spring Batch应用程序,而Item Writer将数据从Spring Batch应用程序写入特定目标。

Item processor是一个包含处理代码的类,该代码处理读取到Spring Batch中的数据。如果应用程序读取n条记录,则处理器中的代码将对每条记录执行。

chunktasklet的子元素。它用于执行读取、写入和处理操作。我们可以在步骤中使用此元素配置读取器、写入器和处理器,如下所示。

<batch:job id = "helloWorldJob"> 
   <batch:step id = "step1"> 
      <batch:tasklet> 
         <batch:chunk reader = "cvsFileItemReader" writer = "xmlItemWriter" 
            processor = "itemProcessor" commit-interval = "10"> 
         </batch:chunk> 
      </batch:tasklet> 
   </batch:step> 
</batch:job>

Spring Batch提供读取器和写入器,用于从各种文件系统/数据库读取和写入数据,例如MongoDB、Neo4j、MySQL、XML、平面文件、CSV等。

要在应用程序中包含读取器,需要为该读取器定义一个bean,为bean中的所有必需属性提供值,并将此类bean的id作为值传递给chunk元素的reader属性(writer相同)。

ItemReader

它是步骤(批处理过程的一个步骤)中读取数据的实体。ItemReader一次读取一个项目。Spring Batch提供了一个接口ItemReader。所有读取器都实现此接口。

以下是Spring Batch提供的一些预定义ItemReader类,用于从各种来源读取数据。

读取器 用途
FlatFIleItemReader 从平面文件读取数据。
StaxEventItemReader 从XML文件读取数据。
StoredProcedureItemReader 从数据库的存储过程中读取数据。
JDBCPagingItemReader 从关系数据库读取数据。
MongoItemReader 从MongoDB读取数据。
Neo4jItemReader 从Neo4jItemReader读取数据。

我们需要通过创建bean来配置ItemReaders。以下是读取XML文件数据的StaxEventItemReader示例。

<bean id = "mysqlItemWriter" 
   class = "org.springframework.batch.item.xml.StaxEventItemWriter"> 
   <property name = "resource" value = "file:xml/outputs/userss.xml" /> 
   <property name = "marshaller" ref = "reportMarshaller" /> 
   <property name = "rootTagName" value = "Tutorial" /> 
</bean> 

<bean id = "reportMarshaller" 
   class = "org.springframework.oxm.jaxb.Jaxb2Marshaller"> 
   <property name = "classesToBeBound"> 
      <list> 
         <value>Tutorial</value> 
      </list> 
   </property> 
</bean> 

如观察到的,在配置时,我们需要指定所需读取器的相应类名,并且需要为所有必需的属性提供值。

ItemWriter

它是批处理过程步骤中写入数据的元素。ItemWriter一次写入一个项目。Spring Batch提供了一个接口ItemWriter。所有写入器都实现此接口。

以下是Spring Batch提供的一些预定义ItemWriter类,用于从各种来源读取数据。

写入器 用途
FlatFIleItemWriter 将数据写入平面文件。
StaxEventItemWriter 将数据写入XML文件。
StoredProcedureItemWriter 将数据写入数据库的存储过程。
JDBCPagingItemWriter 将数据写入关系数据库。
MongoItemWriter 将数据写入MongoDB。
Neo4jItemWriter 将数据写入Neo4j。

同样,我们需要通过创建bean来配置ItemWriters。以下是将数据写入MySQL数据库的JdbcCursorItemReader示例。

<bean id = "dbItemReader"
   class = "org.springframework.batch.item.database.JdbcCursorItemReader" scope = "step">
   <property name = "dataSource" ref = "dataSource" />
   <property name = "sql" value = "select * from tutorialsdata" />
   <property name = "rowMapper">
      <bean class = "TutorialRowMapper" /> 
   </property>
</bean>

Item Processor

ItemProcessor:ItemProcessor用于处理数据。当给定项目无效时,它返回null,否则它处理给定项目并返回处理后的结果。接口ItemProcessor<I,O>表示处理器。

Tasklet类 - 当没有给出readerwriter时,Tasklet充当SpringBatch的处理器。它只处理单个任务。

我们可以通过实现包org.springframework.batch.item.ItemProcessor的接口ItemProcessor来定义自定义项目处理器。此ItemProcessor类接受一个对象,处理数据并将处理后的数据作为另一个对象返回。

在批处理过程中,如果读取了“n”条记录或数据元素,则对于每条记录,它将读取数据、处理数据并将数据写入写入器。为了处理数据,它依赖于传递的处理器。

例如,假设您编写了加载特定PDF文档、创建新页面、以表格格式将数据项写入PDF的代码。如果执行此应用程序,它将从XML文档读取所有数据项,将它们存储在MySQL数据库中,并将它们打印在给定PDF文档的各个页面中。

示例

以下是一个示例ItemProcessor类。

import org.springframework.batch.item.ItemProcessor;  

public class CustomItemProcessor implements ItemProcessor<Tutorial, Tutorial> {  
   
   @Override 
   public Tutorial process(Tutorial item) throws Exception {  
      System.out.println("Processing..." + item); 
      return item; 
   } 
} 

Spring Batch - 基础应用

本章向您展示基本的Spring Batch应用程序。它将简单地执行一个tasklet来显示一条消息。

我们的Spring Batch应用程序包含以下文件:

  • 配置文件 - 这是一个XML文件,我们在这里定义作业和作业的步骤。(如果应用程序也包含读取器和写入器,则读取器写入器的配置也包含在此文件中。)

  • Context.xml - 在此文件中,我们将定义诸如作业存储库、作业启动器和事务管理器之类的bean。

  • Tasklet类 - 在此类中,我们将编写作业处理代码(在本例中,它显示一条简单的消息)

  • 启动器类 - 在此类中,我们将通过运行作业启动器来启动批处理应用程序。

创建项目

Spring Batch - 环境章节所述,创建一个新的Maven项目。

pom.xml

以下是此Maven项目中使用的pom.xml文件的内容。

<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 
   http://maven.apache.org/maven-v4_0_0.xsd"> 
   <modelVersion>4.0.0</modelVersion> 
   <groupId>com.tutorialspoint</groupId> 
   <artifactId>SpringBatchSample</artifactId> 
   <packaging>jar</packaging> 
   <version>1.0-SNAPSHOT</version> 
   <name>SpringBatchExample</name>
   <url>http://maven.apache.org</url>  

   <properties> 
      <jdk.version>21</jdk.version> 
      <spring.version>5.3.14</spring.version> 
      <spring.batch.version>4.3.4</spring.batch.version> 
      <mysql.driver.version>5.1.25</mysql.driver.version> 
      <junit.version>4.11</junit.version> 
   </properties>  

   <dependencies> 
      <!-- Spring Core --> 
      <dependency> 
         <groupId>org.springframework</groupId> 
         <artifactId>spring-core</artifactId> 
         <version>${spring.version}</version> 
      </dependency>  

      <!-- Spring jdbc, for database --> 
      <dependency> 
         <groupId>org.springframework</groupId> 
         <artifactId>spring-jdbc</artifactId> 
         <version>${spring.version}</version> 
      </dependency>  

      <!-- Spring XML to/back object --> 
      <dependency> 
         <groupId>org.springframework</groupId> 
         <artifactId>spring-oxm</artifactId> 
         <version>${spring.version}</version> 
      </dependency>  

      <!-- MySQL database driver --> 
      <dependency> 
         <groupId>mysql</groupId> 
         <artifactId>mysql-connector-java</artifactId>
         <version>${mysql.driver.version}</version> 
      </dependency>  

      <!-- Spring Batch dependencies --> 
      <dependency> 
         <groupId>org.springframework.batch</groupId> 
         <artifactId>spring-batch-core</artifactId> 
         <version>${spring.batch.version}</version> 
      </dependency> 

      <dependency> 
         <groupId>org.springframework.batch</groupId> 
         <artifactId>spring-batch-infrastructure</artifactId> 
         <version>${spring.batch.version}</version> 
      </dependency>  

      <!-- Spring Batch unit test --> 
      <dependency> 
         <groupId>org.springframework.batch</groupId> 
         <artifactId>spring-batch-test</artifactId> 
         <version>${spring.batch.version}</version> 
      </dependency>  

      <!-- Junit --> 
      <dependency> 
         <groupId>junit</groupId> 
         <artifactId>junit</artifactId> 
         <version>${junit.version}</version> 
         <scope>test</scope> 
      </dependency> 
   </dependencies> 

   <build> 
      <finalName>spring-batch</finalName> 
      <plugins> 
         <plugin> 
            <groupId>org.apache.maven.plugins</groupId> 
            <artifactId>maven-eclipse-plugin</artifactId>
            <version>2.9</version> 
            <configuration> 
               <downloadSources>true</downloadSources> 
               <downloadJavadocs>false</downloadJavadocs> 
            </configuration> 
         </plugin> 
   
         <plugin> 
            <groupId>org.apache.maven.plugins</groupId> 
            <artifactId>maven-compiler-plugin</artifactId> 
            <version>2.3.2</version> 
            <configuration> 
               <source>${jdk.version}</source> 
               <target>${jdk.version}</target> 
            </configuration> 
         </plugin> 
      </plugins> 
   </build> 
</project>    

jobConfig.xml

以下是我们的示例Spring Batch应用程序的配置文件。在Maven项目的src > main > resources文件夹中创建此文件。

<beans xmlns = "http://www.springframework.org/schema/beans" 
   xmlns:batch = "http://www.springframework.org/schema/batch" 
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" 
   xsi:schemaLocation = "http://www.springframework.org/schema/batch 
      http://www.springframework.org/schema/batch/spring-batch-2.2.xsd
      http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans-3.2.xsd "> 
   <import resource="context.xml" />      
   <!-- Defining a bean --> 
   <bean id = "tasklet" class = "MyTasklet" />  
   <!-- Defining a job--> 
   <batch:job id = "helloWorldJob">  
      <!-- Defining a Step --> 
      <batch:step id = "step1"> 
         <tasklet ref = "tasklet"/>   
      </batch:step>    
   </batch:job>  
</beans> 

Context.xml

以下是我们的Spring Batch应用程序的context.xml。在Maven项目的src > main > resources文件夹中创建此文件。

<beans xmlns = "http://www.springframework.org/schema/beans" 
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" 
   xsi:schemaLocation = "http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">  
   
   <bean id = "jobRepository"   
      class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean"> 
      <property name = "transactionManager" ref = "transactionManager" /> 
   </bean>     
     
   <bean id = "transactionManager" 
      class = "org.springframework.batch.support.transaction.ResourcelessTransactionManager" />  
   <bean id = "jobLauncher" 
      class = "org.springframework.batch.core.launch.support.SimpleJobLauncher"> 
      <property name = "jobRepository" ref = "jobRepository" /> 
   </bean> 
</beans> 

Tasklet.java

以下是显示简单消息的Tasklet类。在Maven项目的src > main > java文件夹中创建此类。

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;  

public class MyTasklet implements Tasklet { 
   
   @Override 
   public RepeatStatus execute(StepContribution arg0, ChunkContext arg1) throws Exception {  
      System.out.println("Hello This is a sample example of spring batch"); 
      return RepeatStatus.FINISHED; 
   } 
} 

App.java

以下是启动批处理过程的代码。在Maven项目的src > main > java文件夹中创建此类。

import org.springframework.batch.core.Job; 
import org.springframework.batch.core.JobExecution; 
import org.springframework.batch.core.JobParameters; 
import org.springframework.batch.core.launch.JobLauncher; 
import org.springframework.context.ApplicationContext; 
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App { 
   public static void main(String[] args)throws Exception { 
  
      String[] springConfig  =  {"jobConfig.xml"};  
      
      // Creating the application context object  
      ApplicationContext context = new ClassPathXmlApplicationContext(springConfig); 
      
      // Creating the job launcher 
      JobLauncher jobLauncher = (JobLauncher) context.getBean("jobLauncher"); 
  
      // Creating the job 
      Job job = (Job) context.getBean("helloWorldJob"); 
  
      // Executing the JOB 
      JobExecution execution = jobLauncher.run(job, new JobParameters()); 
      System.out.println("Exit Status : " + execution.getStatus()); 
   }    
}

输出

在Eclipse中右键单击项目,选择以...运行 -> Maven构建。将目标设置为clean package并运行项目。您将看到以下输出。

[INFO] Scanning for projects...
[INFO] 
[INFO] [1m----------------< [0;36mcom.tutorialspoint:SpringBatchSample[0;1m >----------------[m
[INFO] [1mBuilding SpringBatchExample 1.0-SNAPSHOT[m
[INFO]   from pom.xml
[INFO] [1m--------------------------------[ jar ]---------------------------------[m
[INFO] 
[INFO] [1m--- [0;32mclean:3.2.0:clean[m [1m(default-clean)[m @ [36mSpringBatchSample[0;1m ---[m
[INFO] Deleting C:\Users\Tutorialspoint\eclipse-workspace\SpringBatchSample\target
[INFO] 
[INFO] [1m--- [0;32mresources:3.3.1:resources[m [1m(default-resources)[m @ [36mSpringBatchSample[0;1m ---[m
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 3 resources from src\main\resources to target\classes
[INFO] 
[INFO] [1m--- [0;32mcompiler:2.3.2:compile[m [1m(default-compile)[m @ [36mSpringBatchSample[0;1m ---[m
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 5 source files to C:\Users\Tutorialspoint\eclipse-workspace\SpringBatchSample\target\classes
[INFO] 
[INFO] [1m--- [0;32mresources:3.3.1:testResources[m [1m(default-testResources)[m @ [36mSpringBatchSample[0;1m ---[m
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource from src\test\resources to target\test-classes
[INFO] 
[INFO] [1m--- [0;32mcompiler:2.3.2:testCompile[m [1m(default-testCompile)[m @ [36mSpringBatchSample[0;1m ---[m
[INFO] Nothing to compile - all classes are up to date
[INFO] 
[INFO] [1m--- [0;32msurefire:3.1.2:test[m [1m(default-test)[m @ [36mSpringBatchSample[0;1m ---[m
[INFO] 
[INFO] [1m--- [0;32mjar:3.3.0:jar[m [1m(default-jar)[m @ [36mSpringBatchSample[0;1m ---[m
[INFO] Building jar: C:\Users\Tutorialspoint\eclipse-workspace\SpringBatchSample\target\spring-batch.jar
[INFO] [1m------------------------------------------------------------------------[m
[INFO] [1;32mBUILD SUCCESS[m
[INFO] [1m------------------------------------------------------------------------[m
[INFO] Total time:  4.426 s
[INFO] Finished at: 2024-07-30T11:10:59+05:30
[INFO] [1m------------------------------------------------------------------------

要检查上述SpringBatch程序的输出,请右键单击App.java类并选择以...运行 -> Java应用程序。它将产生以下输出:

Jul 30, 2024 11:21:25 AM org.springframework.batch.core.launch.support.SimpleJobLauncher afterPropertiesSet
INFO: No TaskExecutor has been set, defaulting to synchronous executor.
Jul 30, 2024 11:21:25 AM org.springframework.batch.core.launch.support.SimpleJobLauncher$1 run
INFO: Job: [FlowJob: [name=helloWorldJob]] launched with the following parameters: [{}]
Jul 30, 2024 11:21:25 AM org.springframework.batch.core.job.SimpleStepHandler handleStep
INFO: Executing step: [step1]
Hello This is a sample example of spring batch
Jul 30, 2024 11:21:25 AM org.springframework.batch.core.step.AbstractStep execute
INFO: Step: [step1] executed in 25ms
Jul 30, 2024 11:21:25 AM org.springframework.batch.core.launch.support.SimpleJobLauncher$1 run
INFO: Job: [FlowJob: [name=helloWorldJob]] completed with the following parameters: [{}] and the following status: [COMPLETED] in 47ms
Exit Status : COMPLETED

Spring Batch - XML 到 MySQL

在本章中,我们将创建一个使用XML读取器和MySQL写入器的Spring Batch应用程序。

读取器 - 我们在应用程序中使用的读取器是StaxEventItemReader,用于从XML文档读取数据。

创建项目

Spring Batch - 环境章节所述,创建一个新的Maven项目。

以下是我们在此应用程序中使用的输入XML文档。此文档保存指定详细信息的数据记录,例如教程ID、教程作者、教程标题、提交日期、教程图标和教程描述。

tutorial.xml

在Maven项目的src > main > resources文件夹中创建此文件。

<?xml version="1.0" encoding="UTF-8"?> 
<tutorials> 
   <tutorial>      
      <tutorial_id>1001</tutorial_id> 
      <tutorial_author>Sanjay</tutorial_author> 
      <tutorial_title>Learn Java</tutorial_title> 
      <submission_date>06-05-2007</submission_date> 
      <tutorial_icon>https://tutorialspoint.com/java/images/java-minilogo.jpg</tutorial_icon> 
      <tutorial_description>Java is a high-level programming language originally 
         developed by Sun Microsystems and released in 1995. 
         Java runs on a variety of platforms. 
         This tutorial gives a complete understanding of Java.');</tutorial_description> 
   </tutorial> 
    
   <tutorial>      
      <tutorial_id>1002</tutorial_id> 
      <tutorial_author>Abdul S</tutorial_author> 
      <tutorial_title>Learn MySQL</tutorial_title> 
      <submission_date>19-04-2007</submission_date> 
      <tutorial_icon>https://tutorialspoint.com/mysql/images/mysql-minilogo.jpg</tutorial_icon> 
      <tutorial_description>MySQL is the most popular 
         Open Source Relational SQL database management system. 
         MySQL is one of the best RDBMS being used for developing web-based software applications. 
         This tutorial will give you quick start with MySQL 
         and make you comfortable with MySQL programming.</tutorial_description> 
   </tutorial> 
    
   <tutorial>
      <tutorial_id>1003</tutorial_id> 
      <tutorial_author>Krishna Kasyap</tutorial_author> 
      <tutorial_title>Learn JavaFX</tutorial_title> 
      <submission_date>06-07-2017</submission_date> 
      <tutorial_icon>https://tutorialspoint.com/javafx/images/javafx-minilogo.jpg</tutorial_icon> 
      <tutorial_description>JavaFX is a Java library used to build Rich Internet Applications. 
         The applications developed using JavaFX can run on various devices 
         such as Desktop Computers, Mobile Phones, TVs, Tablets, etc. 
         This tutorial, discusses all the necessary elements of JavaFX that are required
         to develop effective Rich Internet Applications</tutorial_description> 
   </tutorial> 
</tutorials>

写入器 - 我们在应用程序中使用的写入器JdbcBatchItemWriter,用于将数据写入MySQL数据库。假设我们在名为“details”的数据库中创建了一个MySQL表。

CREATE TABLE details.TUTORIALS( 
   tutorial_id int(10) NOT NULL, 
   tutorial_author VARCHAR(20), 
   tutorial_title VARCHAR(50), 
   submission_date VARCHAR(20), 
   tutorial_icon VARCHAR(200), 
   tutorial_description VARCHAR(1000) 
);

处理器 - 我们在应用程序中使用的处理器是一个自定义处理器,它将每条记录的数据写入PDF文档。

在批处理过程中,如果读取了“n”条记录或数据元素,则对于每条记录,它将读取数据、处理数据并将数据写入写入器。为了处理数据,它依赖于传递的处理器。在本例中,在自定义处理器类中,我们编写了加载特定PDF文档、创建新页面、以表格格式将数据项写入PDF的代码。

最后,如果您执行此应用程序,它将读取XML文档中的所有数据项,并将它们存储到MySQL数据库中,然后在给定的PDF文档中逐页打印它们。

pom.xml

以下是此Maven项目中使用的pom.xml文件的内容。

<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 
   http://maven.apache.org/maven-v4_0_0.xsd"> 
   <modelVersion>4.0.0</modelVersion> 
   <groupId>com.tutorialspoint</groupId> 
   <artifactId>SpringBatchSample</artifactId> 
   <packaging>jar</packaging> 
   <version>1.0-SNAPSHOT</version> 
   <name>SpringBatchExample</name>
   <url>http://maven.apache.org</url>  

   <properties> 
      <jdk.version>21</jdk.version> 
      <spring.version>5.3.14</spring.version> 
      <spring.batch.version>4.3.4</spring.batch.version> 
      <mysql.driver.version>8.4.0</mysql.driver.version> 
      <junit.version>4.11</junit.version> 
      <pdf.version>2.0.32</pdf.version>
      <xstream.version>1.4.17</xstream.version>
   </properties>  

   <dependencies> 
      <!-- Spring Core --> 
      <dependency> 
         <groupId>org.springframework</groupId> 
         <artifactId>spring-core</artifactId> 
         <version>${spring.version}</version> 
      </dependency>  

      <!-- Spring jdbc, for database --> 
      <dependency> 
         <groupId>org.springframework</groupId> 
         <artifactId>spring-jdbc</artifactId> 
         <version>${spring.version}</version> 
      </dependency>  

      <!-- Spring XML to/back object --> 
      <dependency> 
         <groupId>org.springframework</groupId> 
         <artifactId>spring-oxm</artifactId> 
         <version>${spring.version}</version> 
      </dependency>  

      <!-- MySQL database driver --> 
      <dependency>
         <groupId>com.mysql</groupId>
         <artifactId>mysql-connector-j</artifactId>
         <version>${mysql.driver.version}</version>
      </dependency>  

      <!-- Spring Batch dependencies --> 
      <dependency> 
         <groupId>org.springframework.batch</groupId> 
         <artifactId>spring-batch-core</artifactId> 
         <version>${spring.batch.version}</version> 
      </dependency> 

      <dependency> 
         <groupId>org.springframework.batch</groupId> 
         <artifactId>spring-batch-infrastructure</artifactId> 
         <version>${spring.batch.version}</version> 
      </dependency>  

      <!-- Spring Batch unit test --> 
      <dependency> 
         <groupId>org.springframework.batch</groupId> 
         <artifactId>spring-batch-test</artifactId> 
         <version>${spring.batch.version}</version> 
      </dependency>  

      <!-- Junit --> 
      <dependency> 
         <groupId>junit</groupId> 
         <artifactId>junit</artifactId> 
         <version>${junit.version}</version> 
         <scope>test</scope> 
      </dependency> 

      <!-- pdfbox -->
      <dependency>
         <groupId>org.apache.pdfbox</groupId>
         <artifactId>pdfbox</artifactId>
         <version>${pdf.version}</version>
      </dependency>
	  
      <!-- xstream -->
      <dependency>
         <groupId>com.thoughtworks.xstream</groupId>
         <artifactId>xstream</artifactId>
         <version>${xstream.version}</version>
      </dependency>

   </dependencies> 

   <build> 
      <finalName>spring-batch</finalName> 
      <plugins> 
         <plugin> 
            <groupId>org.apache.maven.plugins</groupId> 
            <artifactId>maven-eclipse-plugin</artifactId>
            <version>2.9</version> 
            <configuration> 
               <downloadSources>true</downloadSources> 
               <downloadJavadocs>false</downloadJavadocs> 
            </configuration> 
         </plugin> 
   
         <plugin> 
            <groupId>org.apache.maven.plugins</groupId> 
            <artifactId>maven-compiler-plugin</artifactId> 
            <version>2.3.2</version> 
            <configuration> 
               <source>${jdk.version}</source> 
               <target>${jdk.version}</target> 
            </configuration> 
         </plugin> 
      </plugins> 
   </build> 
</project>    

jobConfig.xml

以下是我们的示例Spring Batch应用程序的配置文件。在这个文件中,我们将定义作业和步骤。除此之外,我们还定义了ItemReader、ItemProcessor和ItemWriter的bean。(在这里,我们将它们与各自的类关联,并传递所需属性的值来配置它们。)

在Maven项目的src > main > resources文件夹中创建此文件。

<beans xmlns = "http://www.springframework.org/schema/beans" 
   xmlns:batch = "http://www.springframework.org/schema/batch" 
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" 
   xmlns:util = "http://www.springframework.org/schema/util" 
   xsi:schemaLocation = "http://www.springframework.org/schema/batch 
    
      http://www.springframework.org/schema/batch/spring-batch-2.2.xsd 
      http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 
      http://www.springframework.org/schema/util     
      http://www.springframework.org/schema/util/spring-util-3.0.xsd ">  
  
   <import resource = "context.xml" /> 
  
   <bean id = "itemProcessor" class = "CustomItemProcessor" /> 
   <batch:job id = "helloWorldJob"> 
      <batch:step id = "step1"> 
         <batch:tasklet>           
            <batch:chunk reader = "xmlItemReader" writer = "mysqlItemWriter" processor = "itemProcessor" commit-interval="1">
            </batch:chunk> 
         </batch:tasklet> 
      </batch:step> 
   </batch:job> 
                
   <bean id = "xmlItemReader" 
      class = "org.springframework.batch.item.xml.StaxEventItemReader"> 
      <property name = "fragmentRootElementName" value = "tutorial" /> 
      <property name = "resource" value = "classpath:tutorial.xml" /> 
      <property name = "unmarshaller" ref = "customUnMarshaller" /> 
   </bean> 
      
   <bean id = "customUnMarshaller" class = "org.springframework.oxm.xstream.XStreamMarshaller">
      <property name = "aliases"> 
         <util:map id = "aliases"> 
            <entry key = "tutorial" value = "Tutorial" />            
         </util:map> 
      </property> 
   </bean>  
   <bean id = "mysqlItemWriter" class = "org.springframework.batch.item.database.JdbcBatchItemWriter"> 
      <property name = "dataSource" ref = "dataSource" /> 
      <property name = "sql"> 
         <value> 
            <![CDATA[insert into details.tutorials (tutorial_id, tutorial_author, tutorial_title, 
               submission_date, tutorial_icon, tutorial_description) 
               values (:tutorial_id, :tutorial_author, :tutorial_title, :submission_date, 
               :tutorial_icon, :tutorial_description);]]>
         </value> 
      </property>   
      
      <property name = "itemSqlParameterSourceProvider"> 
         <bean class = "org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider" /> 
      </property> 
   </bean> 
</beans>     

Context.xml

以下是我们的Spring Batch应用程序的context.xml文件。在这个文件中,我们将定义诸如作业存储库、作业启动器和事务管理器之类的bean。

在Maven项目的src > main > resources文件夹中创建此文件。

<beans xmlns = "http://www.springframework.org/schema/beans" 
   xmlns:jdbc = "http://www.springframework.org/schema/jdbc" 
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" 
   xsi:schemaLocation = "http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 
      http://www.springframework.org/schema/jdbc 
      http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd"> 
   
   <!-- stored job-meta in database -->
   <bean id = "jobRepository" 
      class = "org.springframework.batch.core.repository.support.JobRepositoryFactoryBean"> 
      <property name = "dataSource" ref = "dataSource" /> 
      <property name = "transactionManager" ref = "transactionManager" /> 
      <property name = "databaseType" value = "mysql" /> 
   </bean>  
 
   <bean id = "transactionManager" 
   class = "org.springframework.batch.support.transaction.ResourcelessTransactionManager" />  
   <bean id = "jobLauncher" 
      class = "org.springframework.batch.core.launch.support.SimpleJobLauncher"> 
      <property name = "jobRepository" ref = "jobRepository" /> 
   </bean> 
  
   <!-- connect to MySQL database --> 
   <bean id = "dataSource" 
      class = "org.springframework.jdbc.datasource.DriverManagerDataSource"> 
      <property name = "url" value = "jdbc:mysql://127.0.0.1:3306/details" /> 
      <property name = "username" value = "myuser" /> 
      <property name = "password" value = "password" /> 
   </bean>  
 
   <!-- create job-meta tables automatically --> 
   <jdbc:initialize-database data-source = "dataSource">   
      <jdbc:script location = "org/springframework/batch/core/schema-drop-mysql.sql"/>   
      <jdbc:script location = "org/springframework/batch/core/schema-mysql.sql"/> 
   </jdbc:initialize-database> 
</beans>   

CustomItemProcessor.java

以下是处理器类。在这个类中,我们编写应用程序的处理代码。在这里,我们加载一个PDF文档,创建一个新页面,创建一个表格,并在表格中为每条记录插入以下值:教程ID、教程名称、作者、提交日期。

在Maven项目的src > main > java文件夹中创建此类。

import java.io.File; 
import java.io.IOException;  

import org.apache.pdfbox.pdmodel.PDDocument; 
import org.apache.pdfbox.pdmodel.PDPage; 
import org.apache.pdfbox.pdmodel.PDPageContentStream; 
import org.apache.pdfbox.pdmodel.font.PDType1Font; 
import org.springframework.batch.item.ItemProcessor;  

public class CustomItemProcessor implements ItemProcessor<Tutorial, Tutorial> {  
   
   public static void drawTable(PDPage page, PDPageContentStream contentStream, 
      float y, float margin, String[][] content) throws IOException { 
      final int rows = content.length; 
      final int cols = content[0].length; 
      final float rowHeight = 50; 
      final float tableWidth = page.getMediaBox().getWidth()-(2*margin); 
      final float tableHeight = rowHeight * rows; 
      final float colWidth = tableWidth/(float)cols; 
      final float cellMargin=5f;  
      
      // draw the rows 
      float nexty = y ; 
      for (int i = 0; i <= rows; i++) {   
         contentStream.drawLine(margin,nexty,margin+tableWidth,nexty); 
         nexty-= rowHeight; 
      }  
      
      //draw the columns 
      float nextx = margin; 
      for (int i = 0; i <= cols; i++) {
         contentStream.drawLine(nextx,y,nextx,y-tableHeight); 
         nextx += colWidth; 
      }  
      
      // now add the text    
      contentStream.setFont(PDType1Font.HELVETICA_BOLD,12);  
      
      float textx = margin+cellMargin; 
      float texty = y-15; 
      for(int i = 0; i < content.length; i++){ 
         for(int j = 0 ; j < content[i].length; j++){ 
            String text = content[i][j]; 
            contentStream.beginText(); 
            contentStream.moveTextPositionByAmount(textx,texty); 
            contentStream.drawString(text); 
            contentStream.endText(); 
            textx += colWidth; 
         } 
        
         texty-=rowHeight; 
         textx = margin+cellMargin; 
      } 
   }  
   
   
   private void createPDFDocument() throws IOException {
      // Creating PDF document object 
      PDDocument document = new PDDocument();    

      // Saving the document
      document.save("E:/Examples/test.pdf");

      System.out.println("PDF created");  

      // Closing the document  
      document.close();
   }
   
   @Override 
   public Tutorial process(Tutorial item) throws Exception { 
      System.out.println("Processing..." + item); 
   
      createPDFDocument();
   
      // Creating PDF document object 
      PDDocument doc = PDDocument.load(new File("E:/Examples/test.pdf"));     
      
      // Creating a blank page 
      PDPage page = new PDPage(); 
      doc.addPage( page ); 
      PDPageContentStream contentStream =  new PDPageContentStream(doc, page);  
      
      String[][] content = {{"Id",""+item.getTutorial_id()},
      {"Title", item.getTutorial_title()}, 
      {"Authour", item.getTutorial_author()}, 
      {"Submission Date", item.getSubmission_date()}} ;  
      drawTable(page, contentStream, 700, 100, content);       
      
      contentStream.close(); 
      doc.save("E:/Examples/test.pdf" ); 
      System.out.println("Hello"); 
      return item; 
   }    
}      

TutorialFieldSetMapper.java

以下是ReportFieldSetMapper类,它将数据设置到Tutorial类。

在Maven项目的src > main > java文件夹中创建此类。

import org.springframework.batch.item.file.mapping.FieldSetMapper; 
import org.springframework.batch.item.file.transform.FieldSet; 
import org.springframework.validation.BindException;  

public class TutorialFieldSetMapper implements FieldSetMapper<Tutorial> { 
   
   @Override 
   public Tutorial mapFieldSet(FieldSet fieldSet) throws BindException {   
      // instantiating the Tutorial class 
      Tutorial tutorial = new Tutorial(); 
   
      // Setting the fields from XML 
      tutorial.setTutorial_id(fieldSet.readInt(0));   
      tutorial.setTutorial_title(fieldSet.readString(1)); 
      tutorial.setTutorial_author(fieldSet.readString(2)); 
      tutorial.setTutorial_icon(fieldSet.readString(3)); 
      tutorial.setTutorial_description(fieldSet.readString(4));   
      return tutorial;  
   }  
} 

Tutorial.java

以下是Tutorial类。它是一个简单的类,包含settergetter方法。

在Maven项目的src > main > java文件夹中创建此类。

public class Tutorial { 
   private int tutorial_id; 
   private String tutorial_author; 
   private String tutorial_title; 
   private String submission_date; 
   private String tutorial_icon; 
   private String tutorial_description;   
   
   @Override 
   public String toString() { 
      return " [id=" + tutorial_id + ", author=" + tutorial_author  
         + ", title=" + tutorial_title + ", date=" + submission_date + ", icon =" 
         +tutorial_icon +", description = "+tutorial_description+"]"; 
   }  
   
   public int getTutorial_id() { 
      return tutorial_id; 
   }  
   
   public void setTutorial_id(int tutorial_id) { 
      this.tutorial_id = tutorial_id; 
   }  
   
   public String getTutorial_author() { 
      return tutorial_author; 
   }  
   
   public void setTutorial_author(String tutorial_author) { 
      this.tutorial_author = tutorial_author; 
   }  
   
   public String getTutorial_title() { 
      return tutorial_title; 
   } 
   
   public void setTutorial_title(String tutorial_title) { 
      this.tutorial_title = tutorial_title; 
   }  
   
   public String getSubmission_date() { 
      return submission_date; 
   }  
   
   public void setSubmission_date(String submission_date) { 
      this.submission_date = submission_date; 
   }  
   
   public String getTutorial_icon() { 
      return tutorial_icon; 
   }  
   
   public void setTutorial_icon(String tutorial_icon) { 
      this.tutorial_icon = tutorial_icon; 
   }  
   
   public String getTutorial_description() { 
      return tutorial_description; 
   }  
   
   public void setTutorial_description(String tutorial_description) { 
      this.tutorial_description = tutorial_description; 
   } 
}

App.java

以下是启动批处理过程的代码。在这个类中,我们将通过运行JobLauncher来启动Batch应用程序。

在Maven项目的src > main > java文件夹中创建此类。

import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App { 
   public static void main(String[] args) throws Exception { 
      String[] springConfig  = {    "jobConfig.xml" };  
      
      // Creating the application context object  
      ApplicationContext context = new ClassPathXmlApplicationContext(springConfig);  
      
      // Creating the job launcher 
      JobLauncher jobLauncher = (JobLauncher) context.getBean("jobLauncher"); 
   
      // Creating the job 
      Job job = (Job) context.getBean("helloWorldJob"); 
   
      // create the pdf
      createPDFDocument();
	  
      // Executing the JOB 
      JobExecution execution = jobLauncher.run(job, new JobParameters()); 
      System.out.println("Exit Status : " + execution.getStatus()); 
   }  
   
   private static void createPDFDocument() throws IOException {
      // Creating PDF document object 
      PDDocument document = new PDDocument();    

      // Saving the document
      document.save("E:/Examples/test.pdf");

      System.out.println("PDF created");  

      // Closing the document  
      document.close();
   }   
} 

输出

在Eclipse中右键单击项目,选择以...运行 -> Maven构建。将目标设置为clean package并运行项目。您将看到以下输出。

[INFO] Scanning for projects...
[INFO] 
[INFO] [1m----------------< [0;36mcom.tutorialspoint:SpringBatchSample[0;1m >----------------[m
[INFO] [1mBuilding SpringBatchExample 1.0-SNAPSHOT[m
[INFO]   from pom.xml
[INFO] [1m--------------------------------[ jar ]---------------------------------[m
[INFO] 
[INFO] [1m--- [0;32mclean:3.2.0:clean[m [1m(default-clean)[m @ [36mSpringBatchSample[0;1m ---[m
[INFO] Deleting C:\Users\Tutorialspoint\eclipse-workspace\SpringBatchSample\target
[INFO] 
[INFO] [1m--- [0;32mresources:3.3.1:resources[m [1m(default-resources)[m @ [36mSpringBatchSample[0;1m ---[m
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 3 resources from src\main\resources to target\classes
[INFO] 
[INFO] [1m--- [0;32mcompiler:2.3.2:compile[m [1m(default-compile)[m @ [36mSpringBatchSample[0;1m ---[m
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 5 source files to C:\Users\Tutorialspoint\eclipse-workspace\SpringBatchSample\target\classes
[INFO] 
[INFO] [1m--- [0;32mresources:3.3.1:testResources[m [1m(default-testResources)[m @ [36mSpringBatchSample[0;1m ---[m
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource from src\test\resources to target\test-classes
[INFO] 
[INFO] [1m--- [0;32mcompiler:2.3.2:testCompile[m [1m(default-testCompile)[m @ [36mSpringBatchSample[0;1m ---[m
[INFO] Nothing to compile - all classes are up to date
[INFO] 
[INFO] [1m--- [0;32msurefire:3.1.2:test[m [1m(default-test)[m @ [36mSpringBatchSample[0;1m ---[m
[INFO] 
[INFO] [1m--- [0;32mjar:3.3.0:jar[m [1m(default-jar)[m @ [36mSpringBatchSample[0;1m ---[m
[INFO] Building jar: C:\Users\Tutorialspoint\eclipse-workspace\SpringBatchSample\target\spring-batch.jar
[INFO] [1m------------------------------------------------------------------------[m
[INFO] [1;32mBUILD SUCCESS[m
[INFO] [1m------------------------------------------------------------------------[m
[INFO] Total time:  3.495 s
[INFO] Finished at: 2024-07-31T12:14:52+05:30
[INFO] [1m------------------------------------------------------------------------[m

要检查上述SpringBatch程序的输出,请右键单击App.java类并选择以...运行 -> Java应用程序。它将产生以下输出:

Jul 31, 2024 12:16:16 PM org.springframework.batch.core.launch.support.SimpleJobLauncher afterPropertiesSet
INFO: No TaskExecutor has been set, defaulting to synchronous executor.
PDF created
Jul 31, 2024 12:16:19 PM org.springframework.batch.core.launch.support.SimpleJobLauncher$1 run
INFO: Job: [FlowJob: [name=helloWorldJob]] launched with the following parameters: [{}]
Jul 31, 2024 12:16:20 PM org.springframework.batch.core.job.SimpleStepHandler handleStep
INFO: Executing step: [step1]
Security framework of XStream not explicitly initialized, using predefined black list on your own risk.
Processing... [id=1001, author=Sanjay, title=Learn Java, date=06-05-2007, icon =https://tutorialspoint.com/java/images/java-minilogo.jpg, description = Java is a high-level programming language originally 
         developed by Sun Microsystems and released in 1995. 
         Java runs on a variety of platforms. 
         This tutorial gives a complete understanding of Java.');]
Processing... [id=1002, author=Abdul S, title=Learn MySQL, date=19-04-2007, icon =https://tutorialspoint.com/mysql/images/mysql-minilogo.jpg, description = MySQL is the most popular 
         Open Source Relational SQL database management system. 
         MySQL is one of the best RDBMS being used for developing web-based software applications. 
         This tutorial will give you quick start with MySQL 
         and make you comfortable with MySQL programming.]
Processing... [id=1003, author=Krishna Kasyap, title=Learn JavaFX, date=06-07-2017, icon =https://tutorialspoint.com/javafx/images/javafx-minilogo.jpg, description = JavaFX is a Java library used to build Rich Internet Applications. 
         The applications developed using JavaFX can run on various devices 
         such as Desktop Computers, Mobile Phones, TVs, Tablets, etc. 
         This tutorial, discusses all the necessary elements of JavaFX that are required
         to develop effective Rich Internet Applications]
Jul 31, 2024 12:16:21 PM org.springframework.batch.core.step.AbstractStep execute
INFO: Step: [step1] executed in 1s232ms
Jul 31, 2024 12:16:21 PM org.springframework.batch.core.launch.support.SimpleJobLauncher$1 run
INFO: Job: [FlowJob: [name=helloWorldJob]] completed with the following parameters: [{}] and the following status: [COMPLETED] in 1s484ms
Exit Status : COMPLETED

如果您验证数据库中的details.tutorial表,它将显示以下输出:

tutorial_id tutorial_author tutorial_title submission_date tutorial_icon tutorial_description
1001 Sanjay 学习Java 06-05-2007 https://tutorialspoint.com/java/images/java-mini-logo.jpg Java是一种高级编程语言,最初由Sun Microsystems开发,并于1995年发布。Java可在各种平台上运行。本教程将全面讲解Java。
1002 Abdul S 学习MySQL 19-04-2007 https://tutorialspoint.com/mysql/images/mysql-minilogo.jpg MySQL是最流行的开源关系型SQL数据库管理系统。MySQL是用于开发基于Web的软件应用程序的最佳RDBMS之一。本教程将快速入门MySQL,并让您轻松掌握MySQL编程。
1003 学习JavaFX Krishna Kasyap 06-07-2017 https://tutorialspoint.com/javafx/images/javafx-minilogo.jpg MySQL是最流行的开源关系型SQL数据库管理系统。MySQL是用于开发基于Web的软件应用程序的最佳RDBMS之一。本教程将快速入门MySQL,并让您轻松掌握MySQL编程。

这将生成一个PDF文件,每页显示如下所示的记录。

Page Thumbnails

Spring Batch - CSV 到 XML

在本章中,我们将创建一个简单的Spring Batch应用程序,该应用程序使用CSV读取器和XML写入器。

读取器 - 我们在应用程序中使用的读取器FlatFileItemReader,用于从CSV文件读取数据。

写入器 - 我们在应用程序中使用的写入器是StaxEventItemWriter,用于将数据写入XML文件。

处理器 - 我们在应用程序中使用的处理器是一个自定义处理器,它只打印从CSV文件读取的记录。

创建项目

Spring Batch - 环境章节所述,创建一个新的Maven项目。

以下是我们在本应用程序中使用的输入CSV文件。此文档包含指定教程ID、教程作者、教程标题、提交日期、教程图标和教程描述等详细信息的数据记录。

report.csv

在Maven项目的src > main > resources文件夹中创建此文件。

1001, "Sanjay", "Learn Java", 06/05/2007 
1002, "Abdul S", "Learn MySQL", 19/04/2007 
1003, "Krishna Kasyap", "Learn JavaFX", 06/07/2017

pom.xml

以下是此Maven项目中使用的pom.xml文件的内容。

<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 
   http://maven.apache.org/maven-v4_0_0.xsd"> 
   <modelVersion>4.0.0</modelVersion> 
   <groupId>com.tutorialspoint</groupId> 
   <artifactId>SpringBatchSample</artifactId> 
   <packaging>jar</packaging> 
   <version>1.0-SNAPSHOT</version> 
   <name>SpringBatchExample</name>
   <url>http://maven.apache.org</url>  

   <properties> 
      <jdk.version>21</jdk.version> 
      <spring.version>5.3.14</spring.version> 
      <spring.batch.version>4.3.4</spring.batch.version> 
      <mysql.driver.version>8.4.0</mysql.driver.version> 
      <junit.version>4.11</junit.version> 
      <pdf.version>2.0.32</pdf.version>
      <xstream.version>1.4.17</xstream.version>
      <jaxb.version>2.3.1</jaxb.version> 
      <jaxb.impl.version>2.3.4</jaxb.impl.version> 
   </properties>  

   <dependencies> 
      <!-- Spring Core --> 
      <dependency> 
         <groupId>org.springframework</groupId> 
         <artifactId>spring-core</artifactId> 
         <version>${spring.version}</version> 
      </dependency>  

      <!-- Spring jdbc, for database --> 
      <dependency> 
         <groupId>org.springframework</groupId> 
         <artifactId>spring-jdbc</artifactId> 
         <version>${spring.version}</version> 
      </dependency>  

      <!-- Spring XML to/back object --> 
      <dependency> 
         <groupId>org.springframework</groupId> 
         <artifactId>spring-oxm</artifactId> 
         <version>${spring.version}</version> 
      </dependency>  

      <!-- MySQL database driver --> 
      <dependency>
         <groupId>com.mysql</groupId>
         <artifactId>mysql-connector-j</artifactId>
         <version>${mysql.driver.version}</version>
      </dependency>  

      <!-- Spring Batch dependencies --> 
      <dependency> 
         <groupId>org.springframework.batch</groupId> 
         <artifactId>spring-batch-core</artifactId> 
         <version>${spring.batch.version}</version> 
      </dependency> 

      <dependency> 
         <groupId>org.springframework.batch</groupId> 
         <artifactId>spring-batch-infrastructure</artifactId> 
         <version>${spring.batch.version}</version> 
      </dependency>  

      <!-- Spring Batch unit test --> 
      <dependency> 
         <groupId>org.springframework.batch</groupId> 
         <artifactId>spring-batch-test</artifactId> 
         <version>${spring.batch.version}</version> 
      </dependency>  

      <!-- Junit --> 
      <dependency> 
         <groupId>junit</groupId> 
         <artifactId>junit</artifactId> 
         <version>${junit.version}</version> 
         <scope>test</scope> 
      </dependency> 

      <!-- pdfbox -->
      <dependency>
         <groupId>org.apache.pdfbox</groupId>
         <artifactId>pdfbox</artifactId>
         <version>${pdf.version}</version>
      </dependency>
	  
      <!-- xstream -->
      <dependency>
         <groupId>com.thoughtworks.xstream</groupId>
         <artifactId>xstream</artifactId>
         <version>${xstream.version}</version>
      </dependency>
	  
      <!-- jaxb-api -->
      <dependency>
         <groupId>javax.xml.bind</groupId>
         <artifactId>jaxb-api</artifactId>
         <version>${jaxb.version}</version>
      </dependency>
	  
      <!-- JAXB RI -->
      <dependency>
         <groupId>com.sun.xml.bind</groupId>
         <artifactId>jaxb-impl</artifactId>
         <version>${jaxb.impl.version}</version>
      </dependency>

   </dependencies> 

   <build> 
      <finalName>spring-batch</finalName> 
      <plugins> 
         <plugin> 
            <groupId>org.apache.maven.plugins</groupId> 
            <artifactId>maven-eclipse-plugin</artifactId>
            <version>2.9</version> 
            <configuration> 
               <downloadSources>true</downloadSources> 
               <downloadJavadocs>false</downloadJavadocs> 
            </configuration> 
         </plugin> 
   
         <plugin> 
            <groupId>org.apache.maven.plugins</groupId> 
            <artifactId>maven-compiler-plugin</artifactId> 
            <version>2.3.2</version> 
            <configuration> 
               <source>${jdk.version}</source> 
               <target>${jdk.version}</target> 
            </configuration> 
         </plugin> 
      </plugins> 
   </build> 
</project>    

jobConfig.xml

以下是我们的示例Spring Batch应用程序的配置文件。在这个文件中,我们将定义作业和步骤。除此之外,我们还定义了ItemReader、ItemProcessor和ItemWriter的bean。(在这里,我们将它们与各自的类关联,并传递所需属性的值来配置它们。)

在Maven项目的src > main > resources文件夹中创建此文件。

<beans xmlns = "http://www.springframework.org/schema/beans" 
   xmlns:batch = "http://www.springframework.org/schema/batch" 
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" 
   xsi:schemaLocation = "http://www.springframework.org/schema/batch 
      http://www.springframework.org/schema/batch/spring-batch-2.2.xsd 
      http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">  
   
   <import resource = "context.xml" />  
   
   <bean id = "report" class = "Report" scope = "prototype" /> 
   <bean id = "itemProcessor" class = "CustomItemProcessor" />  
   
   <batch:job id = "helloWorldJob"> 
   
      <batch:step id = "step1"> 
   
         <batch:tasklet> 
            <batch:chunk reader = "cvsFileItemReader" writer = "xmlItemWriter" 
               processor = "itemProcessor" commit-interval = "10"> 
            </batch:chunk> 
         </batch:tasklet> 
      </batch:step> 
   </batch:job>  
 
   <bean id = "cvsFileItemReader" 
      class = "org.springframework.batch.item.file.FlatFileItemReader">  
      <property name = "resource" value = "classpath:report.csv" /> 
      <property name = "lineMapper"> 
         <bean 
            class = "org.springframework.batch.item.file.mapping.DefaultLineMapper"> 
            <property name = "lineTokenizer"> 
               <bean    
                  class = "org.springframework.batch.item.file.transform.DelimitedLineTokenizer"> 
                  <property name = "names" value = "tutorial_id, 
                     tutorial_author, Tutorial_title, submission_date" /> 
               </bean> 
            </property> 
      
            <property name = "fieldSetMapper"> 
               <bean class = "ReportFieldSetMapper" /> 
            </property> 
         </bean> 
      </property> 
   </bean>  
   
   <bean id = "xmlItemWriter" 
      class = "org.springframework.batch.item.xml.StaxEventItemWriter"> 
      <property name = "resource" value = "file:tutorials.xml" /> 
      <property name = "marshaller" ref = "reportMarshaller" /> 
      <property name = "rootTagName" value = "tutorials" /> 
   </bean>  
 
   <bean id = "reportMarshaller" 
      class = "org.springframework.oxm.jaxb.Jaxb2Marshaller">
      <property name = "classesToBeBound"> 
         <list> 
            <value>Tutorial</value> 
         </list> 
      </property> 
   </bean> 
</beans> 

Context.xml

以下是我们的Spring Batch应用程序的context.xml文件。在这个文件中,我们将定义诸如作业存储库、作业启动器和事务管理器之类的bean。

在Maven项目的src > main > resources文件夹中创建此文件。

<beans xmlns = "http://www.springframework.org/schema/beans" 
   xmlns:jdbc = "http://www.springframework.org/schema/jdbc" 
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" 
   xsi:schemaLocation = "http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 
      http://www.springframework.org/schema/jdbc 
      http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd">  
   <!-- stored job-meta in database --> 
   <bean id = "jobRepository" 
      class = "org.springframework.batch.core.repository.support.JobRepositoryFactoryBean"> 
      <property name = "dataSource" ref = "dataSource" /> 
      <property name = "transactionManager" ref = "transactionManager" /> 
      <property name = "databaseType" value = "mysql" /> 
   </bean>  
 
   <bean id = "transactionManager" 
      class = "org.springframework.batch.support.transaction.ResourcelessTransactionManager" />  
   <bean id = "jobLauncher" 
      class = "org.springframework.batch.core.launch.support.SimpleJobLauncher"> 
      <property name = "jobRepository" ref = "jobRepository" /> 
   </bean>  
   
   <bean id = "dataSource" class = "org.springframework.jdbc.datasource.DriverManagerDataSource"> 
      <property name = "url" value = "jdbc:mysql://127.0.0.1:3306/details" />
      <property name = "username" value = "myuser" /> 
      <property name = "password" value = "password" /> 
   </bean> 
  
   <!-- create job-meta tables automatically --> 
   <jdbc:initialize-database data-source = "dataSource">   
      <jdbc:script location = "org/springframework/batch/core/schema-drop-mysql.sql" /> 
      <jdbc:script location = "org/springframework/batch/core/schema-mysql.sql" /> 
   </jdbc:initialize-database> 
</beans>

CustomItemProcessor.java

以下是处理器类。在这个类中,我们编写应用程序的处理代码。在这里,我们打印每条记录的内容。

在Maven项目的src > main > java文件夹中创建此类。

import org.springframework.batch.item.ItemProcessor;  

public class CustomItemProcessor implements ItemProcessor<Tutorial, Tutorial> {  
   
   @Override 
   public Tutorial process(Tutorial item) throws Exception {  
      System.out.println("Processing..." + item); 
      return item; 
   } 
} 

TutorialFieldSetMapper.java

以下是TutorialFieldSetMapper类,它将数据设置到Tutorial类。

在Maven项目的src > main > java文件夹中创建此类。

import org.springframework.batch.item.file.mapping.FieldSetMapper; 
import org.springframework.batch.item.file.transform.FieldSet; 
import org.springframework.validation.BindException;  

public class TutorialFieldSetMapper implements FieldSetMapper<Tutorial> {  

   @Override 
   public Tutorial mapFieldSet(FieldSet fieldSet) throws BindException {  
      
      //Instantiating the report object  
      Tutorial tutorial = new Tutorial(); 
       
      //Setting the fields  
      tutorial.setTutorial_id(fieldSet.readInt(0)); 
      tutorial.setTutorial_author(fieldSet.readString(1)); 
      tutorial.setTutorial_title(fieldSet.readString(2)); 
      tutorial.setSubmission_date(fieldSet.readString(3)); 
       
      return tutorial; 
   } 
}

Tutorial.java类

以下是Tutorial类。它是一个简单的Java类,包含settergetter方法。在这个类中,我们使用注释将此类的​​方法与XML文件的标签关联。

在Maven项目的src > main > java文件夹中创建此类。

import javax.xml.bind.annotation.XmlAttribute; 
import javax.xml.bind.annotation.XmlElement; 
import javax.xml.bind.annotation.XmlRootElement; 

@XmlRootElement(name = "tutorial") 
public class Tutorial {  
   private int tutorial_id; 
   private String tutorial_author; 
   private String tutorial_title;
   private String submission_date;  
 
   @XmlAttribute(name = "tutorial_id") 
   public int getTutorial_id() { 
      return tutorial_id; 
   }  
 
   public void setTutorial_id(int tutorial_id) { 
      this.tutorial_id = tutorial_id; 
   }  
 
   @XmlElement(name = "tutorial_author") 
   public String getTutorial_author() { 
      return tutorial_author; 
   }  
   public void setTutorial_author(String tutorial_author) { 
      this.tutorial_author = tutorial_author; 
   }  
      
   @XmlElement(name = "tutorial_title") 
   public String getTutorial_title() { 
      return tutorial_title; 
   }  
   
   public void setTutorial_title(String tutorial_title) { 
      this.tutorial_title = tutorial_title; 
   }  
   
   @XmlElement(name = "submission_date") 
   public String getSubmission_date() { 
      return submission_date; 
   }  
   
   public void setSubmission_date(String submission_date) { 
      this.submission_date = submission_date; 
   } 
   
   @Override 
   public String toString() { 
      return "  [Tutorial id=" + tutorial_id + 
         ",Tutorial Author=" + tutorial_author  + 
         ",Tutorial Title=" + tutorial_title + 
         ",Submission Date=" + submission_date + "]"; 
   } 
}  

App.java

以下是启动批处理过程的代码。在这个类中,我们将通过运行JobLauncher来启动批处理应用程序。

在Maven项目的src > main > java文件夹中创建此类。

import org.springframework.batch.core.Job; 
import org.springframework.batch.core.JobExecution; 
import org.springframework.batch.core.JobParameters; 
import org.springframework.batch.core.launch.JobLauncher; 
import org.springframework.context.ApplicationContext; 
import org.springframework.context.support.ClassPathXmlApplicationContext;  

public class App {  
   public static void main(String[] args) throws Exception { 
     
      String[] springConfig  =  { "jobConfig.xml" };  
      
      // Creating the application context object        
      ApplicationContext context = new ClassPathXmlApplicationContext(springConfig);  
      
      // Creating the job launcher 
      JobLauncher jobLauncher = (JobLauncher) context.getBean("jobLauncher"); 
   
      // Creating the job 
      Job job = (Job) context.getBean("helloWorldJob"); 
   
      // Executing the JOB 
      JobExecution execution = jobLauncher.run(job, new JobParameters());
      System.out.println("Exit Status : " + execution.getStatus()); 
   } 
}       

输出

在Eclipse中右键单击项目,选择以...运行 -> Maven构建。将目标设置为clean package并运行项目。您将看到以下输出。

[INFO] Scanning for projects...
[INFO] 
[INFO] [1m----------------< [0;36mcom.tutorialspoint:SpringBatchSample[0;1m >----------------[m
[INFO] [1mBuilding SpringBatchExample 1.0-SNAPSHOT[m
[INFO]   from pom.xml
[INFO] [1m--------------------------------[ jar ]---------------------------------[m
[INFO] 
[INFO] [1m--- [0;32mclean:3.2.0:clean[m [1m(default-clean)[m @ [36mSpringBatchSample[0;1m ---[m
[INFO] Deleting C:\Users\Tutorialspoint\eclipse-workspace\SpringBatchSample\target
[INFO] 
[INFO] [1m--- [0;32mresources:3.3.1:resources[m [1m(default-resources)[m @ [36mSpringBatchSample[0;1m ---[m
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 4 resources from src\main\resources to target\classes
[INFO] 
[INFO] [1m--- [0;32mcompiler:2.3.2:compile[m [1m(default-compile)[m @ [36mSpringBatchSample[0;1m ---[m
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 5 source files to C:\Users\Tutorialspoint\eclipse-workspace\SpringBatchSample\target\classes
[INFO] 
[INFO] [1m--- [0;32mresources:3.3.1:testResources[m [1m(default-testResources)[m @ [36mSpringBatchSample[0;1m ---[m
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource from src\test\resources to target\test-classes
[INFO] 
[INFO] [1m--- [0;32mcompiler:2.3.2:testCompile[m [1m(default-testCompile)[m @ [36mSpringBatchSample[0;1m ---[m
[INFO] Nothing to compile - all classes are up to date
[INFO] 
[INFO] [1m--- [0;32msurefire:3.1.2:test[m [1m(default-test)[m @ [36mSpringBatchSample[0;1m ---[m
[INFO] 
[INFO] [1m--- [0;32mjar:3.3.0:jar[m [1m(default-jar)[m @ [36mSpringBatchSample[0;1m ---[m
[INFO] Building jar: C:\Users\Tutorialspoint\eclipse-workspace\SpringBatchSample\target\spring-batch.jar
[INFO] [1m------------------------------------------------------------------------[m
[INFO] [1;32mBUILD SUCCESS[m
[INFO] [1m------------------------------------------------------------------------[m
[INFO] Total time:  3.323 s
[INFO] Finished at: 2024-07-31T12:54:04+05:30
[INFO] [1m------------------------------------------------------------------------[m

要检查上述SpringBatch程序的输出,请右键单击App.java类并选择以...运行 -> Java应用程序。它将产生以下输出:

Jul 31, 2024 1:00:16 PM org.springframework.batch.core.launch.support.SimpleJobLauncher afterPropertiesSet
INFO: No TaskExecutor has been set, defaulting to synchronous executor.
Jul 31, 2024 1:00:19 PM org.springframework.batch.core.launch.support.SimpleJobLauncher$1 run
INFO: Job: [FlowJob: [name=helloWorldJob]] launched with the following parameters: [{}]
Jul 31, 2024 1:00:19 PM org.springframework.batch.core.job.SimpleStepHandler handleStep
INFO: Executing step: [step1]
Processing...  [Tutorial id=1001,Tutorial Author=Sanjay,Tutorial Title=Learn Java,Submission Date=06/05/2007]
Processing...  [Tutorial id=1002,Tutorial Author=Abdul S,Tutorial Title=Learn MySQL,Submission Date=19/04/2007]
Processing...  [Tutorial id=1003,Tutorial Author=Krishna Kasyap,Tutorial Title=Learn JavaFX,Submission Date=06/07/2017]
Jul 31, 2024 1:00:20 PM org.springframework.batch.core.step.AbstractStep execute
INFO: Step: [step1] executed in 215ms
Jul 31, 2024 1:00:20 PM org.springframework.batch.core.launch.support.SimpleJobLauncher$1 run
INFO: Job: [FlowJob: [name=helloWorldJob]] completed with the following parameters: [{}] and the following status: [COMPLETED] in 540ms
Exit Status : COMPLETED

这将生成一个XML文件(根文件夹中的tutorials.xml),内容如下所示。

<?xml version = "1.0" encoding = "UTF-8"?> 
<tutorials> 
   <tutorial tutorial_id = "1001"> 
      <submission_date>06/05/2007</submission_date> 
      <tutorial_author>Sanjay</tutorial_author> 
      <tutorial_title>Learn Java</tutorial_title> 
   </tutorial> 
   
   <tutorial tutorial_id = "1002"> 
      <submission_date>19/04/2007</submission_date> 
      <tutorial_author>Abdul S</tutorial_author> 
      <tutorial_title>Learn MySQL</tutorial_title> 
   </tutorial> 
   
   <tutorial tutorial_id = "1003"> 
      <submission_date>06/07/2017</submission_date>
      <tutorial_author>Krishna Kasyap</tutorial_author> 
      <tutorial_title>Learn JavaFX</tutorial_title> 
   </tutorial> 
</tutorials>

Spring Batch - MySQL 到 XML

在本章中,我们将创建一个Spring Batch应用程序,该应用程序使用MySQL读取器和XML写入器。

读取器 - 我们在应用程序中使用的读取器是JdbcCursorItemReader,用于从MySQL数据库读取数据。

假设我们在MySQL数据库中创建了一个表,如下所示:

CREATE TABLE details.tutorialsdata( 
   tutorial_id int NOT NULL, 
   tutorial_author VARCHAR(20), 
   tutorial_title VARCHAR(20), 
   submission_date VARCHAR(20) 
);

假设我们已向其中插入以下记录。

mysql> select * from tutorialsdata; 
+-------------+-----------------+----------------+-----------------+ 
| tutorial_id | tutorial_author | tutorial_title | submission_date | 
+-------------+-----------------+----------------+-----------------+ 
|         101 | Sanjay          | Learn Java     | 06-05-2007      | 
|         102 | Abdul S         | Learn MySQL    | 19-04-2007      | 
|         103 | Krishna Kasyap  | Learn JavaFX   | 06-07-2017      | 
+-------------+-----------------+----------------+-----------------+ 
3 rows in set (0.00 sec) 

写入器 - 我们在应用程序中使用的写入器是StaxEventItemWriter,用于将数据写入XML文件。

处理器 - 我们在应用程序中使用的处理器是一个自定义处理器,它只打印从CSV文件读取的记录。

创建项目

Spring Batch - 环境章节所述,创建一个新的Maven项目。

pom.xml

以下是此Maven项目中使用的pom.xml文件的内容。

<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 
   http://maven.apache.org/maven-v4_0_0.xsd"> 
   <modelVersion>4.0.0</modelVersion> 
   <groupId>com.tutorialspoint</groupId> 
   <artifactId>SpringBatchSample</artifactId> 
   <packaging>jar</packaging> 
   <version>1.0-SNAPSHOT</version> 
   <name>SpringBatchExample</name>
   <url>http://maven.apache.org</url>  

   <properties> 
      <jdk.version>21</jdk.version> 
      <spring.version>5.3.14</spring.version> 
      <spring.batch.version>4.3.4</spring.batch.version> 
      <mysql.driver.version>8.4.0</mysql.driver.version> 
      <junit.version>4.11</junit.version> 
      <pdf.version>2.0.32</pdf.version>
      <xstream.version>1.4.17</xstream.version>
      <jaxb.version>2.3.1</jaxb.version> 
      <jaxb.impl.version>2.3.4</jaxb.impl.version> 
   </properties>  

   <dependencies> 
      <!-- Spring Core --> 
      <dependency> 
         <groupId>org.springframework</groupId> 
         <artifactId>spring-core</artifactId> 
         <version>${spring.version}</version> 
      </dependency>  

      <!-- Spring jdbc, for database --> 
      <dependency> 
         <groupId>org.springframework</groupId> 
         <artifactId>spring-jdbc</artifactId> 
         <version>${spring.version}</version> 
      </dependency>  

      <!-- Spring XML to/back object --> 
      <dependency> 
         <groupId>org.springframework</groupId> 
         <artifactId>spring-oxm</artifactId> 
         <version>${spring.version}</version> 
      </dependency>  

      <!-- MySQL database driver --> 
      <dependency>
         <groupId>com.mysql</groupId>
         <artifactId>mysql-connector-j</artifactId>
         <version>${mysql.driver.version}</version>
      </dependency>  

      <!-- Spring Batch dependencies --> 
      <dependency> 
         <groupId>org.springframework.batch</groupId> 
         <artifactId>spring-batch-core</artifactId> 
         <version>${spring.batch.version}</version> 
      </dependency> 

      <dependency> 
         <groupId>org.springframework.batch</groupId> 
         <artifactId>spring-batch-infrastructure</artifactId> 
         <version>${spring.batch.version}</version> 
      </dependency>  

      <!-- Spring Batch unit test --> 
      <dependency> 
         <groupId>org.springframework.batch</groupId> 
         <artifactId>spring-batch-test</artifactId> 
         <version>${spring.batch.version}</version> 
      </dependency>  

      <!-- Junit --> 
      <dependency> 
         <groupId>junit</groupId> 
         <artifactId>junit</artifactId> 
         <version>${junit.version}</version> 
         <scope>test</scope> 
      </dependency> 

      <!-- pdfbox -->
      <dependency>
         <groupId>org.apache.pdfbox</groupId>
         <artifactId>pdfbox</artifactId>
         <version>${pdf.version}</version>
      </dependency>
	  
      <!-- xstream -->
      <dependency>
         <groupId>com.thoughtworks.xstream</groupId>
         <artifactId>xstream</artifactId>
         <version>${xstream.version}</version>
      </dependency>
	  
      <!-- jaxb-api -->
      <dependency>
         <groupId>javax.xml.bind</groupId>
         <artifactId>jaxb-api</artifactId>
         <version>${jaxb.version}</version>
      </dependency>
	  
      <!-- JAXB RI -->
      <dependency>
         <groupId>com.sun.xml.bind</groupId>
         <artifactId>jaxb-impl</artifactId>
         <version>${jaxb.impl.version}</version>
      </dependency>

   </dependencies> 

   <build> 
      <finalName>spring-batch</finalName> 
      <plugins> 
         <plugin> 
            <groupId>org.apache.maven.plugins</groupId> 
            <artifactId>maven-eclipse-plugin</artifactId>
            <version>2.9</version> 
            <configuration> 
               <downloadSources>true</downloadSources> 
               <downloadJavadocs>false</downloadJavadocs> 
            </configuration> 
         </plugin> 
   
         <plugin> 
            <groupId>org.apache.maven.plugins</groupId> 
            <artifactId>maven-compiler-plugin</artifactId> 
            <version>2.3.2</version> 
            <configuration> 
               <source>${jdk.version}</source> 
               <target>${jdk.version}</target> 
            </configuration> 
         </plugin> 
      </plugins> 
   </build> 
</project>    

jobConfig.xml

以下是我们的示例Spring Batch应用程序的配置文件。在这个文件中,我们将定义作业和步骤。除此之外,我们还定义了ItemReader、ItemProcessor和ItemWriter的bean。(在这里,我们将它们与各自的类关联,并传递所需属性的值来配置它们。)

在Maven项目的src > main > resources文件夹中创建此文件。

<beans xmlns = "http://www.springframework.org/schema/beans" 
   xmlns:batch = "http://www.springframework.org/schema/batch" 
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" 
   xmlns:util = "http://www.springframework.org/schema/util" 
   xsi:schemaLocation = " http://www.springframework.org/schema/batch 
      http://www.springframework.org/schema/batch/spring-batch-2.2.xsd 
      http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">  
   
   <import resource = "context.xml" /> 
  
   <bean id = "report" class = "Report" scope = "prototype" /> 
   <bean id = "itemProcessor" class = "CustomItemProcessor" />  
   
   <batch:job id = "helloWorldJob"> 
      <batch:step id = "step1"> 
         <batch:tasklet> 
            <batch:chunk reader = "dbItemReader" 
               writer = "mysqlItemWriter" processor = "itemProcessor" commit-interval = "10">
            </batch:chunk> 
         </batch:tasklet> 
      </batch:step> 
   </batch:job> 
         
   <bean id = "dbItemReader" 
      class = "org.springframework.batch.item.database.JdbcCursorItemReader" scope = "step"> 
      <property name = "dataSource" ref = "dataSource" /> 
      <property name = "sql" value = "select * from tutorialsdata" /> 
      <property name = "rowMapper"> 
         <bean class = "TutorialRowMapper" /> 
      </property> 
   </bean>             
   <bean id = "mysqlItemWriter" 
      class = "org.springframework.batch.item.xml.StaxEventItemWriter"> 
      <property name = "resource" value = "file:tutorials.xml" /> 
      <property name = "marshaller" ref = "reportMarshaller" />
      <property name = "rootTagName" value = "tutorials" /> 
   </bean>  
   
   <bean id = "reportMarshaller" class = "org.springframework.oxm.jaxb.Jaxb2Marshaller"> 
      <property name = "classesToBeBound"> 
         <list> 
            <value>Tutorial</value> 
         </list> 
      </property> 
   </bean> 
</beans>  

Context.xml

以下是我们的Spring Batch应用程序的context.xml文件。在这个文件中,我们将定义诸如作业存储库、作业启动器和事务管理器之类的bean。

在Maven项目的src > main > resources文件夹中创建此文件。

<beans xmlns = " http://www.springframework.org/schema/beans" 
   xmlns:jdbc = "http://www.springframework.org/schema/jdbc" 
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" 
   xsi:schemaLocation = "http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 
      http://www.springframework.org/schema/jdbc 
      http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd "> 
   
   <!-- stored job-meta in database --> 
   <bean id = "jobRepository"  
      class = "org.springframework.batch.core.repository.support.JobRepositoryFactoryBean"> 
      <property name = "dataSource" ref = "dataSource" /> 
      <property name = "transactionManager" ref = "transactionManager" /> 
      <property name = "databaseType" value = "mysql" /> 
   </bean>  
   
   <bean id = "transactionManager" 
      class = "org.springframework.batch.support.transaction.ResourcelessTransactionMana ger" />  
   <bean id = "jobLauncher"
      class = "org.springframework.batch.core.launch.support.SimpleJobLauncher"> 
      <property name = "jobRepository" ref = "jobRepository" /> 
   </bean> 
  
   <!-- connect to MySQL database --> 
   <bean id = "dataSource" 
      class = "org.springframework.jdbc.datasource.DriverManagerDataSource"> 
      <property name = "url" value = "jdbc:mysql://127.0.0.1:3306/details" /> 
      <property name = "username" value = "myuser" /> 
      <property name = "password" value = "password" /> 
   </bean> 
  
   <!-- create job-meta tables automatically --> 
   <jdbc:initialize-database data-source = "dataSource">   
      <jdbc:script location = "org/springframework/batch/core/schema-drop-mysql.sql" />   
      <jdbc:script location = "org/springframework/batch/core/schema-mysql.sql" /> 
   </jdbc:initialize-database> 
</beans>  

CustomItemProcessor.java

以下是处理器类。在这个类中,我们编写应用程序的处理代码。在这里,我们打印每条记录的内容。

在Maven项目的src > main > java文件夹中创建此类。

import org.springframework.batch.item.ItemProcessor;  

public class CustomItemProcessor implements ItemProcessor<Tutorial, Tutorial> {  

   @Override 
   public Tutorial process(Tutorial item) throws Exception { 
      System.out.println("Processing..." + item); 
      return item; 
   } 
} 

TutorialRowMapper.java

以下是TutorialRowMapper类,它将数据设置到Tutorial类。

在Maven项目的src > main > java文件夹中创建此类。

import java.sql.ResultSet; 
import java.sql.SQLException; 
import org.springframework.jdbc.core.RowMapper;  

public class TutorialRowMapper implements RowMapper<Tutorial> {  
   
   @Override 
   public Tutorial mapRow(ResultSet rs, int rowNum) throws SQLException {  
      
      Tutorial tutorial = new Tutorial();  
      tutorial.setTutorial_id(rs.getInt("tutorial_id")); 
      tutorial.setTutorial_author(rs.getString("tutorial_author")); 
      tutorial.setTutorial_title(rs.getString("tutorial_title")); 
      tutorial.setSubmission_date(rs.getString("submission_date"));  
      return tutorial; 
   } 
}

Tutorial.java

以下是Tutorial类。它是一个简单的Java类,包含settergetter方法。在这个类中,我们使用注释将此类的​​方法与XML文件的标签关联。

在Maven项目的src > main > java文件夹中创建此类。

import javax.xml.bind.annotation.XmlAttribute; 
import javax.xml.bind.annotation.XmlElement; 
import javax.xml.bind.annotation.XmlRootElement; 

@XmlRootElement(name = "tutorial") 
public class Tutorial {  
   private int tutorial_id; 
   private String tutorial_author; 
   private String tutorial_title;
   private String submission_date;  
 
   @XmlAttribute(name = "tutorial_id") 
   public int getTutorial_id() { 
      return tutorial_id; 
   }  
 
   public void setTutorial_id(int tutorial_id) { 
      this.tutorial_id = tutorial_id; 
   }  
 
   @XmlElement(name = "tutorial_author") 
   public String getTutorial_author() { 
      return tutorial_author; 
   }  
   public void setTutorial_author(String tutorial_author) { 
      this.tutorial_author = tutorial_author; 
   }  
      
   @XmlElement(name = "tutorial_title") 
   public String getTutorial_title() { 
      return tutorial_title; 
   }  
   
   public void setTutorial_title(String tutorial_title) { 
      this.tutorial_title = tutorial_title; 
   }  
   
   @XmlElement(name = "submission_date") 
   public String getSubmission_date() { 
      return submission_date; 
   }  
   
   public void setSubmission_date(String submission_date) { 
      this.submission_date = submission_date; 
   } 
   
   @Override 
   public String toString() { 
      return "  [Tutorial id=" + tutorial_id + 
         ",Tutorial Author=" + tutorial_author  + 
         ",Tutorial Title=" + tutorial_title + 
         ",Submission Date=" + submission_date + "]"; 
   } 
}  

App.java

以下是启动批处理过程的代码。在这个类中,我们将通过运行JobLauncher来启动Batch应用程序。

在Maven项目的src > main > java文件夹中创建此类。

import org.springframework.batch.core.Job; 
import org.springframework.batch.core.JobExecution; 
import org.springframework.batch.core.JobParameters; 
import org.springframework.batch.core.launch.JobLauncher; 
import org.springframework.context.ApplicationContext; 
import org.springframework.context.support.ClassPathXmlApplicationContext;  

public class App {  
   public static void main(String[] args) throws Exception { 
     
      String[] springConfig  =  { "jobConfig.xml" };  
      
      // Creating the application context object  
      ApplicationContext context = new ClassPathXmlApplicationContext(springConfig);  
      
      // Creating the job launcher 
      JobLauncher jobLauncher = (JobLauncher) context.getBean("jobLauncher"); 
    
      // Creating the job 
      Job job = (Job) context.getBean("helloWorldJob");
      
      // Executing the JOB 
      JobExecution execution = jobLauncher.run(job, new JobParameters()); 
      System.out.println("Exit Status : " + execution.getStatus()); 
   } 
}      

输出

在Eclipse中右键单击项目,选择以...运行 -> Maven构建。将目标设置为clean package并运行项目。您将看到以下输出。

[INFO] Scanning for projects...
[INFO] 
[INFO] [1m----------------< [0;36mcom.tutorialspoint:SpringBatchSample[0;1m >----------------[m
[INFO] [1mBuilding SpringBatchExample 1.0-SNAPSHOT[m
[INFO]   from pom.xml
[INFO] [1m--------------------------------[ jar ]---------------------------------[m
[INFO] 
[INFO] [1m--- [0;32mclean:3.2.0:clean[m [1m(default-clean)[m @ [36mSpringBatchSample[0;1m ---[m
[INFO] Deleting C:\Users\Tutorialspoint\eclipse-workspace\SpringBatchSample\target
[INFO] 
[INFO] [1m--- [0;32mresources:3.3.1:resources[m [1m(default-resources)[m @ [36mSpringBatchSample[0;1m ---[m
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 4 resources from src\main\resources to target\classes
[INFO] 
[INFO] [1m--- [0;32mcompiler:2.3.2:compile[m [1m(default-compile)[m @ [36mSpringBatchSample[0;1m ---[m
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 5 source files to C:\Users\Tutorialspoint\eclipse-workspace\SpringBatchSample\target\classes
[INFO] 
[INFO] [1m--- [0;32mresources:3.3.1:testResources[m [1m(default-testResources)[m @ [36mSpringBatchSample[0;1m ---[m
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource from src\test\resources to target\test-classes
[INFO] 
[INFO] [1m--- [0;32mcompiler:2.3.2:testCompile[m [1m(default-testCompile)[m @ [36mSpringBatchSample[0;1m ---[m
[INFO] Nothing to compile - all classes are up to date
[INFO] 
[INFO] [1m--- [0;32msurefire:3.1.2:test[m [1m(default-test)[m @ [36mSpringBatchSample[0;1m ---[m
[INFO] 
[INFO] [1m--- [0;32mjar:3.3.0:jar[m [1m(default-jar)[m @ [36mSpringBatchSample[0;1m ---[m
[INFO] Building jar: C:\Users\Tutorialspoint\eclipse-workspace\SpringBatchSample\target\spring-batch.jar
[INFO] [1m------------------------------------------------------------------------[m
[INFO] [1;32mBUILD SUCCESS[m
[INFO] [1m------------------------------------------------------------------------[m
[INFO] Total time:  3.323 s
[INFO] Finished at: 2024-07-31T12:54:04+05:30
[INFO] [1m------------------------------------------------------------------------[m

要检查上述SpringBatch程序的输出,请右键单击App.java类并选择以...运行 -> Java应用程序。它将产生以下输出:

Jul 31, 2024 1:24:13 PM org.springframework.batch.core.launch.support.SimpleJobLauncher afterPropertiesSet
INFO: No TaskExecutor has been set, defaulting to synchronous executor.
Jul 31, 2024 1:24:16 PM org.springframework.batch.core.launch.support.SimpleJobLauncher$1 run
INFO: Job: [FlowJob: [name=helloWorldJob]] launched with the following parameters: [{}]
Jul 31, 2024 1:24:16 PM org.springframework.batch.core.job.SimpleStepHandler handleStep
INFO: Executing step: [step1]
Processing...  [Tutorial id=101,Tutorial Author=Sanjay,Tutorial Title=Learn Java,Submission Date=06-05-2007]
Processing...  [Tutorial id=102,Tutorial Author=Abdul S,Tutorial Title=Learn MySQL,Submission Date=19-04-2007]
Processing...  [Tutorial id=103,Tutorial Author=Krishna Kasyap,Tutorial Title=Learn JavaFX,Submission Date=06-07-2017]
Jul 31, 2024 1:24:16 PM org.springframework.batch.core.step.AbstractStep execute
INFO: Step: [step1] executed in 312ms
Jul 31, 2024 1:24:16 PM org.springframework.batch.core.launch.support.SimpleJobLauncher$1 run
INFO: Job: [FlowJob: [name=helloWorldJob]] completed with the following parameters: [{}] and the following status: [COMPLETED] in 666ms
Exit Status : COMPLETED

这将生成一个XML文件(根文件夹中的tutorials.xml),内容如下所示。

<?xml version="1.0" encoding="UTF-8"?>
<tutorials>
   <tutorial tutorial_id="101">
      <submission_date>06-05-2007</submission_date>
      <tutorial_author>Sanjay</tutorial_author>
      <tutorial_title>Learn Java</tutorial_title>
   </tutorial>
   <tutorial tutorial_id="102">
      <submission_date>19-04-2007</submission_date>
      <tutorial_author>Abdul S</tutorial_author>
      <tutorial_title>Learn MySQL</tutorial_title>
   </tutorial>
   <tutorial tutorial_id="103">
      <submission_date>06-07-2017</submission_date>
      <tutorial_author>Krishna Kasyap</tutorial_author>
      <tutorial_title>Learn JavaFX</tutorial_title>
   </tutorial>
</tutorials>

Spring Batch - MySQL 到平面文件

在本章中,我们将创建一个Spring Batch应用程序,该应用程序使用MySQL读取器和平面文件写入器(.txt)。

读取器 - 我们在应用程序中使用的读取器是JdbcCursorItemReader,用于从MySQL数据库读取数据。

假设我们在MySQL数据库中创建了一个表,如下所示。

CREATE TABLE details.tutorialsdata( 
   tutorial_id int NOT NULL, 
   tutorial_author VARCHAR(20), 
   tutorial_title VARCHAR(20), 
   submission_date VARCHAR(20) 
);

假设我们已向其中插入以下记录。

mysql> select * from tutorialsdata; 
+-------------+-----------------+----------------+-----------------+ 
| tutorial_id | tutorial_author | tutorial_title | submission_date | 
+-------------+-----------------+----------------+-----------------+ 
|         101 | Sanjay          | Learn Java     | 06-05-2007      | 
|         102 | Abdul S         | Learn MySQL    | 19-04-2007      | 
|         103 | Krishna Kasyap  | Learn JavaFX   | 06-07-2017      | 
+-------------+-----------------+----------------+-----------------+ 
3 rows in set (0.00 sec) 

写入器 - 我们在应用程序中使用的写入器是FlatFileItemWriter,用于将数据写入平面文件(.txt)。

处理器 - 我们在应用程序中使用的处理器是一个自定义处理器,它只打印从CSV文件读取的记录。

创建项目

Spring Batch - 环境章节所述,创建一个新的Maven项目。

pom.xml

以下是此Maven项目中使用的pom.xml文件的内容。

<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 
   http://maven.apache.org/maven-v4_0_0.xsd"> 
   <modelVersion>4.0.0</modelVersion> 
   <groupId>com.tutorialspoint</groupId> 
   <artifactId>SpringBatchSample</artifactId> 
   <packaging>jar</packaging> 
   <version>1.0-SNAPSHOT</version> 
   <name>SpringBatchExample</name>
   <url>http://maven.apache.org</url>  

   <properties> 
      <jdk.version>21</jdk.version> 
      <spring.version>5.3.14</spring.version> 
      <spring.batch.version>4.3.4</spring.batch.version> 
      <mysql.driver.version>8.4.0</mysql.driver.version> 
      <junit.version>4.11</junit.version> 
      <pdf.version>2.0.32</pdf.version>
      <xstream.version>1.4.17</xstream.version>
      <jaxb.version>2.3.1</jaxb.version> 
      <jaxb.impl.version>2.3.4</jaxb.impl.version> 
   </properties>  

   <dependencies> 
      <!-- Spring Core --> 
      <dependency> 
         <groupId>org.springframework</groupId> 
         <artifactId>spring-core</artifactId> 
         <version>${spring.version}</version> 
      </dependency>  

      <!-- Spring jdbc, for database --> 
      <dependency> 
         <groupId>org.springframework</groupId> 
         <artifactId>spring-jdbc</artifactId> 
         <version>${spring.version}</version> 
      </dependency>  

      <!-- Spring XML to/back object --> 
      <dependency> 
         <groupId>org.springframework</groupId> 
         <artifactId>spring-oxm</artifactId> 
         <version>${spring.version}</version> 
      </dependency>  

      <!-- MySQL database driver --> 
      <dependency>
         <groupId>com.mysql</groupId>
         <artifactId>mysql-connector-j</artifactId>
         <version>${mysql.driver.version}</version>
      </dependency>  

      <!-- Spring Batch dependencies --> 
      <dependency> 
         <groupId>org.springframework.batch</groupId> 
         <artifactId>spring-batch-core</artifactId> 
         <version>${spring.batch.version}</version> 
      </dependency> 

      <dependency> 
         <groupId>org.springframework.batch</groupId> 
         <artifactId>spring-batch-infrastructure</artifactId> 
         <version>${spring.batch.version}</version> 
      </dependency>  

      <!-- Spring Batch unit test --> 
      <dependency> 
         <groupId>org.springframework.batch</groupId> 
         <artifactId>spring-batch-test</artifactId> 
         <version>${spring.batch.version}</version> 
      </dependency>  

      <!-- Junit --> 
      <dependency> 
         <groupId>junit</groupId> 
         <artifactId>junit</artifactId> 
         <version>${junit.version}</version> 
         <scope>test</scope> 
      </dependency> 

      <!-- pdfbox -->
      <dependency>
         <groupId>org.apache.pdfbox</groupId>
         <artifactId>pdfbox</artifactId>
         <version>${pdf.version}</version>
      </dependency>
	  
      <!-- xstream -->
      <dependency>
         <groupId>com.thoughtworks.xstream</groupId>
         <artifactId>xstream</artifactId>
         <version>${xstream.version}</version>
      </dependency>
	  
      <!-- jaxb-api -->
      <dependency>
         <groupId>javax.xml.bind</groupId>
         <artifactId>jaxb-api</artifactId>
         <version>${jaxb.version}</version>
      </dependency>
	  
      <!-- JAXB RI -->
      <dependency>
         <groupId>com.sun.xml.bind</groupId>
         <artifactId>jaxb-impl</artifactId>
         <version>${jaxb.impl.version}</version>
      </dependency>

   </dependencies> 

   <build> 
      <finalName>spring-batch</finalName> 
      <plugins> 
         <plugin> 
            <groupId>org.apache.maven.plugins</groupId> 
            <artifactId>maven-eclipse-plugin</artifactId>
            <version>2.9</version> 
            <configuration> 
               <downloadSources>true</downloadSources> 
               <downloadJavadocs>false</downloadJavadocs> 
            </configuration> 
         </plugin> 
   
         <plugin> 
            <groupId>org.apache.maven.plugins</groupId> 
            <artifactId>maven-compiler-plugin</artifactId> 
            <version>2.3.2</version> 
            <configuration> 
               <source>${jdk.version}</source> 
               <target>${jdk.version}</target> 
            </configuration> 
         </plugin> 
      </plugins> 
   </build> 
</project>    

jobConfig.xml

以下是我们的示例Spring Batch应用程序的配置文件。在这个文件中,我们将定义作业和步骤。除此之外,我们还定义了ItemReader、ItemProcessor和ItemWriter的bean。(在这里,我们将它们与各自的类关联,并传递所需属性的值来配置它们。)

在Maven项目的src > main > resources文件夹中创建此文件。

<beans xmlns = "http://www.springframework.org/schema/beans" 
   xmlns:batch = "http://www.springframework.org/schema/batch" 
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" 
   xmlns:util = "http://www.springframework.org/schema/util" 
   xsi:schemaLocation = "http://www.springframework.org/schema/batch 
   
      http://www.springframework.org/schema/batch/spring-batch-2.2.xsd 
      http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">  
   
   <import resource = "context.xml" />  
   <bean id = "tutorial" class = "Tutorial" scope = "prototype" /> 
   <bean id = "itemProcessor" class = "CustomItemProcessor" />  
   
   <batch:job id = "helloWorldJob"> 
      <batch:step id = "step1"> 
         <batch:tasklet> 
            <batch:chunk reader = "mysqlItemReader" 
               writer = "flatFileItemWriter" processor = "itemProcessor" 
               commit-interval = "10"> 
            </batch:chunk> 
         </batch:tasklet> 
      </batch:step> 
   </batch:job> 
         
   <bean id = "mysqlItemReader" 
      class = "org.springframework.batch.item.database.JdbcCursorItemReader" > 
      <property name = "dataSource" ref = "dataSource" /> 
      <property name = "sql" value = "select * from details.tutorialsdata" /> 
      <property name = "rowMapper">  
         <bean class = "TutorialRowMapper" /> 
      </property> 
   </bean>
   
   <bean id = "flatFileItemWriter" 
      class = " org.springframework.batch.item.file.FlatFileItemWriter">      
      <property name = "resource" value = "file:tutorials.txt"/> 
      <property name = "lineAggregator"> 
         <bean class = " org.springframework.batch.item.file.transform.PassThroughLineAggregator"/> 
      </property> 
   </bean> 
</beans> 

Context.xml

以下是我们的Spring Batch应用程序的context.xml文件。在这个文件中,我们将定义诸如作业存储库、作业启动器和事务管理器之类的bean。

在Maven项目的src > main > resources文件夹中创建此文件。

<beans xmlns = "http://www.springframework.org/schema/beans" 
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" 
   xmlns:jdbc = "http://www.springframework.org/schema/jdbc" 
   xsi:schemaLocation = "http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 
      http://www.springframework.org/schema/jdbc 
      http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd "> 
   
   <!-- stored job-meta in database --> 
   <bean id = "jobRepository"  
      class = "org.springframework.batch.core.repository.support.JobRepositoryFactoryBean"> 
      <property name = "dataSource" ref = "dataSource" /> 
      <property name = "transactionManager" ref = "transactionManager" /> 
      <property name = "databaseType" value = "mysql" /> 
   </bean>  
 
   <bean id = "transactionManager"  
      class = "org.springframework.batch.support.transaction.ResourcelessTransactionManager" />  
   
   <bean id = "dataSource" 
      class = "org.springframework.jdbc.datasource.DriverManagerDataSource"> 
      <property name = "url" value = "jdbc:mysql://127.0.0.1:3306/details" /> 
      <property name = "username" value = "myuser" /> 
      <property name = "password" value = "password" /> 
   </bean> 
    
   <bean id = "jobLauncher"  
      class = "org.springframework.batch.core.launch.support.SimpleJobLauncher"> 
      <property name = "jobRepository" ref = "jobRepository" /> 
   </bean> 
  
   <!-- create job-meta tables automatically --> 
   <jdbc:initialize-database data-source = "dataSource">   
      <jdbc:script location = "org/springframework/batch/core/schema-drop-mysql.sql" />   
      <jdbc:script location = "org/springframework/batch/core/schema-mysql.sql" /> 
   </jdbc:initialize-database> 
</beans> 

CustomItemProcessor.java

以下是处理器类。在这个类中,我们编写应用程序的处理代码。在这里,我们打印每条记录的内容。

在Maven项目的src > main > java文件夹中创建此类。

import org.springframework.batch.item.ItemProcessor;  

// Implementing the ItemProcessor interface 
public class CustomItemProcessor implements ItemProcessor<Tutorial, Tutorial> {  
 
   @Override 
   public Tutorial process(Tutorial item) throws Exception { 
      System.out.println("Processing..." + item); 
      return item; 
   } 
}

TutorialRowMapper.java

以下是TutorialRowMapper类,它将数据设置到Tutorial类。

在Maven项目的src > main > java文件夹中创建此类。

public class TutorialRowMapper implements RowMapper<Tutorial> {  
   
   @Override 
   public Tutorial mapRow(ResultSet rs, int rowNum) throws SQLException {  
  
      Tutorial tutorial = new Tutorial();  
  
      tutorial.setTutorial_id(rs.getInt("tutorial_id")); 
      tutorial.setTutorial_title(rs.getString("tutorial_title")); 
      tutorial.setTutorial_author(rs.getString("tutorial_author")); 
      tutorial.setSubmission_date(rs.getString("submission_date"));  
      return tutorial; 
   } 
}

Tutorial.java

以下是Tutorial类。它是一个简单的Java类,包含settergetter方法。在这个类中,我们使用注释将此类的​​方法与XML文件的标签关联。

在Maven项目的src > main > java文件夹中创建此类。

import javax.xml.bind.annotation.XmlAttribute; 
import javax.xml.bind.annotation.XmlElement; 
import javax.xml.bind.annotation.XmlRootElement; 

@XmlRootElement(name = "tutorial") 
public class Tutorial {  
   private int tutorial_id; 
   private String tutorial_author; 
   private String tutorial_title;
   private String submission_date;  
 
   @XmlAttribute(name = "tutorial_id") 
   public int getTutorial_id() { 
      return tutorial_id; 
   }  
 
   public void setTutorial_id(int tutorial_id) { 
      this.tutorial_id = tutorial_id; 
   }  
 
   @XmlElement(name = "tutorial_author") 
   public String getTutorial_author() { 
      return tutorial_author; 
   }  
   public void setTutorial_author(String tutorial_author) { 
      this.tutorial_author = tutorial_author; 
   }  
      
   @XmlElement(name = "tutorial_title") 
   public String getTutorial_title() { 
      return tutorial_title; 
   }  
   
   public void setTutorial_title(String tutorial_title) { 
      this.tutorial_title = tutorial_title; 
   }  
   
   @XmlElement(name = "submission_date") 
   public String getSubmission_date() { 
      return submission_date; 
   }  
   
   public void setSubmission_date(String submission_date) { 
      this.submission_date = submission_date; 
   } 
   
   @Override 
   public String toString() { 
      return "  [Tutorial id=" + tutorial_id + 
         ",Tutorial Author=" + tutorial_author  + 
         ",Tutorial Title=" + tutorial_title + 
         ",Submission Date=" + submission_date + "]"; 
   } 
}  

App.java

以下是启动批处理过程的代码。在这个类中,我们将通过运行JobLauncher来启动Batch应用程序。

在Maven项目的src > main > java文件夹中创建此类。

import org.springframework.batch.core.Job; 
import org.springframework.batch.core.JobExecution; 
import org.springframework.batch.core.JobParameters; 
import org.springframework.batch.core.launch.JobLauncher; 
import org.springframework.context.ApplicationContext; 
import org.springframework.context.support.ClassPathXmlApplicationContext;  

public class App {  
   
   public static void main(String[] args) throws Exception { 
     
      String[] springConfig  =  { "jobConfig.xml" };  
      
      // Creating the application context object  
      ApplicationContext context = new ClassPathXmlApplicationContext(springConfig);  
      
      // Creating the job launcher 
      JobLauncher jobLauncher = (JobLauncher) context.getBean("jobLauncher"); 
    
      // Creating the job 
      Job job = (Job) context.getBean("helloWorldJob"); 
    
      // Executing the JOB 
      JobExecution execution = jobLauncher.run(job, new JobParameters()); 
      System.out.println("Exit Status : " + execution.getStatus()); 
   } 
}

输出

在Eclipse中右键单击项目,选择以...运行 -> Maven构建。将目标设置为clean package并运行项目。您将看到以下输出。

[INFO] Scanning for projects...
[INFO] 
[INFO] [1m----------------< [0;36mcom.tutorialspoint:SpringBatchSample[0;1m >----------------[m
[INFO] [1mBuilding SpringBatchExample 1.0-SNAPSHOT[m
[INFO]   from pom.xml
[INFO] [1m--------------------------------[ jar ]---------------------------------[m
[INFO] 
[INFO] [1m--- [0;32mclean:3.2.0:clean[m [1m(default-clean)[m @ [36mSpringBatchSample[0;1m ---[m
[INFO] Deleting C:\Users\Tutorialspoint\eclipse-workspace\SpringBatchSample\target
[INFO] 
[INFO] [1m--- [0;32mresources:3.3.1:resources[m [1m(default-resources)[m @ [36mSpringBatchSample[0;1m ---[m
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 4 resources from src\main\resources to target\classes
[INFO] 
[INFO] [1m--- [0;32mcompiler:2.3.2:compile[m [1m(default-compile)[m @ [36mSpringBatchSample[0;1m ---[m
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 5 source files to C:\Users\Tutorialspoint\eclipse-workspace\SpringBatchSample\target\classes
[INFO] 
[INFO] [1m--- [0;32mresources:3.3.1:testResources[m [1m(default-testResources)[m @ [36mSpringBatchSample[0;1m ---[m
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource from src\test\resources to target\test-classes
[INFO] 
[INFO] [1m--- [0;32mcompiler:2.3.2:testCompile[m [1m(default-testCompile)[m @ [36mSpringBatchSample[0;1m ---[m
[INFO] Nothing to compile - all classes are up to date
[INFO] 
[INFO] [1m--- [0;32msurefire:3.1.2:test[m [1m(default-test)[m @ [36mSpringBatchSample[0;1m ---[m
[INFO] 
[INFO] [1m--- [0;32mjar:3.3.0:jar[m [1m(default-jar)[m @ [36mSpringBatchSample[0;1m ---[m
[INFO] Building jar: C:\Users\Tutorialspoint\eclipse-workspace\SpringBatchSample\target\spring-batch.jar
[INFO] [1m------------------------------------------------------------------------[m
[INFO] [1;32mBUILD SUCCESS[m
[INFO] [1m------------------------------------------------------------------------[m
[INFO] Total time:  3.323 s
[INFO] Finished at: 2024-07-31T13:35:50+05:30
[INFO] [1m------------------------------------------------------------------------[m

要检查上述SpringBatch程序的输出,请右键单击App.java类并选择以...运行 -> Java应用程序。它将产生以下输出:

Jul 31, 2024 1:36:25 PM org.springframework.batch.core.launch.support.SimpleJobLauncher afterPropertiesSet
INFO: No TaskExecutor has been set, defaulting to synchronous executor.
Jul 31, 2024 1:36:28 PM org.springframework.batch.core.launch.support.SimpleJobLauncher$1 run
INFO: Job: [FlowJob: [name=helloWorldJob]] launched with the following parameters: [{}]
Jul 31, 2024 1:36:28 PM org.springframework.batch.core.job.SimpleStepHandler handleStep
INFO: Executing step: [step1]
Processing...  [Tutorial id=101,Tutorial Author=Sanjay,Tutorial Title=Learn Java,Submission Date=06-05-2007]
Processing...  [Tutorial id=102,Tutorial Author=Abdul S,Tutorial Title=Learn MySQL,Submission Date=19-04-2007]
Processing...  [Tutorial id=103,Tutorial Author=Krishna Kasyap,Tutorial Title=Learn JavaFX,Submission Date=06-07-2017]
Jul 31, 2024 1:36:28 PM org.springframework.batch.core.step.AbstractStep execute
INFO: Step: [step1] executed in 191ms
Jul 31, 2024 1:36:28 PM org.springframework.batch.core.launch.support.SimpleJobLauncher$1 run
INFO: Job: [FlowJob: [name=helloWorldJob]] completed with the following parameters: [{}] and the following status: [COMPLETED] in 515ms
Exit Status : COMPLETED

这将生成一个TXT文件(根文件夹中的tutorials.txt),内容如下所示。

  [Tutorial id=101,Tutorial Author=Sanjay,Tutorial Title=Learn Java,Submission Date=06-05-2007]
  [Tutorial id=102,Tutorial Author=Abdul S,Tutorial Title=Learn MySQL,Submission Date=19-04-2007]
  [Tutorial id=103,Tutorial Author=Krishna Kasyap,Tutorial Title=Learn JavaFX,Submission Date=06-07-2017]
广告