在传统的spring AMQP项目中,我们需要打开我们的kafa或者我们的rabbitMq进行相应的channels和queues的配置以后我们才可以在我们的代码中进行相应逻辑的编写,这对完全不熟悉rabbitMq或者kafa的人来说,他们需要去熟悉如何配置我们的消息中间件,这无形中增加了开发人员的成本,而spring cloud stream则可以完全抛开消息中间件,我们只需要关注与代码就可以快速的构建我们的消息中间价服务。
打开IDEA创建一个empty project 然后在该空的项目底下创建一个modules信息如下:
接着修改我们的pom.xml,引入我们的mq的stream,修改以后代码如下:
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.1.5.RELEASE
com.stream.send
send-mq-demo
0.0.1-SNAPSHOT
send-mq-demo
MQ发送的例子
1.8
org.springframework.boot
spring-boot-starter-web
org.springframework.cloud
spring-cloud-starter-stream-rabbit
org.springframework.boot
spring-boot-starter-test
test
org.springframework.cloud
spring-cloud-stream-dependencies
Fishtown.SR2
pom
import
org.springframework.boot
spring-boot-maven-plugin
打开我们生产者的application.yml配置文件进行如下的配置:
spring:
rabbitmq:
host: 10.10.10.129
port: 5672
username: linzf
password: 123456
cloud:
stream:
bindings:
# 这只是单纯的一个命名,只要不重复即可
sendOneReceiveAllChangel:
# 在MQ中创建一个名为sendOneReceiveAll的changel,发送一次会被所有的接收者消费
destination: sendOneReceiveAll
sayHelloWorldChanel:
# 在MQ中创建一个名为sayHelloWorld的changel,发送一次只会被消费一次
destination: sayHelloWorld
然后在我们的主入口类的同级目录创建一个config和controller目录,在config目录底下创建SendProcess.java的配置文件,配置内容如下:
package com.stream.send.demo.config;
import org.springframework.cloud.stream.annotation.Output;
import org.springframework.messaging.MessageChannel;
/**
* @author linzf
* @since 2019-05-27
* @类描述: 发送的MQ的配置文件
*/
public interface SendProcess {
/**
* 创建一个发送sendOneReceiveAll的通道
* @return 返回发送结果
*/
@Output("sendOneReceiveAll")
MessageChannel sendOneReceiveAll();
/**
* 创建一个发送sayHelloWorld的通道
* @return 返回发送结果
*/
@Output("sayHelloWorld")
MessageChannel sayHelloWorld();
}
接着打开我们的主入口类,注入我们的SendProcess的配置,修改以后代码如下:
package com.stream.send.demo;
import com.stream.send.demo.config.SendProcess;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.stream.annotation.EnableBinding;
/**
* @author linzf
* @since 2019-05-27
* 类描述:MQ的主入口类
*/
@SpringBootApplication
@EnableBinding(SendProcess.class)
public class SendMqDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SendMqDemoApplication.class, args);
}
}
最后在我们的controller包底下创建一个TestController.java,代码如下:
package com.stream.send.demo.controller;
import com.stream.send.demo.config.SendProcess;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author linzf
* @since 2019/5/27
* 类描述:测试发送消息的controller类
*/
@RestController
@RequestMapping("/test")
public class TestController {
@Autowired
private SendProcess sendProcess;
/**
* 功能描述:实现发送我们的测试信息
* @return
*/
@GetMapping("send")
public String send(){
sendProcess.sendOneReceiveAll().send(MessageBuilder.withPayload("测试发送一条数据被所有的接收者接收的例子").setHeader("type", "foo").build());
sendProcess.sayHelloWorld().send(MessageBuilder.withPayload("测试每次发送只会被一个接收者接收的例子").setHeader("type", "foo").build());
return "发送成功";
}
}
到此为止我们就完成了我们的生产者的全部工作了,我们可以启动我们的程序,然后我们在浏览器输入我们MQ的访问地址:
http://127.0.0.1:15672/#/exchanges 登陆成功以后我们会看到我们的exchanges底下多了我们配置文件里配置的sayHelloWorld和sendOneReceiveAll这两个通道,如下所示:
在之前的空的项目项目底下创建一个新的modules信息如下:
接着打开消费者项目的pom.xml文件修改maven依赖,修改完以后如下所示:
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.1.5.RELEASE
com.stream.receive
receive-mq-demo
0.0.1-SNAPSHOT
receive-mq-demo
这是一个接收者的demo
1.8
org.springframework.boot
spring-boot-starter
org.springframework.cloud
spring-cloud-starter-stream-rabbit
org.springframework.boot
spring-boot-starter-test
test
org.springframework.cloud
spring-cloud-stream-dependencies
Fishtown.SR2
pom
import
org.springframework.boot
spring-boot-maven-plugin
打开我们消费者的application.yml配置文件进行如下的配置:
spring:
cloud:
stream:
bindings:
# 没有配置group因此当启动多个消费者的时候,所有的消费者都会消费消息
sendOneReceiveAllChangel:
destination: sendOneReceiveAll
receiveHelloChanel:
# 这个属性是配置发送方是那个
destination: sayHelloWorld
# 创建queues的时候的名字,若不写则为随机数,若编写了则为此处则为【sendHelloWorld.receiveHelloWorld】,这样当我们启动多个消费者的时候消息就只会被消费一次
group: receiveHelloWorld
rabbitmq:
host: 10.10.10.129
port: 5672
username: linzf
password: 123456
接着在消费者的主入口类的同级目录底下创建一个config和receive的包,然后在config底下添加ReceiveProcess.java的配置文件,代码如下:
package com.stream.receive.demo.config;
import org.springframework.cloud.stream.annotation.Input;
import org.springframework.messaging.SubscribableChannel;
/**
* @author linzf
* @since 2019-05-27
* 类描述:接收者的配置
*/
public interface ReceiveProcess {
/**
* 接收sendOneReceiveAllChanel发送过来的消息
* @return
*/
@Input("sendOneReceiveAllChanel")
SubscribableChannel sendOneReceiveAllChanel();
/**
* 接收receiveHelloChanel发送过来的消息
* @return
*/
@Input("receiveHelloChanel")
SubscribableChannel receiveHelloChanel();
}
最后在receive包底下创建ReceiveMsg.java的接收类,代码如下:
package com.stream.receive.demo.receive;
import com.stream.receive.demo.config.ReceiveProcess;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.messaging.Message;
/**
* @author linzf
* @since 2019-05-27
* 类描述:接收者的接收类
*/
@EnableBinding(ReceiveProcess.class)
public class ReceiveMsg {
/**
* 接收所有的通道为sendOneReceiveAllChanel的消息
* @param content
*/
@StreamListener(target = "sendOneReceiveAllChanel" )
public void consumer(Message content){
System.out.println("【sendOneReceiveAllChanel】接收到了消息:"+content);
}
/**
* 接收所有的通道为receiveHelloChanel的消息
* @param content
*/
@StreamListener(target = "receiveHelloChanel" )
public void receiveHelloWorld(Message content){
System.out.println("【receiveHelloWorld】接收到了消息:"+content);
}
}
最后我们配置该消费者启动的时候指定配置文件【若是低版本的IDEA需要把single xxx的按钮去除】,此处我们点击
然后在点击红色标注的位置在里面设置好启动参数
接着我们再点击左上角的加号按钮
然后再次新增一个配置,里面的运行参数设置为8082,这样我们就完成了多个消费者启动的设置了,我们将我们的多个消费者启动起来,这时候大家去访问我们的http://127.0.0.1:15672/#/queues 大家会看到如下效果
这说明我们的配置已经完全生效了,接着我们再浏览器输入http://127.0.0.1:8080/test/send 响应我们的请求,我们会看到我们后端的日志会打印处如下日志:
我们的8081接收到了发送一次被所有接收者接收的例子。
而我们的8082则接收到了我们的两个发送的例子
到此我们完成了我们的MQ神器spring cloud stream的集成,具体的DEMO例子请查看以下的GitHub的地址:
https://github.com/lazyboyl/stream-demo