消息驱动的微服务SpringCloud Stream
快速入门
创建项目 stream-hello 9014
依赖文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zk.springcloud</groupId>
<artifactId>springcloud-stream</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springcloud-stream</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Finchley.SR1</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
<version>2.0.1.RELEASE</version>
</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>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
创建用于接收来自 RabbitMQ 消息的消费者 SinkReceiver
@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);
}
}
启动类
@SpringBootApplication
public class SpringcloudStreamApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudStreamApplication.class, args);
}
}
配置文件
spring.application.name=stream-hello
server.port=9014
启动 stream-hello 9014 ,可以获得以下信息,受用 guest 用户创建一个指向 127.0.0.1:5672 位置的 RabbitMQ 连接
o.s.a.r.c.CachingConnectionFactory : Attempting to connect to: [localhost:5672]
o.s.a.r.c.CachingConnectionFactory : Created new connection: rabbitConnectionFactory#64bfd6fd:0/SimpleConnection@6ba7383d [delegate=amqp://guest@127.0.0.1:5672/, localPort= 43668]
o.s.c.stream.binder.BinderErrorChannel : Channel 'stream-hello.input.anonymous.GcXoim1vRbuMnvWsJOkaUg.errors' has 1 subscriber(s).
o.s.c.stream.binder.BinderErrorChannel : Channel 'stream-hello.input.anonymous.GcXoim1vRbuMnvWsJOkaUg.errors' has 2 subscriber(s).
o.s.i.a.i.AmqpInboundChannelAdapter : started inbound.input.anonymous.GcXoim1vRbuMnvWsJOkaUg
在 RabbitMQ 控制台可以看到 127.0.0.1:43668 rabbitConnectionFactory#64bfd6fd:0 guest 的 connection 和 input.anonymous.GcXoim1vRbuMnvWsJOkaUg 名称的队列,并通过 RabbitMEssageChannelBinder 将自己绑定为它的消费者
在 input.anonymous.GcXoim1vRbuMnvWsJOkaUg 队列中,通过 Publish message 输入一条消息到该队列中,在控制台将接受到
c.z.s.springcloudstream.SinkReceiver : Received: [B@79af2131
消费组
spring.cloud.stream.bindings.inout.group=
注入绑定接口
消息生成者,向 input 消息通道发送数据
创建一个将 Input 消息通道作为输出通道的接口
package com.zk.springcloud.springcloudstream;
import org.springframework.cloud.stream.annotation.Output;
import org.springframework.cloud.stream.messaging.Sink;
import org.springframework.messaging.MessageChannel;
public interface SinkSender {
@Output(Sink.INPUT)
MessageChannel output();
}
在 @EnableBinding 注解中增加对 SinkSender 接口的指定
package com.zk.springcloud.springcloudstream;
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(Sink.INPUT)
public void receive(Object payload){
logger.info("Received: " + payload);
}
}
单元测试类
package com.zk.springcloud.springcloudstream;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringcloudStreamApplicationTests {
@Autowired
private SinkSender sinkSender;
@Test
public void contextLoads() {
sinkSender.output().send(MessageBuilder.withPayload("From, SinkSender").build());
}
}
运行单元测试,可以在控制台输出如下内容,消息被正确地发送到了 input 通道中,并被相对应的消息消费者输出
2018-10-25 13:56:39.026 INFO 13024 --- [ main] c.z.s.springcloudstream.SinkReceiver : Received: From, SinkSender
注入消息通道
通过以下代码,注入上面例子中 SinkSender 接口中定义的名为 input 的消息输入通道
package com.zk.springcloud.springcloudstream;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringcloudStreamApplicationTests {
@Autowired
private MessageChannel input;
@Test
public void contextLoads() {
input.send(MessageBuilder.withPayload("From, SinkSender").build());
}
}
完成了与之前通过注入绑定接口 SinkSender 方式实现的测试用例相同的操作