• 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初体验的更多相关文章

  1. Kubernetes 笔记 02 demo 初体验

    本文首发于我的公众号 Linux云计算网络(id: cloud_dev),专注于干货分享,号内有 10T 书籍和视频资源,后台回复「1024」即可领取,欢迎大家关注,二维码文末可以扫. 从前面的文章我 ...

  2. [开发笔记]-Jqplot图表初体验

    文章内容为初次使用Jqplot图表插件的测试代码,仅供参考. <html xmlns="http://www.w3.org/1999/xhtml"> <head& ...

  3. JAVA 8 新特性Stream初体验

    什么是 Stream? Stream(流)是一个来自数据源的元素队列并支持聚合操作 <strong元素队列< strong="">元素是特定类型的对象,形成一个队 ...

  4. 云中沙箱学习笔记2-ECS之初体验

    1.1 背景知识 云服务器(Elastic Compute Service, 简称ECS),是一种简单高效,处理能力可以弹性伸缩的计算服务.ECS的相关术语说明如下: --实例(Instance):是 ...

  5. Java8初体验(二)Stream语法详解

    感谢同事[天锦]的投稿.投稿请联系 tengfei@ifeve.com 上篇文章Java8初体验(一)lambda表达式语法比 较详细的介绍了lambda表达式的方方面面,细心的读者会发现那篇文章的例 ...

  6. Java8初体验(2):Stream语法详解

    原文出处: 一冰_天锦 上篇文章Java8初体验(1):lambda表达式语法比较详细的介绍了lambda表达式的方方面面,细心的读者会发现那篇文章的例子中有很多Stream的例子.这些Stream的 ...

  7. Java8初体验(二)Stream语法详解(转)

    本文转自http://ifeve.com/stream/ Java8初体验(二)Stream语法详解 感谢同事[天锦]的投稿.投稿请联系 tengfei@ifeve.com上篇文章Java8初体验(一 ...

  8. Java8初体验(二)Stream语法详解---符合人的思维模式,数据源--》stream-->干什么事(具体怎么做,就交给Stream)--》聚合

    Function.identity()是什么? // 将Stream转换成容器或Map Stream<String> stream = Stream.of("I", & ...

  9. VSTO学习笔记(十五)Office 2013 初体验

    原文:VSTO学习笔记(十五)Office 2013 初体验 Office 2013 近期发布了首个面向消费者的预览版本,我也于第一时间进行了更新试用.从此开始VSTO系列全面转向Office 201 ...

  10. Spring Boot 学习笔记1——初体验之3分钟启动你的Web应用[z]

    前言 早在去年就简单的使用了一下Spring Boot,当时就被其便捷的功能所震惊.但是那是也没有深入的研究,随着其在业界被应用的越来越广泛,因此决定好好地深入学习一下,将自己的学习心得在此记录,本文 ...

随机推荐

  1. 【C# IO 操作 】详解去掉字符顺序标记(BOM)头的方法

    类似WINDOWS自带的记事本等软件,在保存一个以UTF-8编码的文件时,会在文件开始的地方插入三个不可见的字符(0xEF 0xBB 0xBF,即BOM).它是一串隐藏的字符,用于让记事本等编辑器识别 ...

  2. Oracle之关系型数据库

    什么是关系型数据库? (1)关系型数据库是依据关系模型来创建的数据库. (2)所谓关系模型就是"一对一.一对多.多对多"等关系模型,关系模型就是指二维表格模型,因而一个关系型数据库 ...

  3. Symfony Bundle开发视频教程分享

    之前分享了自己录制的<Symfony 5全面开发>视频教程,收到的反馈不错,说学到了东西,讲的很深入等等. 上一次分享的链接:自己录制的Symfony5视频教程,免费分享给大家学习. 小晒 ...

  4. Docker-镜像常用命令&安装Mysql\Nginx\ES\Kibana练习

    目录 前言: 一.常用命令 1.帮助命令 2.查看现在本地有哪些镜像 3.镜像搜索&下载&运行&停止&删除 镜像搜索 镜像下载 不指定版本下载 指定版本下载 运行镜像 ...

  5. 痞子衡嵌入式:恩智浦i.MX RTxxx系列MCU启动那些事(7)- 从SD/eMMC启动

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦i.MXRTxxx系列MCU的SD/eMMC卡启动. 关于 i.MXRT 启动设备,痞子衡之前写过很多篇文章,都是关于串并行 NO ...

  6. WebGL 与 WebGPU比对[6] - 纹理

    目录 1. WebGL 中的纹理 1.1. 创建二维纹理与设置采样参数 1.2. 纹理数据写入与拷贝 1.3. 着色器中的纹理 1.4. 纹理对象 vs 渲染缓冲对象 1.5. 立方体六面纹理 1.6 ...

  7. tensorflow源码解析之common_runtime-executor-下

    目录 核心概念 executor.h Executor NewLocalExecutor ExecutorBarrier executor.cc structs GraphView ExecutorI ...

  8. R-CNN小结

    1.背景 物体检测(object detection)是计算机视觉非常重要的一个领域.RCNN作为该领域的开山鼻祖,在深度学习出现之前,传统方法始终无法处理好物体检测问题(会通过非常庞大的计算,来算出 ...

  9. kali换源及安装docker

    kali换源及安装docker 以管理员身份运行. 换源,记得先备份, cp /etc/apt/sources.list /etc/apt/sources.list.bak 然后修改/etc/apt/ ...

  10. petite-vue源码剖析-逐行解读@vue/reactivity之reactive

    在petite-vue中我们通过reactive构建上下文对象,并将根据状态渲染UI的逻辑作为入参传递给effect,然后神奇的事情发生了,当状态发生变化时将自动触发UI重新渲染.那么到底这是怎么做到 ...