SpringCloud 使用@StreamListener进行基于内容的路由
Spring Cloud Stream支持根据条件将消息调度到用@StreamListener
注释的多个处理程序方法。
为了有资格支持条件分派,一种方法必须满足以下条件:
- 它不能返回值。
- 它必须是单独的消息处理方法(不支持反应性API方法)。
该条件由注释的condition
参数中的SpEL表达式指定,并针对每条消息进行评估。所有与条件匹配的处理程序都在同一线程中调用,并且不必假设调用的顺序。
在具有分配条件的@StreamListener
的以下示例中,所有带有标头type
且具有值bogey
的消息都被分配到receiveBogey
方法,所有带有标头{11的消息值bacall
的/}发送到receiveBacall
方法。
@EnableBinding(Sink.class) @EnableAutoConfiguration public static class TestPojoWithAnnotatedArguments { @StreamListener(target = Sink.INPUT, condition = "headers['type']=='bogey'") public void receiveBogey(@Payload BogeyPojo bogeyPojo) { // handle the message } @StreamListener(target = Sink.INPUT, condition = "headers['type']=='bacall'") public void receiveBacall(@Payload BacallPojo bacallPojo) { // handle the message } }
condition
上下文中的内容类型协商
了解使用@StreamListener
参数condition
的基于内容的路由背后的一些机制很重要,尤其是在整个消息类型的上下文中。如果在继续之前熟悉,内容类型协商,这也可能会有所帮助。
请考虑以下情形:
@EnableBinding(Sink.class) @EnableAutoConfiguration public static class CatsAndDogs { @StreamListener(target = Sink.INPUT, condition = "payload.class.simpleName=='Dog'") public void bark(Dog dog) { // handle the message } @StreamListener(target = Sink.INPUT, condition = "payload.class.simpleName=='Cat'") public void purr(Cat cat) { // handle the message } }
前面的代码是完全有效的。它可以毫无问题地进行编译和部署,但是永远不会产生您期望的结果。
这是因为您正在测试的东西在您期望的状态下尚不存在。这是因为消息的有效负载尚未从有线格式(byte[]
)转换为所需的类型。换句话说,它尚未经过,内容类型协商中描述的类型转换过程。
因此,除非使用SPeL表达式评估原始数据(例如,字节数组中第一个字节的值),否则请使用基于消息标头的表达式(例如condition = "headers['type']=='dog'"
)。
目前,仅基于通道的绑定程序(不支持响应编程)支持通过
@StreamListener
条件进行分派。
更多建议: