我想允许呼叫者传递外部routing slip,例如通过发布:
POST http://localhost:8080/transform?routing-slip=capitalize&routing-slip=lowercase
Content-Type: text/plain
camelCase
应该可以使用给定的路由清单数组作为pojo的外部路由清单:
@Bean
public IntegrationFlow transformerChain(RoutingSlipRouteStrategy routeStrategy) {
return IntegrationFlows.from(
Http.inboundGateway("/transform")
.headerExpression("routingSlipParam",
"#requestParams['routing-slip']")
.requestPayloadType(String.class))
.enrichHeaders(spec -> spec.header(
IntegrationMessageHeaderAccessor.ROUTING_SLIP,
new RoutingSlipHeaderValueMessageProcessor(
"@routePojo.get(request, reply)")
)
)
.logAndReply();
}
pojo可以访问routingSlipParam
标头,然后您会认为它可以将单据保持为内部状态,或者至少是TestRoutingSlipRoutePojo促使我相信的,所以我构建了这个(鉴于pojo仅有一个实例,对此有一点疑问:
public class ExternalRoutingSlipRoutePojo {
private List<String> routingSlip;
private int i = 0;
public String get(Message<?> requestMessage, Object reply) {
if (routingSlip == null) {
routingSlip = (LinkedList)requestMessage.getHeaders()
.get("routingSlipParam");
}
try {
return this.routingSlip.get(i++);
} catch (Exception e) {
return null;
}
}
}
事实证明,它只能运行一次,这并不奇怪-毕竟对于每个传入消息,索引都会递增,并且路由清单不会更新。
所以我想,当然,我必须保留所有传入消息的内部状态并提出此RouteStrategy:
public class ExternalRoutingSlipRouteStrategy implements RoutingSlipRouteStrategy {
private Map<UUID, LinkedList<String>> routingSlips = new WeakHashMap<>();
private static final LinkedList EMPTY_ROUTINGSLIP = new LinkedList<>();
@Override
public Object getNextPath(Message<?> requestMessage,Object reply) {
MessageHeaders headers = requestMessage.getHeaders();
UUID id = headers.getId();
if (!routingSlips.containsKey(id)) {
@SuppressWarnings("unchecked")
List<String> routingSlipParam =
headers.get("routingSlipParam", List.class);
if (routingSlipParam != null) {
routingSlips.put(id,
new LinkedList<>(routingSlipParam));
}
}
LinkedList<String> routingSlip = routingSlips.getOrDefault(id,
EMPTY_ROUTINGSLIP);
String nextPath = routingSlip.poll();
if (nextPath == null) {
routingSlips.remove(id);
}
return nextPath;
}
}
这不起作用,因为不仅要为传入消息调用该策略,还要为动态路由创建的所有新消息(当然它们具有不同的ID)调用该策略。
但是原始消息仅被调用两次,因此路由清单永远不会被耗尽,并且应用程序会无限循环运行。
如何使用外部布线条使弹簧集成?
更新:
如Gary Russel所建议,外部路由清单索引或外部路由清单本身都不应该存储在Spring bean中,而是可以使用消息头针对每个请求分别维护它们:
Http.inboundGateway("/transform")
.headerExpression("routingSlipParam",
"#requestParams['routing-slip']")
.requestPayloadType(String.class))
.enrichHeaders(spec -> spec
.headerFunction("counter",h -> new AtomicInteger())
.header(IntegrationMessageHeaderAccessor.ROUTING_SLIP,
new RoutingSlipHeaderValueMessageProcessor(externalRouteStrategy)
)
)
externalRouteStrategy
是以下类的实例:
public class ExternalRoutingSlipRouteStrategy implements
RoutingSlipRouteStrategy {
@Override
public Object getNextPath(Message<?> requestMessage, Object reply) {
List<String> routingSlip = (List<String>)
requestMessage.getHeaders().get("routingSlipParam");
int routingSlipIndex = requestMessage.getHeaders()
.get("counter", AtomicInteger.class)
.getAndIncrement();
String routingSlipEntry;
if (routingSlip != null
&& routingSlipIndex < routingSlip.size()) {
routingSlipEntry = routingSlip.get(routingSlipIndex);
} else {
routingSlipEntry = null;
}
return routingSlipEntry;
}
}
作为参考,我已在Github中发布了示例。
答案 0 :(得分:1)
返回您的第一个版本,并将i
存储在邮件头扩展程序的邮件标题(AtomicInteger
)中。
.headerExpression("counter", "new java.util.concurrent.atomic.AtomicInteger()")
然后
int i = requestMessage.getHeaders().get("counter", AtomicInteger.class).getAndIncrement();