


1.引入spring cloud, spring cloud alibaba, spring boot依赖
<!-- SpringCloud 微服务 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2020.0.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- SpringCloud Alibaba 微服务 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2021.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- SpringBoot 依赖配置 -->
<!--<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.4.2</version>
<type>pom</type>
<scope>import</scope>
</dependency>-->
2.引入spring cloud stream rabbit依赖
<!-- spring cloud stream RabbitMQ -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
3. 配置
spring:
cloud:
stream:
binders:
default-rabbit:
type: rabbit
environment:
spring:
rabbitmq:
host: ${RABBITMQ_HOST:xx}
port: ${RABBITMQ_PORT:5672}
username: xx
password: xx
bindings:
#MQ生产者
test-out-0:
destination: test-topic
content-type: application/json
binder: default-rabbit
#MQ消费者
test1-in-0:
destination: test-topic
group: test1-group
content-type: application/json
binder: default-rabbit
#MQ消费者
test2-in-0:
destination: test-topic
group: test2-group
content-type: application/json
binder: default-rabbit
rabbit:
bindings:
test-out-0:
producer:
routingKeyExpression: headers.type
exchange-type: direct
test1-in-0:
consumer:
bindingRoutingKey: k1
exchange-type: direct
acknowledge-mode: AUTO
test2-in-0:
consumer:
bindingRoutingKey: k2
exchange-type: direct
acknowledge-mode: AUTO
#消费者方法名
function:
definition: test1;test2;

4 生产者代码
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.function.StreamBridge;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpStatus;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
@Autowired
private StreamBridge streamBridge;
@ApiOperation("动态解析并发送消息到指定名称的通道")
@PostMapping("test/send/{destination}/{routingKey}")
@ResponseStatus(HttpStatus.ACCEPTED)
public void send(@PathVariable String destination, @PathVariable String routingKey){
Map<String,String> payload = new HashMap<>();
payload.put("key1", "value1");
payload.put("key2", "value2");
Message<Map<String, String>> message = MessageBuilder
.withPayload(payload)
.setHeader("type", routingKey)
.build();
streamBridge.send(destination, message);
}
// 请求 : http://localhost/test/send/test-out-0/k2
@ApiOperation("动态解析并发送消息到指定名称的通道")
@PostMapping("test/send/{destination}")
@ResponseStatus(HttpStatus.ACCEPTED)
public void send2(@PathVariable String destination){
Map<String,String> message = new HashMap<>();
message.put("key1", "value1");
message.put("key2", "value2");
streamBridge.send(destination, message);
}
5 消费者
@Bean
public Consumer test1() {
return request -> {
log.info("test1 MQ消费 req:{}", request);
};
}
@Bean
public Consumer test2() {
return request -> {
log.info("test2 MQ消费 req:{}", request);
};
}
6 源码分析
生产者发送源码分析:
org.springframework.cloud.stream.function.StreamBridge#send
SubscribableChannel messageChannel = org.springframework.cloud.stream.function.StreamBridge#resolveDestination 封装channel
SubscribableChannel messageChannel = new DirectWithAttributesChannel();
Binding<T> binding = org.springframework.cloud.stream.binding.BindingService#bindProducer
org.springframework.cloud.stream.binding.BindingService#getBinder
org.springframework.cloud.stream.binder.DefaultBinderFactory#getBinder
org.springframework.cloud.stream.binder.DefaultBinderFactory#doGetBinder
org.springframework.cloud.stream.binder.DefaultBinderFactory#getBinderInstance
1.得到RabbitMessageChannelBinder,启动时注入的org.springframework.cloud.stream.binder.rabbit.config.RabbitMessageChannelBinderConfiguration
2.得到DefaultBinderFactory, 启动时注入的org.springframework.cloud.stream.config.BindingServiceConfiguration
org.springframework.cloud.stream.binding.BindingService#doBindProducer
org.springframework.cloud.stream.binder.AbstractMessageChannelBinder#doBindProducer
org.springframework.cloud.stream.binder.AbstractMessageChannelBinder#createProducerMessageHandler
org.springframework.cloud.stream.binder.rabbit.RabbitMessageChannelBinder#createProducerMessageHandler
MessageHandler endpoint = new AmqpOutboundEndpoint()