Spring Boot web开发(十) RabbitMQ消息与队列的使用

目录

1. 消息与队列的简单介绍

2. RabbitMQ简介和安装使用

2.1 核心概念

2.2 Exchange类型

2.3 RabbitMQ安装使用

3. SpringBoot整合使用RabbitMQ

3.1 新建项目引入spring-boot-starter-amqp

3.2 添加application.properties配置

3.3 RabbitTemplate操作RabbitMQ

3.4 监听消息@RabbitListener

3.5 AmqpAdmin系统管理组件


1. 消息与队列的简单介绍

消息队列(Message Queue),是分布式系统中重要的组件,可通过消息服务中间件来提升系统异步通信、扩展解耦能力。

消息服务中两个重要概念:消息代理(message broker)和目的地(destination)当消息发送者发送消息以后,将由消息代理接管,消息代理保证消息传递到指定目的地。

消息队列主要有两种形式的目的地。

  •      队列(queue):点对点消息通信,发送者发送消息,消息代理收入消息,接收者从队列中获取消息,然后移出队列。
  •      主题(topic):发布/订阅消息通信,发送者发送消息到主题,多个接收者监听这个主题,当消息到达时同时收到消息。

2. RabbitMQ简介和安装使用

RabbitMQ是一个由erlang开发的AMQP(Advanved Message Queue Protocol)的开源实现。

2.1 核心概念

  • Message:消息,消息是不具名的,它由消息头和消息体组成。消息体是不透明的,而消息头则由一系列的可选属性组成,这些属性包括routing-key(路由键)、delivery-mode(指出该消息可能需要持久性存储)等。
  • Publisher:消息的生产者,也是一个向交换器发布消息的客户端应用程序。
  • Exchange:交换器,用来接收生产者发送的消息并将这些消息路由给服务器中的队列。Exchange有4种类型:direct(默认),fanout, topic, 和headers,不同类型的Exchange转发消息的策略有所区别。
  • Queue:消息队列,用来保存消息直到发送给消费者。它是消息的容器,也是消息的终点。一个消息可投入一个或多个队列。消息一直在队列里面,等待消费者连接到这个队列将其取走。
  • Binding:绑定,用于消息队列和交换器之间的关联。一个绑定就是基于路由键将交换器和消息队列连接起来的路由规则,所以可以将交换器理解成一个由绑定构成的路由表。Exchange 和Queue的绑定可以是多对多的关系。
  • Channel:信道,多路复用连接中的一条独立的双向数据流通道。信道是建立在真实的TCP连接内的虚拟连接,AMQP 命令都是通过信道发出去的,不管是发布消息、订阅队列还是接收消息,这些动作都是通过信道完成。因为对于操作系统来说建立和销毁 TCP 都是非常昂贵的开销,所以引入了信道的概念,以复用一条 TCP 连接。
  • Consumer:消息的消费者,表示一个从消息队列中取得消息的客户端应用程序。
  • Virtual Host:虚拟主机,表示一批交换器、消息队列和相关对象。虚拟主机是共享相同的身份认证和加密环境的独立服务器域。每个 vhost 本质上就是一个 mini 版的 RabbitMQ 服务器,拥有自己的队列、交换器、绑定和权限机制。vhost 是 AMQP 概念的基础,必须在连接时指定,RabbitMQ 默认的 vhost 是 / 。

2.2 Exchange类型

Exchange有4种类型:direct(默认),fanout, topic, 和headers,不同类型的Exchange转发消息的策略有所区别。下面具体说一下前三种的区别。

  1. direct:消息中的路由键(routing key)如果和 Binding 中的 binding key 一致, 交换器就将消息发到对应的队列中。路由键与队列名完全匹配。
  2. fanout:不处理路由键,将队列绑定与该交换器绑定的所有队列上。
  3. topic: 交换器通过模式匹配分配消息的路由键属性,将路由键和某个模式进行匹配,此时队列需要绑定到一个模式上。它将路由键和绑定键的字符串切分成单词,这些单词之间用点隔开。它同样也会识别两个通配符:符号“#”和符号“*”。#匹配0个或多个单词,*匹配一个单词。

2.3 RabbitMQ安装使用

RabbitMQ依然采用docker安装,比较方便快速操作,安装过程如下。

docker pull rabbitmq:3.8-management


root@ubuntu:~# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
rabbitmq            3.8-management      94fe3fd9c75f        13 hours ago        180.3 MB
rabbitmq            latest              f6438d62c67c        13 hours ago        150.2 MB
web                 latest              1807c52016d2        2 weeks ago         680.1 MB
redis               latest              ee077f82946a        2 weeks ago         98.22 MB
mysql               latest              2ec553978d80        2 weeks ago         456.2 MB
tomcat              latest              9edcbdad4d26        3 weeks ago         511.2 MB
java                latest              c435c0fb17b9        2 years ago         643.2 MB


docker -d -p 15672:15672 -p 5672:5672 --name myrabbitmq 94fe3fd9c75f

然后访问虚拟主机ip和端口,出现以下界面说明安装成功。

接下来先介绍一些基本操作(使用用户:guest,密码:guest进行登录):

3. SpringBoot整合使用RabbitMQ

3.1 新建项目引入spring-boot-starter-amqp

<!-- 引入的starter -->
<dependency>
	<groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
	<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>

3.2 添加application.properties配置

spring.rabbitmq.addresses=192.168.146.139
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
#不写默认也是5672
spring.rabbitmq.port=5672
#不写默认是/
spring.rabbitmq.virtual-host=/

3.3 RabbitTemplate操作RabbitMQ

和JDBC,Redis相似,RabbitTemplate也可以对RabbitMQ进行操作,能够发送和接受消息。

在测试类中添加方法:

package com.chtw.rabbitmp;

import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class SpringBootRabbitmpApplicationTests {

	@Autowired
	RabbitTemplate rabbitTemplate;

	//发送
	@Test
	public void send(){
		//exchange:指定交换机,routingKey:指定路由键,object:发送数据的内容,会被jdk自动序列化
		List<String> str = new ArrayList<>();
		str.add("hello");
		str.add("world");
		str.add("哈哈哈哈");
		rabbitTemplate.convertAndSend("user.direct","info",str);
	}

	@Test
	void contextLoads() {
	}

}

然后运行,登录到web管理平台去看,消息是发上去了,但是格式不是我们想要的json格式,他是被java序列化后的结果:

在RebbitTemplate中有一个MessageConverter,他默认的是SimpleMessageConverter(),就是默认使用的jdk的序列化机制。

我们添加自己的序列化器,然结果以json的数据格式保存:添加一个配置类来指定我们自己额序列化规则

package com.chtw.rabbitmp.config;

import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author CHTW
 * @date 2019-11-07-20:50
 */

@Configuration
public class MyAMQPConfig {

    @Bean
    public MessageConverter messageConverter(){
        return new Jackson2JsonMessageConverter();
    }
}

然后在运行发送send()方法。

有发送消息,同样也有获取消息的方法:

	@Test
	void receive() {
		Object object = rabbitTemplate.receive("info");
		System.out.println(object);
	}

3.4 监听消息@RabbitListener

首先我们要开启基于注解的RabbitMQ,在主类上添加一个注解来开启基于注解的RabbitMQ

为了方便测试监听功能,我们先添加一个JavaBean

package com.chtw.rabbitmp.bean;

import java.io.Serializable;

/**
 * @author CHTW
 * @date 2019-11-07-21:09
 */
public class User{
    private int id;
    private String username;
    private String passwprd;
    public User(){}
    public User(int id,String username,String passwprd){
        this.id = id;
        this.username = username;
        this.passwprd = passwprd;
    }
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPasswprd() {
        return passwprd;
    }

    public void setPasswprd(String passwprd) {
        this.passwprd = passwprd;
    }

    @Override
    public String toString() {
        return "User:" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", passwprd='" + passwprd + '\'' ;
    }
}

在写一个service,在service里面监听消息。

package com.chtw.rabbitmp.service;

import com.chtw.rabbitmp.bean.User;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;

/**
 * @author CHTW
 * @date 2019-11-07-21:12
 */
@Service
public class UserService {

    @RabbitListener(queues = "info")
    public void RabbitListenerTest(User user){
        System.out.println("用户信息:"+user);
    }
}

然后再测试类里面再写一个发送用户信息的方法,

	@Test
	public void sendUser(){
		//exchange:指定交换机,routingKey:指定路由键,object:发送数据的内容,会被jdk自动序列化
		User user = new User(1,"Alice","123456789");
		rabbitTemplate.convertAndSend("user.direct","info",user);
	}

运行项目再运行这个发送用户的方法:

重新发送一个user对象,传一个user对象为id=1,username=Bob,password=11111;

再看控制台:

3.5 AmqpAdmin系统管理组件

AmqpAdmin提供了一些方法给我们来创建交换机、队列异界进行绑定等操作。运行以下方法,

	@Test
	public void amqpAdmin(){
		/**
		 * 以declare开头的都是创建函数
		 * 以delete开头的都是删除函数
		 * removeBinding();解除绑定
		 */
		//创建交换机
		amqpAdmin.declareExchange(new DirectExchange("user.info"));
		//创建队列
		amqpAdmin.declareQueue(new Queue("info.user",true));
		//将队列和交换机绑定
		amqpAdmin.declareBinding(new Binding("info.user", Binding.DestinationType.QUEUE,
				"user.info","user.info",null));
	}

本节类容到此结束

本人联系方式2329095893,欢迎各位进行学习讨论

欢迎关注熊熊出没ING公众号,不定时跟新Java、python、信息安全等相关知识哦。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值