SpringCloudStream是SpringCloud中对于消息中间件操作的封装包,目前支持的消息中间件有RabbitMQ、Kafka,以下是SpringCloudStream的模型图。
从上图可以发现消息的发送由output接口提供,消息的接收由input输入。应用程序与消息中间件通过Binder进行链接。
SpringCloudStream是对消息中间件操作的再次封装,简化了消息中间件的细节,它可以使得我们对消息中间间无感知,使我们能够更加专注业务代码的开发。
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-stream-rabbitartifactId>
dependency>
spring:
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
cloud:
stream:
bindings:
input:
destination: myMsg
output:
destination: myMsg
package com.qingyun.order.server.message;
import org.springframework.cloud.stream.annotation.Input;
import org.springframework.cloud.stream.annotation.Output;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.SubscribableChannel;
public interface StreamClient {
static String INPUT="input";
static String OUTPUT="output";
@Input(StreamClient.INPUT)
SubscribableChannel input();
@Output(StreamClient.OUTPUT)
MessageChannel output();
}
package com.qingyun.order.server.message;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.stereotype.Component;
/**
* Created with IntelliJ IDEA.
* User: 李敷斌.
* Date: 2020-02-16
* Time: 18:16
* Explain:
*/
@EnableBinding(StreamClient.class)
@Component
@Slf4j
public class StreamReceiver {
@StreamListener(StreamClient.INPUT)
public void process(Object msg){
log.info("StreamReceiver msg={}",msg);
}
}
package com.qingyun.order.server.controller;
import com.qingyun.order.server.message.StreamClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
/**
* Created with IntelliJ IDEA.
* User: 李敷斌.
* Date: 2020-02-16
* Time: 18:17
* Explain:
*/
@RestController
public class SendMsgController {
@Autowired
private StreamClient streamClient;
@GetMapping(value = "sendMsg")
public void sendStreamMsg(){
String msg="now time="+new Date();
streamClient.output().send(MessageBuilder.withPayload(msg).build());
}
}
消息正常传达,那么这个时候我们就可以开启多个实例进行测试了。
查看RabbitMQ的控制面板可以发现此时有两个myMsg开头的队列,这个时候我们发起一次测试
spring.cloud.stream.bindings.名称.group
属性。spring:
cloud:
stream:
bindings:
input:
destination: myMsg
group: order-service
output:
destination: myMsg
group: order-service
从上图可以很清楚的发现,之前的随机字符串被替换成了我们添加的group属性值,并且两个实例都与它有关,这个时候我们发起一次测试,看看消息是否还会被重复消费。
StreamClient2
package com.qingyun.order.server.message;
import org.springframework.cloud.stream.annotation.Input;
import org.springframework.cloud.stream.annotation.Output;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.SubscribableChannel;
public interface StreamClient2 {
static String INPUT="input2";
static String OUTPUT="output2";
@Input(StreamClient2.INPUT)
SubscribableChannel input();
@Output(StreamClient2.OUTPUT)
MessageChannel output();
}
消息接收器
@EnableBinding(StreamClient2.class)
@Component
@Slf4j
public class StreamReceiver2 {
@StreamListener(StreamClient2.INPUT)
public void process(Object msg){
log.info("StreamReceiver2 msg={}",msg);
}
}
spring:
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
cloud:
stream:
bindings:
input:
destination: myMsg
group: order-service
output:
destination: myMsg
group: order-service
input2:
destination: myMsg2
group: order-service
output2:
destination: myMsg2
group: order-service
package com.qingyun.order.server.message;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Component;
/**
* Created with IntelliJ IDEA.
* User: 李敷斌.
* Date: 2020-02-16
* Time: 18:16
* Explain:
*/
@EnableBinding(StreamClient.class)
@Component
@Slf4j
public class StreamReceiver {
@StreamListener(StreamClient.INPUT)
@SendTo(StreamClient2.INPUT)
public boolean process(Object msg){
log.info("StreamReceiver msg={}",msg);
return true;
}
}
这里需要注意的是返回值只能是 true、false、null三者,否则将会引发程序运行时异常。