前言
在《Stream进阶篇-实体对象数据的生产消费与转换》章节,已经展示了如何获取header信息,本小节将更加具体的展示其特性,并结合
@StreamListener
注解的
condition
参数实现多个监听者方法的选择调度。场景描述:
如上图,sender服务发送消息至user-channel通道,如果头信息中flag值为aa则被StreamListener1接收;如果flag值为bb则被StreamListener2接收。
本章概要
1、获取header信息;
2、多监听方法调度;
获取header信息
通过官方,可以看到有除了
@Payload、@Headers之前还有一个
@Header注解,其能够获取指定头信息,下面是一个简单的示例:
1、在监听方法中添加
@Header注解应用,如下:
@StreamListener(value = MySink.USER_CHANNEL)
public void userReceive(@Payload User user, @Headers Map headers, @Header(name = "name") Object name) {
LOGGER.info(headers.get("contentType").toString());
LOGGER.info("name : {}", name.toString());
LOGGER.info("Received from {} channel username: {}", MySink.USER_CHANNEL, user.getUsername());
}
2、单元测试修改如下,在Header中添加了一个name属性:
@Test
public void myUserSenderTester() {
User user = new User().setUsername("shuaishuai").setAge(12);
userSender.userChannelSender().send(MessageBuilder.withPayload(ReflectionToStringBuilder.toString(user, ToStringStyle.JSON_STYLE))
.setHeader("name", "song").build());
}
3、执行单元测试:
小节:通过上述示例,可以看到
@Payload注解内容为消息体,
@Headers注解获取所有的Header头信息,
@Header注解获取指定name的头信息。
多监听方法调度
在消费实例方,可以定义多个监听方法对同一通道进行监听处理,但其需要在某些指定的条件下方可触发。恰好
@StreamListener
注解提供了
condition
参数作为条件设定,其支持
SpEL
表达式,通过条件约束即可满足我们的需求。具体示例如下:
1、添加如下两个监听方法,其中
userReceiveByHeader1方法监听头信息中
flag为
aa的消息,
userReceiveByHeader2方法监听头信息中
flag为
bb的消息:
/*********************************实现多个监听者应用******************************/
@StreamListener(value = MySink.USER_CHANNEL, condition = "headers['flag']=='aa'")
public void userReceiveByHeader1(@Payload User user) {
LOGGER.info("Received from {} channel : {} with head (flag:aa)", MySink.USER_CHANNEL, user.getUsername());
}
@StreamListener(value = MySink.USER_CHANNEL, condition = "headers['flag']=='bb'")
public void userReceiveByHeader2(@Payload User user) {
LOGGER.info("Received from {} channel : {} with head (flag:bb)", MySink.USER_CHANNEL, user.getUsername());
}
2、在单元测试消息发送时添加
flag头信息,如下值
aa:
@Test
public void myUserSenderTester() {
User user = new User().setUsername("shuaishuai").setAge(12);
userSender.userChannelSender().send(MessageBuilder.withPayload(ReflectionToStringBuilder.toString(user, ToStringStyle.JSON_STYLE))
.setHeader("name", "song")
.setHeader("flag","aa")
.build());
}
3、执行单元测试打印如下:
4、继续修改单元测试,设置
flag值为
bb:
@Test
public void myUserSenderTester() {
User user = new User().setUsername("shuaishuai").setAge(12);
userSender.userChannelSender().send(MessageBuilder.withPayload(ReflectionToStringBuilder.toString(user, ToStringStyle.JSON_STYLE))
.setHeader("name", "song")
.setHeader("flag","bb")
.build());
}
5、执行单元测试打印如下:
小节:在某些指定场景下,通过
condition
参数能够实现多个监听器在不同条件对监听通道的更多选择性处理。如果多个
@StreamListener
注解的方法均符合条件,则会被重复消费。