Item processing
项目处理
ItemReader和ItemWriter接口对于其特定的
任务,但是如果您想在编写之前插入业务逻辑怎么办?两者一选一
读写就是使用复合模式:创建一个包含
another 或包含另一个 .以下内容
代码显示了一个例子:ItemWriter
ItemWriter
ItemReader
ItemReader
public class CompositeItemWriter<T> implements ItemWriter<T> {
ItemWriter<T> itemWriter;
public CompositeItemWriter(ItemWriter<T> itemWriter) {
this.itemWriter = itemWriter;
}
public void write(Chunk<? extends T> items) throws Exception {
//Add business logic here
itemWriter.write(items);
}
public void setDelegate(ItemWriter<T> itemWriter){
this.itemWriter = itemWriter;
}
}
前面的类包含另一个类,它在具有
提供了一些业务逻辑。此模式可以很容易地用于 as
好吧,也许是为了根据
主要。如果您需要控制对自己的调用,它也很有用。
但是,如果您只想 “转换” 传入的项,以便在写入之前写入
其实写的,你不需要自己。您可以只修改项目。对于这个
场景中,Spring Batch 提供了如下接口
接口定义显示:ItemWriter
ItemReader
ItemReader
write
write
ItemProcessor
public interface ItemProcessor<I, O> {
O process(I item) throws Exception;
}
An 很简单。给定一个对象,转换它并返回另一个对象。这
提供的对象可能属于同一类型,也可能不是同一类型。关键是业务逻辑可以
在流程中应用,并且完全由开发人员来创建它
逻辑。An 可以直接连接到步骤中。例如,假设 an 提供了一个 type 类,并且需要在写出之前将其转换为 type。以下示例显示了执行
转换:ItemProcessor
ItemProcessor
ItemReader
Foo
Bar
ItemProcessor
public class Foo {}
public class Bar {
public Bar(Foo foo) {}
}
public class FooProcessor implements ItemProcessor<Foo, Bar> {
public Bar process(Foo foo) throws Exception {
//Perform simple transformation, convert a Foo to a Bar
return new Bar(foo);
}
}
public class BarWriter implements ItemWriter<Bar> {
public void write(Chunk<? extends Bar> bars) throws Exception {
//write bars
}
}
在前面的示例中,有一个名为 、 名为 的类 和一个类
named 的 API 执行该接口。转换是
很简单,但任何类型的转换都可以在这里完成。写入对象,如果提供了任何其他类型,则引发异常。同样,如果提供了除 a 之外的任何内容,则 the 会引发异常。然后,可以将 注入到 中,如下例所示:Foo
Bar
FooProcessor
ItemProcessor
BarWriter
Bar
FooProcessor
Foo
FooProcessor
Step
<job id="ioSampleJob">
<step name="step1">
<tasklet>
<chunk reader="fooReader" processor="fooProcessor" writer="barWriter"
commit-interval="2"/>
</tasklet>
</step>
</job>
@Bean
public Job ioSampleJob(JobRepository jobRepository) {
return new JobBuilder("ioSampleJob", jobRepository)
.start(step1())
.build();
}
@Bean
public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new StepBuilder("step1", jobRepository)
.<Foo, Bar>chunk(2, transactionManager)
.reader(fooReader())
.processor(fooProcessor())
.writer(barWriter())
.build();
}
和 or 之间的区别在于 an 对于 .ItemProcessor
ItemReader
ItemWriter
ItemProcessor
Step
链接 ItemProcessors
在许多情况下,执行单个转换都很有用,但如果您想
将多个实现“链接”在一起?您可以通过使用
前面提到的复合模式。要更新上一个
转换(例如)转换为 ,后者被转换为并写出,如下例所示:ItemProcessor
Foo
Bar
Foobar
public class Foo {}
public class Bar {
public Bar(Foo foo) {}
}
public class Foobar {
public Foobar(Bar bar) {}
}
public class FooProcessor implements ItemProcessor<Foo, Bar> {
public Bar process(Foo foo) throws Exception {
//Perform simple transformation, convert a Foo to a Bar
return new Bar(foo);
}
}
public class BarProcessor implements ItemProcessor<Bar, Foobar> {
public Foobar process(Bar bar) throws Exception {
return new Foobar(bar);
}
}
public class FoobarWriter implements ItemWriter<Foobar>{
public void write(Chunk<? extends Foobar> items) throws Exception {
//write items
}
}
A 和 a 可以“链接”在一起以得到结果,如以下示例所示:FooProcessor
BarProcessor
Foobar
CompositeItemProcessor<Foo,Foobar> compositeProcessor =
new CompositeItemProcessor<Foo,Foobar>();
List itemProcessors = new ArrayList();
itemProcessors.add(new FooProcessor());
itemProcessors.add(new BarProcessor());
compositeProcessor.setDelegates(itemProcessors);
与前面的示例一样,您可以将复合处理器配置为:Step
<job id="ioSampleJob">
<step name="step1">
<tasklet>
<chunk reader="fooReader" processor="compositeItemProcessor" writer="foobarWriter"
commit-interval="2"/>
</tasklet>
</step>
</job>
<bean id="compositeItemProcessor"
class="org.springframework.batch.item.support.CompositeItemProcessor">
<property name="delegates">
<list>
<bean class="..FooProcessor" />
<bean class="..BarProcessor" />
</list>
</property>
</bean>
@Bean
public Job ioSampleJob(JobRepository jobRepository) {
return new JobBuilder("ioSampleJob", jobRepository)
.start(step1())
.build();
}
@Bean
public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new StepBuilder("step1", jobRepository)
.<Foo, Foobar>chunk(2, transactionManager)
.reader(fooReader())
.processor(compositeProcessor())
.writer(foobarWriter())
.build();
}
@Bean
public CompositeItemProcessor compositeProcessor() {
List<ItemProcessor> delegates = new ArrayList<>(2);
delegates.add(new FooProcessor());
delegates.add(new BarProcessor());
CompositeItemProcessor processor = new CompositeItemProcessor();
processor.setDelegates(delegates);
return processor;
}
筛选记录
项目处理器的一个典型用途是在将记录传递给
这。筛选是一种不同于跳过的操作。跳过表示
记录无效,而筛选表示记录不应无效
写。ItemWriter
例如,考虑一个批处理作业,它读取包含三种不同类型的
记录:要插入的记录、要更新的记录和要删除的记录。如果记录删除
不受系统支持,我们不希望将任何可删除的记录发送到
这。但是,由于这些记录实际上并不是不良记录,因此我们希望
过滤掉它们而不是跳过它们。因此,将只接收
可插入和可更新的记录。ItemWriter
ItemWriter
要筛选记录,您可以从 .框架检测
,并避免将该项目添加到传递到
这。从
跳。null
ItemProcessor
null
ItemWriter
ItemProcessor
验证输入
ItemReaders和ItemWriters一章讨论了解析 Importing 的多种方法。
如果每个主要实现不是 “格式正确” ,则会引发异常。如果缺少数据范围,则引发异常。同样地
尝试访问不存在的 OR 中的索引,或者
的格式与预期的格式不同,会导致引发异常。全部
这些类型的异常在 return 之前引发。但是,它们没有解决
返回的项目是否有效的问题。例如,如果其中一个字段
是一个年龄,它不能是负数。它可能会正确解析,因为它存在并且
是一个数字,但不会导致异常。由于已经有大量的
验证框架,Spring Batch 不会尝试提供另一个。相反,它
提供了一个名为 的简单接口,您可以通过任意数量的
frameworks,如下面的接口定义所示:FixedLengthTokenizer
RowMapper
FieldSetMapper
read
Validator
public interface Validator<T> {
void validate(T value) throws ValidationException;
}
协定是,如果对象无效,该方法将引发异常
如果有效,则正常返回。Spring Batch 提供了一个 ,如下面的 bean 定义所示:validate
ValidatingItemProcessor
<bean class="org.springframework.batch.item.validator.ValidatingItemProcessor">
<property name="validator" ref="validator" />
</bean>
<bean id="validator" class="org.springframework.batch.item.validator.SpringValidator">
<property name="validator">
<bean class="org.springframework.batch.sample.domain.trade.internal.validator.TradeValidator"/>
</property>
</bean>
@Bean
public ValidatingItemProcessor itemProcessor() {
ValidatingItemProcessor processor = new ValidatingItemProcessor();
processor.setValidator(validator());
return processor;
}
@Bean
public SpringValidator validator() {
SpringValidator validator = new SpringValidator();
validator.setValidator(new TradeValidator());
return validator;
}
您还可以使用 来验证注释
Bean 验证 API (JSR-303) 注释。例如,请考虑以下类型:BeanValidatingItemProcessor
Person
class Person {
@NotEmpty
private String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
您可以通过在
application context 并在面向 chunk 的步骤中将其注册为处理器:BeanValidatingItemProcessor
@Bean
public BeanValidatingItemProcessor<Person> beanValidatingItemProcessor() throws Exception {
BeanValidatingItemProcessor<Person> beanValidatingItemProcessor = new BeanValidatingItemProcessor<>();
beanValidatingItemProcessor.setFilter(true);
return beanValidatingItemProcessor;
}