SpringCloud Stream+RabbitMQ简单整合

本篇记录Spring Cloud Stream和RabbitMQ的整合,简单实现了消息生产和消息消费。

本篇有两个项目节点互为消息的生产者和消息消费者。

1 父maven工程

1.1 工程结构如下:

在这里插入图片描述

1.2 pom.xml如下:

<?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.study</groupId>
  <artifactId>cloud-ma</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>pom</packaging>
  <name>SpringCloudStudy</name>
  <description>SpringCloudStudy</description>
  
  <!-- 私有仓库的配置 -->
  <repositories>          
	<repository>            
	    <id>nexus</id> <!-- 和setting.xml中配置的id保持一致 -->           
		<url>http://xxx.xx.xxx.xxx:8081/repository/maven-public/</url>            
	    <releases>
		    <enabled>true</enabled>
	    </releases>           
		<snapshots>
			<enabled>true</enabled>
		</snapshots>          
	  </repository>               
   </repositories>
  
  <parent>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-parent</artifactId>
     <version>2.0.3.RELEASE</version>
     <relativePath/>
  </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.RELEASE</spring-cloud.version>
  </properties>
  
  <dependencies>
  
    <!-- 上边引入 parent,因此 下边无需指定版本 -->
	    <!-- 包含 mvc,aop 等jar资源 -->
	    <dependency>
	        <groupId>org.springframework.boot</groupId>
	        <artifactId>spring-boot-starter-web</artifactId>
	        <exclusions>
	            <exclusion><!-- 去除默认log配置 -->
	                <groupId>org.springframework.boot</groupId>
	                <artifactId>spring-boot-starter-logging</artifactId>
	            </exclusion>
	        </exclusions>
	    </dependency>
	    
	    <!-- 配置log4j2 -->
	    <dependency>
	        <groupId>org.springframework.boot</groupId>
	        <artifactId>spring-boot-starter-log4j2</artifactId>
	    </dependency>
	    <!-- 配置log4j2 -->
	    
	    <!-- 支持识别yml配置 -->
	    <dependency>
	        <groupId>com.fasterxml.jackson.dataformat</groupId>
	        <artifactId>jackson-dataformat-yaml</artifactId>
	    </dependency>
	    <!-- 支持识别yml配置 -->
  
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    
    <!-- 热部署 -->
	<dependency>
	    <groupId>org.springframework.boot</groupId>
	    <artifactId>spring-boot-devtools</artifactId>
	    <optional>true</optional>
	    <scope>true</scope>
	</dependency>
	
	<!--开始  阿里的fastjson  -->
	<dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.51</version>
    </dependency>
    <!--结束  阿里的fastjson  -->
    
  </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>
             <configuration>
	                <!-- 没有该配置,devtools 不生效 -->
	                <fork>true</fork>
	         </configuration>
         </plugin>
     </plugins>
  </build>

  
  <modules>
  	<module>EurekaServer</module>
  	<module>EurekaClientHi</module>
    <module>EurekaClientRibbonCustomer</module>
    <module>EurekaClientHi2</module>
    <module>EurekaClientFeignCustomer</module>
    <module>EurekaClientZuul</module>
    <module>config_server</module>
    <module>config-client</module>
    <module>config-server-svn</module>
    <module>config-client-svn</module>
    <module>StreamProvider</module>
    <module>stream-output</module>
    <module>stream-input</module>
    <module>StreamRabbitMQSelf</module>
  </modules>
</project>

2 项目节点一

项目节点一的工程名称为stream-input-output

2.1 工程结构

在这里插入图片描述

2.2 该工程的pom.xml

<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>com.study</groupId>
    <artifactId>cloud-ma</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  
  <artifactId>stream-input</artifactId>
  <name>stream-input</name>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </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>
    </dependency>
  
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

2.3 application.yml

application.yml位于src/main/resources,其配置如下:

server:
  port: 8085
spring:
  cloud:
    stream:
      binders: 
        defaultRabbit: 
          type: rabbit
          environment: #配置rabbimq连接环境
            spring: 
              rabbitmq:
                host: xxx.xx.xxx.xxx
                username: xxx
                password: xxx
                virtual-host: / 
      bindings: 
        output:
          destination: MyOutput  #exchange名称,交换模式默认是topic
          content-type: application/json
        input: 
          destination: MyInput
          content-type: application/json

        application.yml配置了 spring.cloud.stream.bindings.input.destination=MyInput、spring.cloud.stream.bindings.output.destination=MyOutput 后会在RabbitMQ 中创建一个名为MyInput交换器(exchange)和一个名为MyOutput交换器(exchange)。如果没有在RabbitMQ中创建这两个交换器,那么程序运行后会自动在RabbbitMQ中创建。

        spring.cloud.stream.bindings.input.destination=MyInput是把springcloud stream的输入通道和RabbitMQ的MyInput交换器绑定,spring.cloud.stream.bindings.output.destination=MyOutput是把springcloud stream的消息输出通道和RabbitMQ的MyOutput交换器绑定。

2.4 Application主类

package com.stream.input;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * Hello world!
 *
 */
@SpringBootApplication
public class StreamInputApplication {
    public static void main( String[] args ) {
        SpringApplication.run(StreamInputApplication.class, args);
    }
}

2.5 消息生产类

2.5.1 消息生产类–接口

/**
 * 
 */
package com.stream.input.rabbitMQ.service;

import org.springframework.integration.core.MessageSource;


/**
 * @author mazhen
 *
 */
public interface SendMsg {
	
	public MessageSource<String>  sendTime();
	
}

2.5.2 消息生产类–实现类

/**
 * 
 */
package com.stream.input.rabbitMQ.service.impl;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.messaging.Source;
import org.springframework.context.annotation.Bean;
import org.springframework.integration.annotation.InboundChannelAdapter;
import org.springframework.integration.annotation.Poller;
import org.springframework.integration.core.MessageSource;
import org.springframework.messaging.support.GenericMessage;

import com.stream.input.rabbitMQ.service.SendMsg;

/**
 * @author mazhen
 *
 */

@EnableBinding(value= {Source.class})
public class SendMsgImpl implements SendMsg {
    
	/**
	 * 引入日志,注意都是"org.slf4j"包下
	 */
	private final static Logger logger = LoggerFactory.getLogger(SendMsgImpl.class);
	
	private String format="yyyy-mm-dd  HH:mm:ss";
	
    @Bean
    @InboundChannelAdapter(value = Source.OUTPUT, poller = @Poller(fixedDelay = "2000", maxMessagesPerPoll = "1"))
    @Override
 	public MessageSource<String> sendTime() {
    	logger.info(new SimpleDateFormat(format).format(new Date()));
    	return () -> new GenericMessage<>(new SimpleDateFormat(format).format(new Date()));
 	}

}

2.6 消息消费类

2.6.1 消息消费类–接口

/**
 * 
 */
package com.stream.input.rabbitMQ.service;

import org.springframework.messaging.Message;

/**
 * @author mazhen
 *
 */
public interface ReceiveMsg {
	public void receiveTime(Message<String> message);
}

2.6.2 消息消费类–实现类

/**
 * 
 */
package com.stream.input.rabbitMQ.service.impl;

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;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;

import com.stream.input.rabbitMQ.service.ReceiveMsg;


/**
 * @author mazhen
 *
 */
@Component
@EnableBinding(value= {Sink.class})
public class ReceiveMsgImpl implements ReceiveMsg {
   
	/**
	 * 引入日志,注意都是"org.slf4j"包下
	 */
	private final static Logger logger = LoggerFactory.getLogger(ReceiveMsgImpl.class);
	
	@Override
	@StreamListener(Sink.INPUT)
	public void receiveTime(Message<String> message) {
		logger.info("接收消息" + message.getPayload().toString());
	}

}

2.7 log4j2.yml

log4j2.yml位于src/main/resources,其配置如下:

Appenders:
    Console: #输出到控制台
      name: CONSOLE #Appender命名
      target: SYSTEM_OUT
      PatternLayout:
        pattern: "%d{yyyy-MM-dd HH:mm:ss,SSS}:%4p %t (%F:%L) - %m%n"
    RollingFile: # 输出到文件,超过256MB归档
      - name: ROLLING_FILE
        ignoreExceptions: false
#        fileName: /Users/zsq/Desktop/Project/tream-input-output/tream-input-output.log
#        filePattern: "/Users/zsq/Desktop/Project/tream-input-output/$${date:yyyy-MM} -%d{yyyy-MM-dd}-%i.log.gz"
        fileName: /stream-input-output/logs/stream-input-output.log
        filePattern: "/stream-input-output/logs/$${date:yyyy-MM}/stream-input-output-%d{yyyy-MM-dd}-%i.log.gz"
        PatternLayout:
          pattern: "%d{yyyy-MM-dd HH:mm:ss,SSS}:%4p %t (%F:%L) - %m%n"
        Policies:
          SizeBasedTriggeringPolicy:
            size: "256 MB"
        DefaultRolloverStrategy:
          max: 1000
          
Loggers:
    Root:
      level: info
      AppenderRef:
        - ref: CONSOLE
    Logger: #单独设置某些包的输出级别
      - name: com.stream.input #复数加上-
        additivity: false #去除重复的log
        level: trace
        AppenderRef: 
          - ref: CONSOLE #复数加上-
          - ref: ROLLING_FILE #复数加上-

3 项目节点二

项目节点二的工程名称为stream-output-input

3.1 工程结构

在这里插入图片描述

3.2 该工程的pom.xml

<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>com.study</groupId>
    <artifactId>cloud-ma</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>

  <artifactId>stream-output</artifactId>
  <name>stream-output</name>
  <url>http://maven.apache.org</url>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </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>
    </dependency>
  
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

3.3 application.yml

application.yml位于src/main/resources,其配置如下:

server:
  port: 8083
spring:
  cloud:
    stream:
      binders: 
        defaultRabbit: 
          type: rabbit
          environment: #配置rabbimq连接环境
            spring: 
              rabbitmq:
                host: xxx.xx.xxx.xxx
                username: xxx
                password: xxx
                virtual-host: / 
      bindings: 
        output:
          destination: MyInput  #exchange名称,交换模式默认是topic
          content-type: application/json
        input: 
          destination: MyOutput
          content-type: application/json

        application.yml配置了 spring.cloud.stream.bindings.input.destination=MyOutput、spring.cloud.stream.bindings.output.destination=MyInput 后会在RabbitMQ 中创建一个名为MyInput交换器(exchange)和一个名为MyOutput交换器(exchange)。如果项目节点一先启动运行,那么这两个交换器已经在RabbitMQ中创建。

        spring.cloud.stream.bindings.input.destination=MyInput是把springcloud stream的输入通道和RabbitMQ的MyInput交换器绑定,spring.cloud.stream.bindings.output.destination=MyOutput是把springcloud stream的消息输出通道和RabbitMQ的MyOutput交换器绑定。

        这样项目节点二的输入通道对应项目节点一的输出通道,项目节点二的输出通道对应项目节点一的输入通道,就可以互相作为对方的消费端和生成端。

3.4 Application主类

package com.stream.output;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * Hello world!
 *
 */
@SpringBootApplication
public class StreamOutputApplication {
    public static void main( String[] args ) {
        SpringApplication.run(StreamOutputApplication.class, args);
    }
}

3.5 消息生产类

3.5.1 消息生产类–接口

/**
 * 
 */
package com.stream.output.rabbitMQ.service;

import org.springframework.integration.core.MessageSource;

/**
 * @author mazhen
 *
 */
public interface SendMsg {
   public MessageSource<String> sendTime();
}

3.5.2 消息生产类–实现类

/**
 * 
 */
package com.stream.output.rabbitMQ.service.impl;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.messaging.Source;
import org.springframework.context.annotation.Bean;
import org.springframework.integration.annotation.InboundChannelAdapter;
import org.springframework.integration.annotation.Poller;
import org.springframework.integration.core.MessageSource;
import org.springframework.messaging.support.GenericMessage;

import com.stream.output.rabbitMQ.service.SendMsg;

/**
 * @author mazhen
 *
 */
@EnableBinding(Source.class)
public class SendMsgImpl implements SendMsg {
	

	/**
	 * 引入日志,注意都是"org.slf4j"包下
	 */
	private final static Logger logger = LoggerFactory.getLogger(SendMsgImpl.class);
	
	private String format="yyyy-mm-dd  HH:mm:ss";

	
    @Bean
    @InboundChannelAdapter(value = Source.OUTPUT, poller = @Poller(fixedDelay = "2000", maxMessagesPerPoll = "1"))
    @Override
	public MessageSource<String> sendTime() {
   	   logger.info(new SimpleDateFormat(format).format(new Date()));
   	   return () -> new GenericMessage<>(new SimpleDateFormat(format).format(new Date()));
	}

}

3.6 消息消费类

3.6.1 消息消费类–接口

/**
 * 
 */
package com.stream.output.rabbitMQ.service;

import org.springframework.messaging.Message;

/**
 * @author mazhen
 *
 */
public interface ReceiveMsg {
	public void receiveTime(Message<String> message);
}

3.6.2 消息消费类–实现类

/**
 * 
 */
package com.stream.output.rabbitMQ.service.impl;

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;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;

import com.stream.output.rabbitMQ.service.ReceiveMsg;

/**
 * @author mazhen
 *
 */
@Component
@EnableBinding(value={Sink.class})
public class ReceiveMsgImpl implements ReceiveMsg {

	/**
	 * 引入日志,注意都是"org.slf4j"包下
	 */
	private final static Logger logger = LoggerFactory.getLogger(ReceiveMsgImpl.class);
	
	@Override
	@StreamListener(Sink.INPUT)
	public void receiveTime(Message<String> message) {
		logger.info("接收消息" + message.getPayload());
	}

}

3.7 log4j2.yml

Appenders:
    Console: #输出到控制台
      name: CONSOLE #Appender命名
      target: SYSTEM_OUT
      PatternLayout:
        pattern: "%d{yyyy-MM-dd HH:mm:ss,SSS}:%4p %t (%F:%L) - %m%n"
    RollingFile: # 输出到文件,超过256MB归档
      - name: ROLLING_FILE
        ignoreExceptions: false
#        fileName: /Users/zsq/Desktop/Project/tream-output-input/tream-output-intput.log
#        filePattern: "/Users/zsq/Desktop/Project/tream-output-input/$${date:yyyy-MM} -%d{yyyy-MM-dd}-%i.log.gz"
        fileName: /stream-output-input/logs/stream-output-input.log
        filePattern: "/stream-output-input/logs/$${date:yyyy-MM}/stream-output-input-%d{yyyy-MM-dd}-%i.log.gz"
        PatternLayout:
          pattern: "%d{yyyy-MM-dd HH:mm:ss,SSS}:%4p %t (%F:%L) - %m%n"
        Policies:
          SizeBasedTriggeringPolicy:
            size: "256 MB"
        DefaultRolloverStrategy:
          max: 1000
          
Loggers:
    Root:
      level: info
      AppenderRef:
        - ref: CONSOLE
    Logger: #单独设置某些包的输出级别
      - name: com.stream.ouput #复数加上-
        additivity: false #去除重复的log
        level: trace
        AppenderRef: 
          - ref: CONSOLE #复数加上-
          - ref: ROLLING_FILE #复数加上-

4 测试

  • 启动 RabbitMQ
  • 启动项目节点一
  • 启动项目节点二

在 RabbitMQ 创建了 MyInput 和 MyOutput 交换器如下:
在这里插入图片描述
下面是对应的消息队列:
在这里插入图片描述
在项目节点一和项目节点二的控制台可以看到下面的消息输出:
在这里插入图片描述
在这里插入图片描述

欢迎关注我的微信公众号,不定期更新文章和大家一起学习共勉-在这里插入图片描述
Spring Cloud Stream 是基于 Spring BootSpring Integration 的框架,用于构建消息驱动的微服务应用程序。它提供了一种简单的方式来在应用程序中使用消息中间件,比如 RabbitMQ 和 Kafka。 下面分别介绍 Spring Cloud Stream 如何整合 RabbitMQ 和 Kafka。 ## 整合 RabbitMQ 1. 添加依赖 在 `pom.xml` 文件中添加以下依赖: ```xml <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-stream-binder-rabbit</artifactId> </dependency> <dependency> <groupId>org.springframework.amqp</groupId> <artifactId>spring-rabbit</artifactId> </dependency> ``` 2. 创建消息生产者 创建一个消息生产者,可以使用 `@EnableBinding` 注解将其与 RabbitMQ 绑定: ```java @EnableBinding(MessageSource.class) public class RabbitMQProducer { @Autowired private MessageSource<String> messageSource; public void sendMessage(String message) { messageSource.output().send(MessageBuilder.withPayload(message).build()); } } ``` 3. 创建消息消费者 创建一个消息消费者,同样使用 `@EnableBinding` 注解将其与 RabbitMQ 绑定: ```java @EnableBinding(MessageSink.class) public class RabbitMQConsumer { @StreamListener(MessageSink.INPUT) public void receiveMessage(String message) { System.out.println("Received: " + message); } } ``` 4. 配置 RabbitMQ 在 `application.yml` 文件中配置 RabbitMQ: ```yaml spring: rabbitmq: host: localhost port: 5672 username: guest password: guest ``` ## 整合 Kafka 1. 添加依赖 在 `pom.xml` 文件中添加以下依赖: ```xml <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-stream-binder-kafka</artifactId> </dependency> <dependency> <groupId>org.springframework.kafka</groupId> <artifactId>spring-kafka</artifactId> </dependency> ``` 2. 创建消息生产者 创建一个消息生产者,可以使用 `@EnableBinding` 注解将其与 Kafka 绑定: ```java @EnableBinding(MessageSource.class) public class KafkaProducer { @Autowired private MessageSource<String> messageSource; public void sendMessage(String message) { messageSource.output().send(MessageBuilder.withPayload(message).build()); } } ``` 3. 创建消息消费者 创建一个消息消费者,同样使用 `@EnableBinding` 注解将其与 Kafka 绑定: ```java @EnableBinding(MessageSink.class) public class KafkaConsumer { @StreamListener(MessageSink.INPUT) public void receiveMessage(String message) { System.out.println("Received: " + message); } } ``` 4. 配置 Kafka 在 `application.yml` 文件中配置 Kafka: ```yaml spring: kafka: bootstrap-servers: localhost:9092 consumer: group-id: myGroup auto-offset-reset: earliest producer: retries: 0 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值