springcloudstream是一个构建消息驱动微服务框架,可以用来实现服务间的通信。
从图中可以看出,应用程序定义好inputs(服务接受消息)、outputs(服务发送消息)通过binder(与消息中间件通信的组件)与中间件(支持Kafka rabbitmq rocketmq)通过创建bindings(链接应用程序跟消息中间件的桥梁,用于消息的消费和生产)进行消息的发送与接受,springcloudstream支持发布与订阅、支持消费组、消息持久化、分区等等
下面看一下简单的运用:
@Input、@Output分别定义消息接受和消息发布的通道,而@EnableBinding则触发绑定,把接口里的通道绑定到消息中间件上
首先引入依赖:这里用的是rabbitmq
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
,然后配置好的rabbitmq
定义消息载体类
package com.gdut.clouddemo.order.VO;
import lombok.Data;
import java.util.Date;
/**
* @author lulu
* @Date 2019/7/2 16:18
*/
@Data
public class MessageVO {
private String id;
private String content;
private Date date;
}
定义通道集合类
package com.gdut.clouddemo.order.stream;
import org.springframework.cloud.stream.annotation.Input;
import org.springframework.cloud.stream.annotation.Output;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.SubscribableChannel;
/**
* @author lulu
* @Date 2019/7/2 11:01
*/
public interface ChannelList {
String INPUT = "input";
String OUTPUT = "output";
@Input(INPUT)
SubscribableChannel input();
@Output(OUTPUT)
MessageChannel output();
}
,然后定义消息发布或接受的类
package com.gdut.clouddemo.order.stream;
import com.gdut.clouddemo.order.VO.MessageVO;
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;
/**
* @author lulu
* @Date 2019/7/2 11:03
*/
@EnableBinding(ChannelList.class)
@Slf4j
public class StreamHandler {
//定义output发送到对应的input,这里的SentTo可以发送到多个消费者,这里相当于发送到output时消息的前置处理
@StreamListener(ChannelList.OUTPUT)
@SendTo(ChannelList.INPUT)
public MessageVO sendMessage(MessageVO messageVO) {
log.info("生产信息 ={}", messageVO);
return messageVO;
}
//当有消息过来时执行
@StreamListener(ChannelList.INPUT)
public void receiveMessage(MessageVO messageVO){
log.info("消费信息 ={}",messageVO);
}
}
然后是定义一个发送消息的方法
这里不是很规范,因为发送和接受都放到一个应用里面了,其实可以把channellist类放到公用程序里面,然后其他应用引包,分别引用里面的通道,根据应用角色编写相应的处理方法。
package com.gdut.clouddemo.order.controller;
import com.gdut.clouddemo.order.VO.MessageVO;
import com.gdut.clouddemo.order.stream.ChannelList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.*;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
/**
* @author lulu
* @Date 2019/7/2 11:05
*/
@RestController
public class SendMessageController {
@Autowired
private ChannelList streamClient;
@GetMapping("/sendMsg")
public String sendMsg() {
MessageVO messageVO = new MessageVO();
messageVO.setContent("haha");
messageVO.setDate(new Date());
messageVO.setId(System.nanoTime() + "");
Message message = MessageBuilder.withPayload(messageVO).build();
SubscribableChannel messageChannel = streamClient.input();
messageChannel.send(message);
return "发送成功";
}
}
结果: