spring cloud stream
创建spring boot工程,添加pom依赖

<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-stream-rabbit</artifactId> </dependency>
添加消息接收SinkReceiver

import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.cloud.stream.annotation.EnableBinding; import org.springframework.cloud.stream.annotation.StreamListener; import org.springframework.cloud.stream.messaging.Sink; @EnableBinding(Sink.class) public class SinkReceiver { private static Logger logger= LoggerFactory.getLogger(SinkReceiver.class); @StreamListener(Sink.INPUT) public void receive(Object payload){ logger.info("Received: "+payload); } }
配置

spring.application.name=stream-hello spring.rabbitmq.host=10.202.203.29 spring.rabbitmq.port=5672 spring.rabbitmq.username=springcloud spring.rabbitmq.password=123456
运行程序,打开rabbitmq监控界面,可以看到
推送消息
在控制台查看结果
创建一个消息发送类SinkSender

import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.cloud.stream.annotation.EnableBinding; import org.springframework.cloud.stream.messaging.Sink; import org.springframework.context.annotation.Bean; import org.springframework.integration.annotation.InboundChannelAdapter; import org.springframework.integration.annotation.Poller; import org.springframework.integration.core.MessageSource; import org.springframework.messaging.support.GenericMessage; import java.util.Date; @EnableBinding(value = {Sink.class}) public class SinkSender { private static Logger logger= LoggerFactory.getLogger(SinkSender.class); @Bean @InboundChannelAdapter(value = Sink.INPUT,poller = @Poller(fixedDelay = "2000")) public MessageSource<Date> timerMessageSource(){ return ()-> new GenericMessage<>(new Date()); } }
启动工程,可以在控制台看到每隔2秒收到信息
在SinkSender中添加日期转换

@Transformer(inputChannel = Sink.INPUT,outputChannel = Sink.INPUT) public Object transform(Date message){ return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(message); }
控制台查看消息
添加一个User类

public class User { private Integer id; private String name; private Integer age; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
修改SinkSender

@Bean @InboundChannelAdapter(value = Sink.INPUT,poller = @Poller(fixedDelay = "2000")) public MessageSource<String> timerMessageSource(){ return ()->new GenericMessage<>("{\"id\":1,\"name\":\"tom\",\"age\":20}"); }
修改SinkReceiver

@ServiceActivator(inputChannel = Sink.INPUT) public void receive(User user){ logger.info("Received: "+user); } @Transformer(inputChannel = Sink.INPUT,outputChannel = Sink.INPUT) public User transform(String message) throws Exception { ObjectMapper objectMapper=new ObjectMapper(); User user=objectMapper.readValue(message,User.class); return user; }
这里使用@ServiceActivator必须指定@Transformer来处理自定义对象
改成就无需自定义@Transformer

@StreamListener(Sink.INPUT) public void receive(User user){ logger.info("Received: "+user); }
消息反馈
按上面项目再新建两个项目:App1和App2
App1

import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.cloud.stream.annotation.EnableBinding; import org.springframework.cloud.stream.annotation.StreamListener; import org.springframework.cloud.stream.messaging.Processor; import org.springframework.messaging.handler.annotation.SendTo; @EnableBinding(value = {Processor.class}) public class App1 { private static Logger logger= LoggerFactory.getLogger(App1.class); @StreamListener(Processor.INPUT) @SendTo(Processor.OUTPUT) public Object receiveFromInput(Object payload){ logger.info("Received: "+payload); return "From Input Channel Return - "+payload; } }
App2

import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.cloud.stream.annotation.EnableBinding; import org.springframework.cloud.stream.annotation.StreamListener; import org.springframework.cloud.stream.messaging.Processor; import org.springframework.context.annotation.Bean; import org.springframework.integration.annotation.InboundChannelAdapter; import org.springframework.integration.annotation.Poller; import org.springframework.integration.core.MessageSource; import org.springframework.messaging.support.GenericMessage; import java.util.Date; @EnableBinding(value = {Processor.class}) public class App2 { private static Logger logger= LoggerFactory.getLogger(App2.class); @Bean @InboundChannelAdapter(value = Processor.OUTPUT,poller = @Poller(fixedDelay = "2000")) public MessageSource<Date> timeMessageSource(){ return ()->new GenericMessage<>(new Date()); } @StreamListener(Processor.INPUT) public void receiveFromOutput(Object payload){ logger.info("Received: "+payload); } }
App2的配置做个变更

spring.rabbitmq.host=10.202.203.29 spring.rabbitmq.port=5672 spring.rabbitmq.username=springcloud spring.rabbitmq.password=123456 spring.cloud.stream.bindings.input.destination=output spring.cloud.stream.bindings.output.destination=input server.port=8001
启动两个项目
消费组
启动多个消费端App1和一个生产端App2,可以看到App2发送的消息被多个App1接收并处理
通过指定group可以然消息只被相应的group接收
App1-1
spring.cloud.stream.bindings.input.group=Service-A
App1-2
spring.cloud.stream.bindings.input.group=Service-A
App2
spring.cloud.stream.bindings.input.group=Service-A
这样App2发送的消息将被两个App1轮询处理
如果此时添加一个App1-3
spring.cloud.stream.bindings.input.group=Service-B
从rabbitmq管理界面查看
一个exchange绑定了两个queue,从exchange里推送一条消息,两个queue里都会有
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· [AI/GPT/综述] AI Agent的设计模式综述
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!