重复模板
批处理是关于重复操作的,无论是作为简单的优化还是作为一部分 的工作。制定战略和概括重复,并提供相当于 迭代器框架,Spring Batch具有接口。该接口具有以下定义:RepeatOperationsRepeatOperations
public interface RepeatOperations { RepeatStatus iterate(RepeatCallback callback) throws RepeatException;}回调是一个接口,如以下定义所示,允许您插入 一些要重复的业务逻辑:
public interface RepeatCallback { RepeatStatus doInIteration(RepeatContext context) throws Exception;}重复执行回调,直到实现确定 迭代应结束。这些接口中的返回值是一个枚举值,它可以 为 或 。枚举向重复操作的调用方传达有关是否 任何工作都留下来。一般来说,实现应该检查并使用它作为结束 迭 代。任何希望向调用方发出没有工作的信号的回调仍然存在 可以返回.RepeatStatus.CONTINUABLERepeatStatus.FINISHEDRepeatStatusRepeatOperationsRepeatStatusRepeatStatus.FINISHED
最简单的通用实现是:RepeatOperationsRepeatTemplate
RepeatTemplate template = new RepeatTemplate();template.setCompletionPolicy(new SimpleCompletionPolicy(2));template.iterate(new RepeatCallback() { public RepeatStatus doInIteration(RepeatContext context) { // Do stuff in batch... return RepeatStatus.CONTINUABLE; }});在前面的示例中,我们返回 ,以表明存在 还有更多的工作要做。回调也可以返回 ,以向 呼叫者说没有工作仍然存在。某些迭代可以通过以下方式终止 回调中正在完成的工作所固有的注意事项。其他是有效的 无限循环(就回调而言),完成决策为 委派给外部策略,如前面示例中所示的情况。RepeatStatus.CONTINUABLERepeatStatus.FINISHED
重复上下文
的方法参数为 .许多回调忽略 上下文。但是,如有必要,您可以将其用作属性包来存储瞬态 迭代期间的数据。方法返回后,上下文 不再存在。RepeatCallbackRepeatContextiterate
如果正在进行嵌套迭代,则 具有父上下文。这 父上下文有时可用于存储需要在之间共享的数据 调用 。例如,如果您想计算 事件在迭代中出现,并在后续调用中记住它。RepeatContextiterate
重复状态
RepeatStatus是 Spring 批处理用于指示处理是否具有的枚举 完成。它有两个可能的值:RepeatStatus
表 1.重复状态属性
价值
描述
CONTINUABLE
还有更多的工作要做。
FINISHED
不应再重复。
可以使用 中的方法将值与逻辑 AND 运算组合在一起。这样做的效果是对 可连续标志。换言之,如果任一状态为 ,则结果为 。RepeatStatusand()RepeatStatusFINISHEDFINISHED
完成政策
在 a 中,方法中循环的终止为 由 确定,这也是 的工厂。负责使用当前策略创建并将其传递给迭代的每个阶段。 回调完成后,必须进行调用 以要求它更新其状态(将存储在 中)。然后,它会询问策略迭代是否完成。RepeatTemplateiterateCompletionPolicyRepeatContextRepeatTemplateRepeatContextRepeatCallbackdoInIterationRepeatTemplateCompletionPolicyRepeatContext
Spring Batch 提供了一些简单的通用实现。 允许执行固定次数(随时强制提前完成)。CompletionPolicySimpleCompletionPolicyRepeatStatus.FINISHED
用户可能需要为更复杂的实现自己的完成策略 决定。例如,阻止批处理作业执行的批处理窗口 一旦使用在线系统,就需要自定义策略。
异常处理
如果在 中抛出异常,则咨询 一个 ,可以决定是否重新引发异常。RepeatCallbackRepeatTemplateExceptionHandler
以下清单显示了接口定义:ExceptionHandler
public interface ExceptionHandler { void handleException(RepeatContext context, Throwable throwable) throws Throwable;}一个常见的用例是计算给定类型的异常数,并在 已达到限制。为此,Spring Batch 提供了 和 稍微灵活一点 .有限制 属性和应与当前异常进行比较的异常类型。都 所提供类型的子类也被计算在内。给定类型的例外情况是 忽略,直到达到限制,然后重新抛出它们。其他类型的例外 总是被重新抛出。SimpleLimitExceptionHandlerRethrowOnThresholdExceptionHandlerSimpleLimitExceptionHandler
的一个重要可选属性是布尔标志 叫。这是默认的,因此限制仅在 当前。设置为 时,限制将跨同级上下文保持 嵌套迭代(例如步骤中的一组区块)。SimpleLimitExceptionHandleruseParentfalseRepeatContexttrue
听众
通常,能够接收跨领域关注点的其他回调很有用 跨多个不同的迭代。为此,Spring Batch提供了接口。允许用户注册实现,并在迭代期间通过 和 位置向他们提供回调。RepeatListenerRepeatTemplateRepeatListenerRepeatContextRepeatStatus
该接口具有以下定义:RepeatListener
public interface RepeatListener { void before(RepeatContext context); void after(RepeatContext context, RepeatStatus result); void open(RepeatContext context); void onError(RepeatContext context, Throwable e); void close(RepeatContext context);}和回调在整个迭代之前和之后出现。、 ,并应用于各个调用。openclosebeforeafteronErrorRepeatCallback
请注意,当有多个侦听器时,它们位于一个列表中,因此有一个 次序。在本例中,和 以相同的顺序调用,而 、 和 以相反的顺序调用。openbeforeafteronErrorclose
并行处理
的实现不限于执行回调 顺序。一些实现能够执行其 并行回调。为此,Spring Batch 提供了 ,它使用 Spring 策略来运行 .默认使用 ,具有 在同一线程中执行整个迭代(与普通线程相同)。RepeatOperationsTaskExecutorRepeatTemplateTaskExecutorRepeatCallbackSynchronousTaskExecutorRepeatTemplate
声明性迭代
有时,您知道每次都想重复一些业务处理 它发生了。这方面的典型示例是消息管道的优化。 如果一批消息频繁到达,则处理它们比处理它们更有效 承担每条消息的单独事务费用。春季批处理提供 AOP 为此将方法调用包装在对象中的拦截器 目的。执行截获的方法并重复 根据在提供的.RepeatOperationsRepeatOperationsInterceptorCompletionPolicyRepeatTemplate
以下示例显示了使用 Spring AOP 命名空间的声明式迭代 对名为 (有关如何 配置 AOP 拦截器,请参阅 <<https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#aop,Spring 用户指南>>):processMessage
<aop:config> <aop:pointcut id="transactional" expression="execution(* com..*Service.processMessage(..))" /> <aop:advisor pointcut-ref="transactional" advice-ref="retryAdvice" order="-1"/></aop:config><bean id="retryAdvice" class="org.spr...RepeatOperationsInterceptor"/>以下示例使用 Java 配置来 对名为 (有关如何 配置 AOP 拦截器,请参阅 <<https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#aop,Spring 用户指南>>):processMessage
@Beanpublic MyService myService() { ProxyFactory factory = new ProxyFactory(RepeatOperations.class.getClassLoader()); factory.setInterfaces(MyService.class); factory.setTarget(new MyService()); MyService service = (MyService) factory.getProxy(); JdkRegexpMethodPointcut pointcut = new JdkRegexpMethodPointcut(); pointcut.setPatterns(".*processMessage.*"); RepeatOperationsInterceptor interceptor = new RepeatOperationsInterceptor(); ((Advised) service).addAdvisor(new DefaultPointcutAdvisor(pointcut, interceptor)); return service;}前面的示例在侦听器中使用默认值。要更改 策略、侦听器和其他详细信息,您可以将 的实例注入到拦截器中。RepeatTemplateRepeatTemplate
如果截获的方法返回,拦截器总是返回(所以如果 没有有限的端点,则存在无限循环的危险)。否则,它将返回,直到截获方法的返回值为 。 此时,它返回 .因此,业务逻辑 在 Target 方法内部,可以通过返回或抛出由提供的 .voidRepeatStatus.CONTINUABLECompletionPolicyRepeatStatus.CONTINUABLEnullRepeatStatus.FINISHEDnullExceptionHandlerRepeatTemplate