SpringCloud个人笔记-04-Stream初体验
sb_cloud_stream
Spring Cloud Stream 是一个构建消息驱动微服务的框架
- 应用程序通过 inputs 或者 outputs 来与 Spring Cloud Stream 中binder 交互,通过我们配置来 binding ,而 Spring Cloud Stream 的 binder 负责与消息中间件交互。
- 通过使用Spring Integration来连接消息代理中间件以实现消息事件驱动。Spring Cloud Stream 为一些供应商的消息中间件产品提供了个性化的自动化配置实现,引用了发布-订阅、消费组、分区的三个核心概念。目前仅支持RabbitMQ、Kafka。
为什么需要SpringCloud Stream消息驱动呢?
比方说我们用到了RabbitMQ和Kafka,由于这两个消息中间件的架构上的不同,像RabbitMQ有exchange,kafka有Topic,partitions分区,这些中间件的差异性导致我们实际项目开发给我们造成了一定的困扰,我们如果用了两个消息队列的其中一种,
后面的业务需求,我想往另外一种消息队列进行迁移,这时候无疑就是一个灾难性的,一大堆东西都要重新推倒重新做,因为它跟我们的系统耦合了,这时候springcloud Stream给我们提供了一种解耦合的方式。

- Spring Cloud Stream由一个中间件中立的核组成。应用通过Spring Cloud Stream插入的input(相当于消费者consumer,它是从队列中接收消息的)和output(相当于生产者producer,它是从队列中发送消息的。)通道与外界交流。
通道通过指定中间件的Binder实现与外部代理连接。业务开发者不再关注具体消息中间件,只需关注Binder对应用程序提供的抽象概念来使用消息中间件实现业务即可
1.基础消息发送消费
- <?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.huarui</groupId>
- <artifactId>sb_cloud_stream</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- <name>sb_cloud_stream</name>
- <description>Demo project for Spring Boot</description>
- <parent>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-parent</artifactId>
- <version>1.5.13.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>Edgware.SR3</spring-cloud.version>
- </properties>
- <dependencies>
- <!-- rabbit -->
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-bus-amqp</artifactId>
- </dependency>
- <!-- stream -->
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
- </dependency>
- <!-- eureka client -->
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-eureka</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-test</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>
pom.xml
- 1 spring:
- 2 application:
- 3 name: sb_cloud_config_client
- 4 # #RebbitMq
- 5 rabbitmq:
- 6 host: 39.108.85.204
- 7 port: 5672
- 8 username: guest
- 9 password: guest
- 10
- 11
- 12 eureka:
- 13 client:
- 14 serviceUrl:
- 15 defaultZone: http://39.108.85.204:8761/eureka/
- 16 instance:
- 17 #注册时使用ip而不是主机名
- 18 prefer-ip-address: true
- 19 #指定此实例的ip
- 20 #ip-address: ip
- 21 server:
- 22 port: 9004
application.yml
- public class Girl implements Serializable {
- private String id;
- private String name;
- private Date date;
- public Girl(){
- }
- public Girl(String id, String name, Date date) {
- this.id = id;
- this.name = name;
- this.date = date;
- }
- public String getId() {
- return id;
- }
- public void setId(String id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public Date getDate() {
- return date;
- }
- public void setDate(Date date) {
- this.date = date;
- }
- @Override
- public String toString() {
- return "Girl{" +
- "id='" + id + '\'' +
- ", name='" + name + '\'' +
- ", date=" + date +
- '}';
- }
- }
Girl.java
- package com.huarui.util;
- import com.fasterxml.jackson.core.JsonFactory;
- import com.fasterxml.jackson.core.JsonParseException;
- import com.fasterxml.jackson.core.type.TypeReference;
- import com.fasterxml.jackson.databind.JsonMappingException;
- import com.fasterxml.jackson.databind.ObjectMapper;
- import com.fasterxml.jackson.databind.type.TypeFactory;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import java.io.IOException;
- import java.text.SimpleDateFormat;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- public class JsonUtils {
- private static Logger log = LoggerFactory.getLogger(JsonUtils.class);
- private static JsonFactory jsonfactory = new JsonFactory();
- private static ObjectMapper mapper = new ObjectMapper(jsonfactory);
- public static <T> T parseObject(String json,Class<T> clzz) {
- //设置JSON时间格式
- SimpleDateFormat myDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- mapper.setDateFormat(myDateFormat);
- try {
- return mapper.readValue(json, clzz);
- } catch (JsonParseException e) {
- e.printStackTrace();
- } catch (JsonMappingException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return null;
- }
- /**
- * json转map
- *
- * @param json
- * @return
- */
- public static Map<String,Object> parseMap(String json){
- TypeReference<HashMap<String,Object>> typeRef = new TypeReference<HashMap<String,Object>>() {};
- try {
- return mapper.readValue(json, typeRef);
- } catch (JsonParseException e) {
- log.error("字符串转json出错!"+json, e);
- } catch (JsonMappingException e) {
- log.error("json映射map出错!"+json, e);
- } catch (IOException e) {
- log.error("json转map流错误!"+json, e);
- }
- return null;
- }
- public static <T> List<T> parseList(String json,Class<?> clazz){
- TypeFactory t = TypeFactory.defaultInstance();
- try {
- List<T> list = mapper.readValue(json,t.constructCollectionType(ArrayList.class,clazz));
- return list;
- } catch (JsonParseException e) {
- e.printStackTrace();
- } catch (JsonMappingException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return null;
- }
- /**
- * 对像转json字符串
- *
- * @param obj
- * @return
- */
- public static String parseString(Object obj){
- String result = null;
- try {
- SimpleDateFormat myDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- mapper.setDateFormat(myDateFormat);
- result = mapper.writeValueAsString(obj);
- } catch (JsonParseException e) {
- log.error("字符串转json出错!", e);
- } catch (JsonMappingException e) {
- log.error("json映射map出错!", e);
- } catch (IOException e) {
- log.error("json转map流错误!", e);
- }
- return result;
- }
- }
JsonUtils.java
- package com.huarui.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;
- /**
- * 自定义input output
- */
- public interface StreamClient {
- public static final String INPUT = "myinput";
- public static final String OUTPUT = "myoutput";
- public static final String INPUTTO = "myinputto";
- public static final String OUTPUTTO = "myoutputto";
- /**
- * 相当于消费者consumer,它是从队列中接收消息的
- */
- @Input(INPUT)
- SubscribableChannel input();
- /**
- * 相当于生产者producer,它是从队列中发送消息的
- */
- @Output(OUTPUT)
- MessageChannel output();
- }
- @Component
- @EnableBinding(StreamClient.class)
- public class StreamReceiver {
- /**
- * 基本 INPUT
- * @param girlStr
- */
- @StreamListener(StreamClient.INPUT)
- public void process(String girlStr){
- Girl girl = JsonUtils.parseObject(girlStr, Girl.class);
- System.out.println("process 收到: "+girl);
- }
- }
- @RestController
- public class SendMessageController {
- @Autowired
- private StreamClient streamClient;
- @GetMapping("/sendGirl/{name}")
- public String sendGirl(@PathVariable String name){
- Girl girl = new Girl(UUID.randomUUID().toString(),name,new Date());
- streamClient.output().send(MessageBuilder.withPayload(girl).build());
- return name+" send ok";
- }
- }
避免启动项目时找不到该队列,手动创建 myinput队列
访问 http://localhost:9004/sendGirl/huahua 可见消息发送 并被消费,控制台打印的消息就可以证明
2.消息分组 一条消息只让组内一个实例消费
- spring:
- jackson:
- date-format: yyyy-MM-dd HH:mm:ss
- time-zon: GMT+8
- application:
- name: sb_cloud_config_client
- # #RebbitMq
- rabbitmq:
- host: 39.108.85.204
- port: 5672
- username: guest
- password: guest
- cloud:
- stream:
- bindings:
- myoutput: # 自定义output
- content-type: application/json #消息发送的格式 发送端指定即可
- destination: sb-cloud-stream
- myinput: # 自定义input
- destination: sb-cloud-stream
- group: girlfriend #分组 同一组的消息只有一个实例接收
yml配置文件中添加group 即可实现。
3.接收消息后 并回馈消息
- spring:
- jackson:
- date-format: yyyy-MM-dd HH:mm:ss
- time-zon: GMT+8
- application:
- name: sb_cloud_config_client
- # #RebbitMq
- rabbitmq:
- host: 39.108.85.204
- port: 5672
- username: guest
- password: guest
- cloud:
- stream:
- bindings:
- myoutput: # 自定义output
- content-type: application/json #消息发送的格式 发送端指定即可
- destination: sb-cloud-stream
- myinput: # 自定义input
- destination: sb-cloud-stream
- group: girlfriend #分组 同一组的消息只有一个实例接收
- myoutputto: # 自定义output (回馈使用)
- content-type: application/json #消息发送的格式 发送端指定即可
- destination: sb-cloud-stream-to
- myinputto: # 自定义input(回馈使用)
- destination: sb-cloud-stream-to
- public interface StreamClient {
- public static final String INPUT = "myinput";
- public static final String OUTPUT = "myoutput";
- public static final String INPUTTO = "myinputto";
- public static final String OUTPUTTO = "myoutputto";
- /**
- * 相当于消费者consumer,它是从队列中接收消息的
- */
- @Input(INPUT)
- SubscribableChannel input();
- /**
- * 相当于生产者producer,它是从队列中发送消息的
- */
- @Output(OUTPUT)
- MessageChannel output();
- /**
- * 相当于消费者consumer,它是从队列中接收消息的 (反馈使用)
- */
- @Input(INPUTTO)
- SubscribableChannel inputto();
- /**
- * 相当于生产者producer,它是从队列中发送消息的 (反馈使用)
- */
- @Output(OUTPUTTO)
- MessageChannel outputto();
- }
- package com.huarui.message;
- import com.huarui.entity.Girl;
- import com.huarui.util.JsonUtils;
- 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 by lihui on 2019/2/28.
- */
- @Component
- @EnableBinding(StreamClient.class)
- public class StreamReceiver {
- /**
- * 基本 INPUT
- * @param girlStr
- */
- @StreamListener(StreamClient.INPUT)
- public void process(String girlStr){
- Girl girl = JsonUtils.parseObject(girlStr, Girl.class);
- System.out.println("process 收到: "+girl);
- }
- /**
- * 我们接收到消息后,给别人一个反馈
- * SpringCloud stream 给我们提供了一个SendTo注解可以帮我们干这些事情
- * @param girlStr
- * @return
- */
- @StreamListener(StreamClient.INPUTTO)
- @SendTo(StreamClient.OUTPUTTO)
- public String processTo(String girlStr){
- Girl girl = JsonUtils.parseObject(girlStr, Girl.class);
- System.out.println("收到: "+girl);
- return JsonUtils.parseString(girl);
- }
- @StreamListener(StreamClient.OUTPUTTO)
- public void process2(String girlStr){
- Girl girl = JsonUtils.parseObject(girlStr, Girl.class);
- System.out.println("ta 已收到: "+girl);
- }
- }
@SendTo 注解就能实现消息接收后回馈消息, return 返回值就是回馈的消息
访问 http://localhost:9004/sendGirlTo/huahua 可见消息被消费后 并回馈了一条消息,控制台打印的消息就可以证明
本项目地址: https://github.com/youxiu326/sb_cloud_stream.git
参考博客: https://i.cnblogs.com/EditPosts.aspx?postid=10464571&update=1
SpringCloud个人笔记-04-Stream初体验的更多相关文章
- Kubernetes 笔记 02 demo 初体验
本文首发于我的公众号 Linux云计算网络(id: cloud_dev),专注于干货分享,号内有 10T 书籍和视频资源,后台回复「1024」即可领取,欢迎大家关注,二维码文末可以扫. 从前面的文章我 ...
- [开发笔记]-Jqplot图表初体验
文章内容为初次使用Jqplot图表插件的测试代码,仅供参考. <html xmlns="http://www.w3.org/1999/xhtml"> <head& ...
- JAVA 8 新特性Stream初体验
什么是 Stream? Stream(流)是一个来自数据源的元素队列并支持聚合操作 <strong元素队列< strong="">元素是特定类型的对象,形成一个队 ...
- 云中沙箱学习笔记2-ECS之初体验
1.1 背景知识 云服务器(Elastic Compute Service, 简称ECS),是一种简单高效,处理能力可以弹性伸缩的计算服务.ECS的相关术语说明如下: --实例(Instance):是 ...
- Java8初体验(二)Stream语法详解
感谢同事[天锦]的投稿.投稿请联系 tengfei@ifeve.com 上篇文章Java8初体验(一)lambda表达式语法比 较详细的介绍了lambda表达式的方方面面,细心的读者会发现那篇文章的例 ...
- Java8初体验(2):Stream语法详解
原文出处: 一冰_天锦 上篇文章Java8初体验(1):lambda表达式语法比较详细的介绍了lambda表达式的方方面面,细心的读者会发现那篇文章的例子中有很多Stream的例子.这些Stream的 ...
- Java8初体验(二)Stream语法详解(转)
本文转自http://ifeve.com/stream/ Java8初体验(二)Stream语法详解 感谢同事[天锦]的投稿.投稿请联系 tengfei@ifeve.com上篇文章Java8初体验(一 ...
- Java8初体验(二)Stream语法详解---符合人的思维模式,数据源--》stream-->干什么事(具体怎么做,就交给Stream)--》聚合
Function.identity()是什么? // 将Stream转换成容器或Map Stream<String> stream = Stream.of("I", & ...
- VSTO学习笔记(十五)Office 2013 初体验
原文:VSTO学习笔记(十五)Office 2013 初体验 Office 2013 近期发布了首个面向消费者的预览版本,我也于第一时间进行了更新试用.从此开始VSTO系列全面转向Office 201 ...
- Spring Boot 学习笔记1——初体验之3分钟启动你的Web应用[z]
前言 早在去年就简单的使用了一下Spring Boot,当时就被其便捷的功能所震惊.但是那是也没有深入的研究,随着其在业界被应用的越来越广泛,因此决定好好地深入学习一下,将自己的学习心得在此记录,本文 ...
随机推荐
- 哈工大 计算机网络 实验三 IPv4 分组收发实验&IPv4 分组转发实验
计算机网络实验代码与文件可见github:计算机网络实验整理 实验名称 IPv4 分组收发实验&IPv4 分组转发实验 实验目的: (注:实验报告模板中的各项内容仅供参考,可依照实际实验情况进 ...
- 转 Linux下安装Tomcat服务器和部署Web应用
转载声明: http://www.cnblogs.com/xdp-gacl/p/4097608.html 一.上传Tomcat服务器
- c# winform中TabControl中给每个选项卡添加不同的图标(图片)
在一个TabControl控件中,有几个选项卡,现在在每个选项卡上显示不同的图标. 1:你要现在form窗体中通过工具箱加入一个imagelist,名字为imagelist1,如下图: 2:然后在里面 ...
- python3中zip()的用法
zip函数接受任意多个可迭代对象作为参数,将对象中对应的元素打包成一个tuple,然后返回一个可迭代的zip对象. 这个可迭代对象可以使用循环的方式列出其元素 若多个可迭代对象的长度不一致,则所返回的 ...
- .NetCore Web Api 利用ActionFilterAttribute统一接口返回值格式
.Net Core 同 Asp.Net MVC一样有几种过滤器,这里不再赘述每个过滤器的执行顺序与作用. 在实际项目开发过程中,统一API返回值格式对前端或第三方调用将是非常必要的,在.NetCore ...
- 【Java分享客栈】一个包装过简历的新同事写完微信支付引起事故后果断离职了
前言 挺长时间没发文了,因为公司有一个紧急项目要赶进度,加班如吃饭喝水,久违的进入到码农的状态. 之所以抽空来发个文,是这个项目才刚上线,时间不长却因为一位新同事的代码引起了生产环境的事故,造成了一批 ...
- SoftwareTeacher直播自我感想
今天老师发布了一个链接直播是关于:同学们聊聊学习软件工程,CS 课程的问题下面是我的个人感悟和笔记 一.编程技术的提升 编程并不是一件很难的事情,就如开车一样,只有多加练习,自己的技术才能提升上去.拿 ...
- JavaWeb之Servlet、拦截器、监听器及编程思想
本文包含的内容有: Servlet的理解 自定义Servlet.监听器和过滤器 三者的一点点编程设计思想 后续的学习 JavaWeb是Web开发的重要基础,对Servlet.监听器和过滤器等知识的掌握 ...
- OpenCv基础_三
轮廓检测 图像金字塔 上采样,图像变大一倍,矩阵用0填充 img = cv2.imread('1,jpg') cv_show('img',img) up = cv2.pyrUp(img) cv_sho ...
- centos7升级openssh8.7&openssl1.1.1l脚本
脚本下载地址或首页联系本人获取 https://files.cnblogs.com/files/blogs/705493/update_ssh.sh 需搭配openssh8.7和openssl1.1. ...