弹簧批处理示例

歡迎來到 Spring Batch 示例. Spring Batch 是一個 spring framework模塊,用於執行批次工作。

春节 例子

在通过春分示例程序之前,让我们了解一下 [春分配]( / 社区 / 教程 / 春分配)术语。

一个任务可以由n数量的步骤组成,每个步骤都包含 阅读过程编写任务,或者它可以有一个单个操作,称为tasklet *阅读过程编写基本上是从数据库,CSV等源读取的,然后处理数据,并将其写入数据库,CSV,XML等源 *任务编写意味着执行单个任务或操作,如清理连接,在处理完成后释放资源 *阅读过程编写和任务编写可以连接在一起执行任务

春节 例子

我们将考虑下面的场景来实现目的. 包含数据需要转换为 XML 的 CSV 文件以及数据和标签将在列名后命名。

  1. Apache Maven 3.5.0 - 用于项目构建和依赖管理
  2. Eclipse Oxygen 发布 4.7.0 - 用于创建春季批量maven应用程序的 IDE
  3. Java 1.8
  4. 春季核心 4.3.12.RELEASE
  5. 春季 OXM 4.3.12.RELEASE
  6. 春季 JDBC 4.3.12.RELEASE
  7. 春季批量 3.0.8.RELEASE
  8. MySQL Java 驱动程序 5.1.25 - 基于您的MySQL 安装。 这是春季批量元数据表

Spring Batch 示例目录结构

Below image illustrates all the components in our Spring Batch example project. spring batch example

春天大麻依赖性

下面是 pom.xml 文件的内容,包括我们春季批量示例项目所需的所有依赖。

  1<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
  2    xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  3    <modelVersion>4.0.0</modelVersion>
  4
  5    <groupId>com.journaldev.spring</groupId>
  6    <artifactId>SpringBatchExample</artifactId>
  7    <version>0.0.1-SNAPSHOT</version>
  8    <packaging>jar</packaging>
  9
 10    <name>SpringBatchDemo</name>
 11    <url>https://maven.apache.org</url>
 12
 13    <properties>
 14    	<jdk.version>1.8</jdk.version>
 15    	<spring.version>4.3.12.RELEASE</spring.version>
 16    	<spring.batch.version>3.0.8.RELEASE</spring.batch.version>
 17    	<mysql.driver.version>5.1.25</mysql.driver.version>
 18    	<junit.version>4.11</junit.version>
 19    </properties>
 20
 21    <dependencies>
 22
 23    	<!-- Spring Core -->
 24    	<dependency>
 25    		<groupId>org.springframework</groupId>
 26    		<artifactId>spring-core</artifactId>
 27    		<version>${spring.version}</version>
 28    	</dependency>
 29
 30    	<!-- Spring jdbc, for database -->
 31    	<dependency>
 32    		<groupId>org.springframework</groupId>
 33    		<artifactId>spring-jdbc</artifactId>
 34    		<version>${spring.version}</version>
 35    	</dependency>
 36
 37    	<!-- Spring XML to/back object -->
 38    	<dependency>
 39    		<groupId>org.springframework</groupId>
 40    		<artifactId>spring-oxm</artifactId>
 41    		<version>${spring.version}</version>
 42    	</dependency>
 43
 44    	<!-- MySQL database driver -->
 45    	<dependency>
 46    		<groupId>mysql</groupId>
 47    		<artifactId>mysql-connector-java</artifactId>
 48    		<version>${mysql.driver.version}</version>
 49    	</dependency>
 50
 51    	<!-- Spring Batch dependencies -->
 52    	<dependency>
 53    		<groupId>org.springframework.batch</groupId>
 54    		<artifactId>spring-batch-core</artifactId>
 55    		<version>${spring.batch.version}</version>
 56    	</dependency>
 57    	<dependency>
 58    		<groupId>org.springframework.batch</groupId>
 59    		<artifactId>spring-batch-infrastructure</artifactId>
 60    		<version>${spring.batch.version}</version>
 61    	</dependency>
 62
 63    	<!-- Spring Batch unit test -->
 64    	<dependency>
 65    		<groupId>org.springframework.batch</groupId>
 66    		<artifactId>spring-batch-test</artifactId>
 67    		<version>${spring.batch.version}</version>
 68    	</dependency>
 69
 70    	<!-- Junit -->
 71    	<dependency>
 72    		<groupId>junit</groupId>
 73    		<artifactId>junit</artifactId>
 74    		<version>${junit.version}</version>
 75    		<scope>test</scope>
 76    	</dependency>
 77
 78    	<dependency>
 79    		<groupId>com.thoughtworks.xstream</groupId>
 80    		<artifactId>xstream</artifactId>
 81    		<version>1.4.10</version>
 82    	</dependency>
 83
 84    </dependencies>
 85    <build>
 86    	<finalName>spring-batch</finalName>
 87    	<plugins>
 88    		<plugin>
 89    			<groupId>org.apache.maven.plugins</groupId>
 90    			<artifactId>maven-eclipse-plugin</artifactId>
 91    			<version>2.9</version>
 92    			<configuration>
 93    				<downloadSources>true</downloadSources>
 94    				<downloadJavadocs>false</downloadJavadocs>
 95    			</configuration>
 96    		</plugin>
 97    		<plugin>
 98    			<groupId>org.apache.maven.plugins</groupId>
 99    			<artifactId>maven-compiler-plugin</artifactId>
100    			<version>2.3.2</version>
101    			<configuration>
102    				<source>${jdk.version}</source>
103    				<target>${jdk.version}</target>
104    			</configuration>
105    		</plugin>
106    	</plugins>
107    </build>
108</project>

春季批量处理 CSV 输入文件

以下是我们春季批量加工样本CSV文件的内容。

11001,Tom,Moody, 29/7/2013
21002,John,Parker, 30/7/2013
31003,Henry,Williams, 31/7/2013

春季批量工作配置

我們必須在配置檔案中定義 spring bean和 Spring batch job. 下面是 job-batch-demo.xml 檔案的內容,它是 Spring batch 項目中最重要的部分。

 1<beans xmlns="https://www.springframework.org/schema/beans"
 2    xmlns:batch="https://www.springframework.org/schema/batch" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
 3    xsi:schemaLocation="https://www.springframework.org/schema/batch
 4    	https://www.springframework.org/schema/batch/spring-batch-3.0.xsd
 5    	https://www.springframework.org/schema/beans 
 6    	https://www.springframework.org/schema/beans/spring-beans-4.3.xsd
 7    ">
 8
 9    <import resource="../config/context.xml" />
10    <import resource="../config/database.xml" />
11
12    <bean id="report" class="com.journaldev.spring.model.Report"
13    	scope="prototype" />
14    <bean id="itemProcessor" class="com.journaldev.spring.CustomItemProcessor" />
15
16    <batch:job id="DemoJobXMLWriter">
17    	<batch:step id="step1">
18    		<batch:tasklet>
19    			<batch:chunk reader="csvFileItemReader" writer="xmlItemWriter"
20    				processor="itemProcessor" commit-interval="10">
21    			</batch:chunk>
22    		</batch:tasklet>
23    	</batch:step>
24    </batch:job>
25
26    <bean id="csvFileItemReader" class="org.springframework.batch.item.file.FlatFileItemReader">
27
28    	<property name="resource" value="classpath:csv/input/report.csv" />
29
30    	<property name="lineMapper">
31    		<bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
32    			<property name="lineTokenizer">
33    				<bean
34    					class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
35    					<property name="names" value="id,firstname,lastname,dob" />
36    				</bean>
37    			</property>
38    			<property name="fieldSetMapper">
39    				<bean class="com.journaldev.spring.ReportFieldSetMapper" />
40
41    				<!-- if no data type conversion, use BeanWrapperFieldSetMapper to map 
42    					by name <bean class="org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper"> 
43    					<property name="prototypeBeanName" value="report" /> </bean> -->
44    			</property>
45    		</bean>
46    	</property>
47
48    </bean>
49
50    <bean id="xmlItemWriter" class="org.springframework.batch.item.xml.StaxEventItemWriter">
51    	<property name="resource" value="file:xml/outputs/report.xml" />
52    	<property name="marshaller" ref="reportMarshaller" />
53    	<property name="rootTagName" value="report" />
54    </bean>
55
56    <bean id="reportMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
57    	<property name="classesToBeBound">
58    		<list>
59    			<value>com.journaldev.spring.model.Report</value>
60    		</list>
61    	</property>
62    </bean>
63
64</beans>
  1. 联合国 我们正在使用FlatFile项目Reader'读取CSV文件海关项目处理器',使用StaxEvent项目Writer'处理数据并写入XML文件。 (_) )2. 批:工作 ' - 此标签定义了我们要创建的工作 。 ID 属性指定工作身份 。 我们可以在一个xml文件中定义多个任务. (_) )3. 批:分步骤- 此标签用于定义弹簧批量任务的不同步骤.
  2. 由"Spring Batch Framework"提供两种不同类型的处理风格,分别是"任务定位"和"Chunk Oriented". 此示例中使用的Chunk Oriented样式是指在交易边界内逐一读取数据并创建将写入的"chunks". (_)
  3. 阅读器:用于读取数据的春豆. 我们在此例子中使用了csvFile项目阅读器'豆,即FlatFile项目阅读器'的例子。 () )6. 处理器:这是用于处理数据的类. 我们在此例子中使用了`海关项目处理器'。 ()
  4. 编剧:用豆子将数据写入xml文件. (_) (英语). 8. 承诺间断 : 此属性定义了处理完成后将执行的块大小 。 基本上,这意味着项目阅读器将逐一读取数据,项目处理器也将以同样的方式处理数据,但项目Writer只有在等同承诺间距大小时才会写入数据.
  5. 作为该项目一部分使用的三个主要接口是项目阅读器 ' 、项目处理器 ' 和项目Writer ' 从org.springframework.batch.trome'软件包。 (_) (英语)

春季班级模型

首先,我们正在阅读 CSV 文件到 java 对象,然后使用 [JAXB]( / 社区 / 教程 / jaxb 示例 - 教程)将其写入 xml 文件。

 1package com.journaldev.spring.model;
 2
 3import java.util.Date;
 4
 5import javax.xml.bind.annotation.XmlAttribute;
 6import javax.xml.bind.annotation.XmlElement;
 7import javax.xml.bind.annotation.XmlRootElement;
 8
 9@XmlRootElement(name = "record")
10public class Report {
11
12    private int id;
13    private String firstName;
14    private String lastName;
15    private Date dob;
16
17    @XmlAttribute(name = "id")
18    public int getId() {
19    	return id;
20    }
21
22    public void setId(int id) {
23    	this.id = id;
24    }
25
26    @XmlElement(name = "firstname")
27    public String getFirstName() {
28    	return firstName;
29    }
30
31    public void setFirstName(String firstName) {
32    	this.firstName = firstName;
33    }
34
35    @XmlElement(name = "lastname")
36    public String getLastName() {
37    	return lastName;
38    }
39
40    public void setLastName(String lastName) {
41    	this.lastName = lastName;
42    }
43
44    @XmlElement(name = "dob")
45    public Date getDob() {
46    	return dob;
47    }
48
49    public void setDob(Date dob) {
50    	this.dob = dob;
51    }
52
53    @Override
54    public String toString() {
55    	return "Report [id=" + id + ", firstname=" + firstName + ", lastName=" + lastName + ", DateOfBirth=" + dob
56    			+ "]";
57    }
58
59}

请注意,模型类域应与春季批量地图配置定义相同,即在我们的情况下, `property name="names" value="id,firstname,lastname,dob" 。

Spring Batch 场地定位

需要一个自定义 FieldSetMapper 来转换一个日期. 如果不需要转换数据类型,那么只需要使用 BeanWrapperFieldSetMapper 来自动地图值以名称。

 1package com.journaldev.spring;
 2
 3import java.text.ParseException;
 4import java.text.SimpleDateFormat;
 5
 6import org.springframework.batch.item.file.mapping.FieldSetMapper;
 7import org.springframework.batch.item.file.transform.FieldSet;
 8import org.springframework.validation.BindException;
 9
10import com.journaldev.spring.model.Report;
11
12public class ReportFieldSetMapper implements FieldSetMapper<Report> {
13
14    private SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
15
16    public Report mapFieldSet(FieldSet fieldSet) throws BindException {
17
18    	Report report = new Report();
19    	report.setId(fieldSet.readInt(0));
20    	report.setFirstName(fieldSet.readString(1));
21    	report.setLastName(fieldSet.readString(2));
22
23    	// default format yyyy-MM-dd
24    	// fieldSet.readDate(4);
25    	String date = fieldSet.readString(3);
26    	try {
27    		report.setDob(dateFormat.parse(date));
28    	} catch (ParseException e) {
29    		e.printStackTrace();
30    	}
31
32    	return report;
33
34    }
35
36}

Spring Batch 元素处理器

现在,正如工作配置中定义的那样,一个 itemProcessor 将在 itemWriter 之前启动,我们为它创建了一个 CustomItemProcessor.java 类。

 1package com.journaldev.spring;
 2
 3import org.springframework.batch.item.ItemProcessor;
 4
 5import com.journaldev.spring.model.Report;
 6
 7public class CustomItemProcessor implements ItemProcessor<Report, Report> {
 8
 9    public Report process(Report item) throws Exception {
10    	
11    	System.out.println("Processing..." + item);
12    	String fname = item.getFirstName();
13    	String lname = item.getLastName();
14    	
15    	item.setFirstName(fname.toUpperCase());
16    	item.setLastName(lname.toUpperCase());
17    	return item;
18    }
19
20}

我们可以在 ItemProcessor 实现中操纵数据,因为你可以看到我正在将姓氏和姓氏值转换为上方案例。

春季配置文件

在我们的春季批量配置文件中,我们已经导入了两个额外的配置文件 - context.xmldatabase.xml

 1<beans xmlns="https://www.springframework.org/schema/beans"
 2    xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
 3    xsi:schemaLocation="
 4    	https://www.springframework.org/schema/beans 
 5    	https://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
 6
 7    <!-- stored job-meta in memory -->
 8    <!--  
 9    <bean id="jobRepository"
10    	class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean">
11    	<property name="transactionManager" ref="transactionManager" />
12    </bean>
13     -->
14     
15     <!-- stored job-meta in database -->
16    <bean id="jobRepository"
17    	class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean">
18    	<property name="dataSource" ref="dataSource" />
19    	<property name="transactionManager" ref="transactionManager" />
20    	<property name="databaseType" value="mysql" />
21    </bean>
22    
23    <bean id="transactionManager"
24    	class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />
25     
26    <bean id="jobLauncher"
27    	class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
28    	<property name="jobRepository" ref="jobRepository" />
29    </bean>
30
31</beans>
  • jobRepository - JobRepository负责将每个Java对象存储在其正确的元数据表中
  • transactionManager - 这负责执行交易,一旦 commit-interval的大小和处理的数据等同
  • jobLauncher - 这是春分的核心。
 1<beans xmlns="https://www.springframework.org/schema/beans"
 2    xmlns:jdbc="https://www.springframework.org/schema/jdbc" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
 3    xsi:schemaLocation="https://www.springframework.org/schema/beans 
 4    	https://www.springframework.org/schema/beans/spring-beans-4.3.xsd
 5    	https://www.springframework.org/schema/jdbc 
 6    	https://www.springframework.org/schema/jdbc/spring-jdbc-4.3.xsd">
 7
 8    <!-- connect to database -->
 9    <bean id="dataSource"
10    	class="org.springframework.jdbc.datasource.DriverManagerDataSource">
11    	<property name="driverClassName" value="com.mysql.jdbc.Driver" />
12    	<property name="url" value="jdbc:mysql://localhost:3306/Test" />
13    	<property name="username" value="test" />
14    	<property name="password" value="test123" />
15    </bean>
16
17    <bean id="transactionManager"
18    	class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />
19
20    <!-- create job-meta tables automatically -->
21    <!-- <jdbc:initialize-database data-source="dataSource"> <jdbc:script location="org/springframework/batch/core/schema-drop-mysql.sql" 
22    	/> <jdbc:script location="org/springframework/batch/core/schema-mysql.sql" 
23    	/> </jdbc:initialize-database> -->
24</beans>

Spring Batch 使用一些元数据表来存储批次工作信息. 我们可以从春季批次配置中创建它们,但建议通过手动执行 SQL 文件,正如您在上面的评论代码中所看到的那样。

春季餐桌

Spring Batch tables very closely match the Domain objects that represent them in Java. For example - JobInstance, JobExecution, JobParameters and StepExecution map to BATCH_JOB_INSTANCE, BATCH_JOB_EXECUTION, BATCH_JOB_EXECUTION_PARAMS and BATCH_STEP_EXECUTION respectively. ExecutionContext maps to both BATCH_JOB_EXECUTION_CONTEXT and BATCH_STEP_EXECUTION_CONTEXT. The JobRepository is responsible for saving and storing each java object into its correct table. spring batch tables Below are the details of each meta-data table.

  1. 联合国 ** 批次_ 任务_ 任务** : 贝特克-约克- INSTEG 表格中包含与 JobInstance. 2 相关的全部信息 。 Batch_job_execution_params: BATCH_JOB_Execution_PARAMS (英语). 表格中包含与JobParemeters 对象有关的所有信息.
  2. ** 批次_ 工作_ 执行** : BATCH_JOB_执行 表格中包含与 JobExecution 对象相关的数据。 每次运行任务时都会添加一行.
  3. ** 批次_步骤_执行** : BATCH_STEP_执行 表格中包含与 StepExecution 对象有关的所有信息 5。 ** 批次_ 工作_ 执行_ 文本** : BATCH_ Job_ Execution_ CONTEXT 主题曲 表格中包含与 Job 执行 Context 相关的数据。 每项任务执行都有一份工作执行协议,其中包含执行该特定任务所需的所有工作级别数据。 此数据通常代表失败后必须检索到的状态,以使一个工作Instance能够从它失败的地方重启.
  4. ** 批次_步骤_执行_文本** : BATCH_STEP_执行_CONTEXT 表格中包含与 Step 执行 Context 相关的数据。 每个步骤执行都有一个完全执行的文字,它包含着需要坚持执行某一步骤的所有数据. 此数据通常代表失败后必须检索到的状态,以使一个工作Instance能够从失败的地方重新启动.
  5. ** 批次_ 工作_ 执行_ seq** : 本表保留了任务的数据执行序列.
  6. ** 批次_步骤_执行_seq** : 本表保存了步执行顺序的数据.
  7. ** 批次_ job_seq** : 本表保留了工作序列数据,以防我们有多个工作,我们会得到多个行. ( (英语)

春季测试计划

我们的 Spring Batch 示例项目已经准备好了,最后一步是编写一个测试类来执行它作为一个 java 程序。

 1package com.journaldev.spring;
 2
 3import org.springframework.batch.core.Job;
 4import org.springframework.batch.core.JobExecution;
 5import org.springframework.batch.core.JobParameters;
 6import org.springframework.batch.core.JobParametersBuilder;
 7import org.springframework.batch.core.launch.JobLauncher;
 8import org.springframework.context.support.ClassPathXmlApplicationContext;
 9
10public class App {
11    public static void main(String[] args) {
12
13    	String[] springConfig = { "spring/batch/jobs/job-batch-demo.xml" };
14
15    	ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(springConfig);
16
17    	JobLauncher jobLauncher = (JobLauncher) context.getBean("jobLauncher");
18    	Job job = (Job) context.getBean("DemoJobXMLWriter");
19
20    	JobParameters jobParameters = new JobParametersBuilder().addLong("time", System.currentTimeMillis())
21    			.toJobParameters();
22
23    	try {
24
25    		JobExecution execution = jobLauncher.run(job, jobParameters);
26    		System.out.println("Exit Status : " + execution.getStatus());
27
28    	} catch (Exception e) {
29    		e.printStackTrace();
30    	}
31
32    	System.out.println("Done");
33    	context.close();
34    }
35}

只需在程序上运行,你会得到输出xml如下。

1<?xml version="1.0" encoding="UTF-8"?><report><record id="1001"><dob>2013-07-29T00:00:00+05:30</dob><firstname>TOM</firstname><lastname>MOODY</lastname></record><record id="1002"><dob>2013-07-30T00:00:00+05:30</dob><firstname>JOHN</firstname><lastname>PARKER</lastname></record><record id="1003"><dob>2013-07-31T00:00:00+05:30</dob><firstname>HENRY</firstname><lastname>WILLIAMS</lastname></record></report>

那就是春班的例子,你可以从下面的链接下载最终项目。

[下载《春天小组示例项目》(LINK0)]

引用: 官方指南

Published At
Categories with 技术
Tagged with
comments powered by Disqus