spring cloud stream 通过定义绑定器作为中间层,完美地实现了应用程序与消息中间件细节之间的隔离。通过向应用程序暴露统一的channel通道,使得应用程序不需要再考虑各种不同的消息中间件的实现
spring cloud stream 中的消息通信方式遵循了发布-订阅模式,当一条消息被投递到消息中间件之后,它会通过共享的topic主题进行广播,消息消费者在订阅的主题中收到它并触发自身的业务逻辑处理
@interface EnableBinding 该注解用来指定一个或多个定义了@Input 或@Output注解的接口,以此实现对消息通道(channel)的绑定
接收器 类似于 consumer, subscriber
public interface Sink {
String INPUT = "input";
@Input(Sink.INPUT)
SubscribableChannel input();
}
@Input 绑定了一个名为input 的通道
来源,类似于 producer,publisher
public interface Source {
String OUTPUT = "output";
@Output(Source.OUTPUT)
MessageChannel output();
}
@Output 默认实现绑定output通道的source接口
public interface Processor extends Source, Sink {
}
结合了sink 和 source
@input @output注解都有一个value 属性,该属性可以用来设置消息通道的名称,如果我们直接使用这两个注解而没有具体的value值,将
默认使用方法名作为消息通道的名称
当我们定义输出通道的时候,需要返回MessageChannel接口对象,该接口定义了像消息通道发送消息的方法;而定义输入通道时,需要返回
SubscribableChannel接口对象,它定义了维护消息通道订阅者的方法
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@MessageMapping
@Documented
public @interface StreamListener {
@AliasFor("target")
String value() default ""; 信息通过值
@AliasFor("value")
String target() default "";
String condition() default "";
String copyHeaders() default "true";
}
它主要定义在方法上,作用是将被修饰的方法注册为消息中间件上数据流的事件监听器,当对 对应的queue发送消息时,被 StreamListener 注解的方法会做出对应的响应
基本使用
版本 spring boot 1.5.14
配置文件 |
spring.cloud.stream.bindings.shendu_input.destination=raw-sensor-data spring.rabbitmq.host=192.168.86.132 spring.rabbitmq.port=5672 spring.rabbitmq.username=springcloud spring.rabbitmq.password=springcloud |
消费者 |
package springcloud.spring_cloud_stream_pt; 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(value = {SinkSender.class}) public class SinkReceiver { private static Logger logger = LoggerFactory.getLogger(SinkReceiver.class); @StreamListener("shendu_input") public void receive(User payload){ logger.info("received: "+payload); } } |
生成者 接口 |
package springcloud.spring_cloud_stream_pt; import org.springframework.cloud.stream.annotation.Output; import org.springframework.cloud.stream.messaging.Sink; import org.springframework.messaging.MessageChannel; public interface SinkSender { @Output("shendu_input") MessageChannel output(); } |
变成调用类 |
package springcloud.spring_cloud_stream_pt; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.messaging.support.MessageBuilder; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class TestController { @Autowired private SinkSender sinkSender; @RequestMapping("/test") public void test(){ sinkSender.output().send(MessageBuilder.withPayload("{\"name\":\"shendu\",\"age\":30}").build()); } } |
实体类 |
package springcloud.spring_cloud_stream_pt; public class User { private String name; private Integer age; 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; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + '}'; } } |
pom 文件 依赖 |
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-stream</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-stream-binder-rabbit</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-stream-test-support</artifactId> <scope>test</scope> </dependency> </dependencies> |