4.0以下版本
1. 发布消息
1.1定时发送消息
1.1.1 导入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
1.1.2 配置类及配置文件
从3.1 开始,推荐使用函数式编程模式定义消息的生产者和消费者,Spring上下文中实现了Supplier的Bean会自动成文消息生产者:
@Configuration
public class MessageSender {
@Bean
public Supplier<Sample> sample1() {
return () -> new Sample(1, "Supplier");
}
}
创建一个名为sample-out-0的绑定,这个绑定通过具体的绑定器实现(如:RabbitMQ Binder)映射到具体的消息中间件目标上。RabbitMQ Binder的实现中,默认映射为一个名称为sample-out-0的Topic类型交换器,可以在配置文件中配置绑定对应的目标名称。
#spring.cloud.stream.bindings.绑定名称.destination=目标名称
spring.cloud.stream.bindings.sample1-out-0.destination=sample1
创建一个消息生产者,默认每秒调用一次返回的Supplier对象的get方法,然后将get返回的数据发送到sample-out-0的绑定器对应的目标。轮询相关属性可以通过spring.integration.poller开头的属性配置。
注意:绑定器实现了Spring Cloud Stream与消息中间件之间的隔离,从而可以随意切换使用的消息中间件。绑定实现了我们的代码与消息中间件具体目标的隔离,也是说在代码中我们操作的是绑定。绑定对应于消息中间件的什么目标,是有具体的绑定器决定的
配置文件
spring:
rabbitmq: ##配置rabbitmq的信息
host: 192.168.5.104
port: 5672
username: rabbitmq
password: rabbitmq
cloud:
stream:
bindings: ## 配置绑定的目标
sample1-out-0:
destination: sample1
function: ## 配置哪些实现了函数式接口的bean要做为消息生成者,默认所有实现了Supplier接口的Beandefinition: sample1
1.2 主动发送消息
1.1 导入依赖
同定时发送消息的依赖
1.2 配置类及配置文件
import org.springframework.cloud.stream.function.StreamBridge;
@Configuration
public class MessageSender {
@Autowired
private StreamBridge streamBridge;
/**
* 发送任意数据,如果绑定不存在则创建
*/
public void sample2(Sample sample) {
streamBridge.send("sample2-out-0", sample);
}
}
配置文件
spring:
rabbitmq: ##配置rabbitmq的信息
...
cloud:
stream:
bindings: ## 配置绑定相关的名称
...
sample2-out-0:
destination: sample2
2. 消费消息
2.1 导入依赖
同发布消息的依赖
2.2 配置类及配置文件
@Component
/*@EnableBinding可以加在任一个配置类中*/
@EnableBinding(SampleMessage.class)
public class StreamConfigurer {
}
/*注意:在配置类中通过@EnableBinding(SampleMessage.class)声明绑定*/
public interface SampleMessage {
String SAMPLE_1 = "sample1";
String SAMPLE_2 = "sample2";
/*可以通过spring.cloud.stream.bindings.绑定名称.destination=目标名称配置绑定对应的
目标名称*/
@Input(SAMPLE_1)
SubscribableChannel receiveMessage1();
@Input(SAMPLE_2)
SubscribableChannel receiveMessage2();
}
@Input(SAMPLE_1)
- 声明一个订阅消息的绑定,基于RabbitMQ实现时,会在RabbitMQ中创建一个队列和一个绑定到队列的交换器,如果交换器已经创建,则直接绑定。
- 默认的队列名为:绑定的目标名称.消费组名称,默认的绑定的目标名称为绑定名称(如:sample1);默认的消费组名称为anonymous.唯一序列码。绑定的目标名称和消费组名称是可配置的
- 默认的交换器名为:绑定的目标名称。修改绑定的目标名称spring.cloud.stream.bindings.
绑定名称.destination=目标名称
注意:声明了SubscribableChannel 就要通过@StreamListener生成消息监听器,否则获取到消息后程序不知道如果处理。
配置文件
##配置rabbitmq的信息
spring.rabbitmq.host=192.170.2.177
spring.rabbitmq.port=5672
spring.rabbitmq.username=rabbitmq
spring.rabbitmq.password=rabbitmq
2.3 消费消息
@Component
public class SampleListener {
private static final Logger logger = LogManager.getLogger();
/*@StreamListener要有对应的@Input*/
@StreamListener(SampleMessage.SAMPLE_1)
public void listenerMessage1(Sample sample) {
logger.info("收到消息1:{},绑定的名称:{}", sample, SampleMessage.SAMPLE_1);
}
/*注意:如果订阅的是同一个目标,则返回值要一样*/
@StreamListener(SampleMessage.SAMPLE_2)
@SendTo({SampleMessage.SAMPLE_1})
public Sample listenerMessage2(Sample sample) {
logger.info("收到消息2:{},绑定的名称:{},回复消息给:{}", sample,
SampleMessage.SAMPLE_2,
SampleMessage.SAMPLE_1);
sample.setMessage("消息已经消费");
return sample;
}
}
4.0以上版本
4.0以上版本删除了消费消息的注解,如@EnableBinding,@Input等
消费消息
1. 导入依赖
同上(只是版本不同)
2. 配置类及配置文件
配置类中可以@Bean实例化实现了Consumer< sample >接口的对象并重写该函数式接口的唯一抽象方法。
但是在配置类中消费消息不是很合适。所以可以实例化一个实现了Consumer< sample >的类并重写accept方法作为消费消息的方法。并用配置类扫描该类。
@Component
public class SampleConsumer implements Consumer<Sample> {
private static final Logger logger = LoggerFactory.getLogger(SampleConsumer .class);
@Autowired
private ProductsService productsService;
@Override
public void accept(Sample sample) {
logger.warn("sample:{}",sample);
}
}
注意:
实现Consumer接口的类会在RabbitMQ中创建一个同类名的交换器和对应绑定队列,实际上与消息生产者没有任何关系,所以需要将消息转换器的名字与消息生产者相同。
4.0之后修改交换器名的配置也有所不同
配置文件
spring.cloud.stream.bindings.sampleConsumer-in-0.destination=sample1#修改转换器名同消息生产者一致