Stream进阶篇-StreamListener实现多个方法调度

前言
在《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方法监听头信息中 flagaa的消息, userReceiveByHeader2方法监听头信息中 flagbb的消息:
/*********************************实现多个监听者应用******************************/
@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 注解的方法均符合条件,则会被重复消费。




你可能感兴趣的:(springcloud)