Spring集成路由到不同类的子流

时间:2018-10-04 12:20:03

标签: java spring-integration

我正在努力几天以完成这项工作。我要完成的工作是基于消息内容从主流程调用不同的子流程(即集成流程),子流程完成后返回主流程。就像委派特定班级的职责一样,它可以完成某些工作并返回主流。该责任还可能需要一些步骤,因此它也将按照流程实施。这是我的主要流程:

public IntegrationFlow processingFlow(
  MessageChannel eventIn,
  MessageChannel eventOut,
  ChangedEventsLoader changedEventsLoader,
  CalculatorRouter calculatorRouter) {

return IntegrationFlows.from(eventIn)
    .handle(changedEventsLoader)
    .route(
        CalculatorRouter::getSportId,
        CalculatorRouter::routeCalculation)
    .channel(eventOut)
    .get();

}

这是路由器的实现:

@Service
@AllArgsConstructor
public class CalculatorRouter {
  private final MessageChannel eventOut;

  public RouterSpec<Integer, MethodInvokingRouter> routeCalculation(
      RouterSpec<Integer, MethodInvokingRouter> mapping) {
    return mapping
        .channelMapping(1, "subflowCalculationChannel")
        .defaultOutputToParentFlow();
  }

  public Integer getSportId(Event event) {
    return 1;
  }

  @Bean
  public MessageChannel subflowCalculationChannel() {
    return MessageChannels.direct().get();
  }
}

这是一个子流的示例:

@Configuration
@AllArgsConstructor
public class CalculatorExample {

  @Bean
  public IntegrationFlow calculateProbabilities(MessageChannel subflowCalculationChannel) {
    return IntegrationFlows.from(subflowCalculationChannel)
        .<Event>handle((p, m) -> p * 2)
        .get();
  }
}

问题在于子流缺少与主流的某种联系。我试图通过在路由部分中使用defaultOutputToParentFlow()来解决此问题,但这还不够。

1 个答案:

答案 0 :(得分:1)

从某个版本开始,我们决定使Java DSL路由器的行为与带有注释或XML的标准配置保持一致。因此,如果我们发送到路由器,则无法期望从那里得到答复。我们只能继续使用该通道作为子流的输出。

在您的情况下,主流中有一个.channel(eventOut)。因此,您所有的路由子流都应准确答复此通道:

    .<Event>handle((p, m) -> corners1H2HCustomBet.getCalculation(p))
    .channel(eventOut)
    .get();

我认为.defaultOutputToParentFlow();不能为您做任何事情,因为您没有默认映射。故事已经有些不同了:它对其他映射没有任何影响。

还要注意此JavaDoc:

/**
 * Add a subflow as an alternative to a {@link #channelMapping(Object, String)}.
 * {@link #prefix(String)} and {@link #suffix(String)} cannot be used when subflow
 * mappings are used.
 * <p> If subflow should refer to the external {@link IntegrationFlow} bean and
 * there is a requirement to expect reply from there, such a reference should be
 * wrapped with a {@code .gateway()}:
 * <pre class="code">
 * {@code
 *     .subFlowMapping(false, sf -> sf.gateway(evenFlow())))
 * }
 * </pre>
 * @param key the key.
 * @param subFlow the subFlow.
 * @return the router spec.
 */
public RouterSpec<K, R> subFlowMapping(K key, IntegrationFlow subFlow) {

与基于通道的路由配置无关,但将来可能会有用。

更新

这里是subFlowMapping的样本(科特琳),返回到主要流程:

    @Bean
    fun splitRouteAggregate() =
            IntegrationFlow { f ->
                f.split()
                        .route<Int, Boolean>({ o -> o % 2 == 0 },
                                { m ->
                                    m.subFlowMapping(true) { sf -> sf.gateway(oddFlow()) }
                                            .subFlowMapping(false) { sf -> sf.gateway(evenFlow()) }
                                })
                        .aggregate()
            }

    @Bean
    fun oddFlow() =
            IntegrationFlow { flow ->
                flow.handle<Any> { _, _ -> "odd" }
            }

    @Bean
    fun evenFlow() =
            IntegrationFlow { flow ->
                flow.handle<Any> { _, _ -> "even" }
            }