1. 在大多应用中,我们系统之间需要进行异步通信,即异步消息。

2. 异步消息中两个重要概念: 消息代理(message broker)和目的地(destination) 当消息发送者发送消息以后,将由消息代理接管,消息代理保证消息传递到指定目 的地。 3. 异步消息主要有两种形式的目的地 1. 队列(queue):点对点消息通信(point-to-point) 2. 主题(topic):发布(publish)/订阅(subscribe)消息通信

4. 点对点式: – 消息发送者发送消息,消息代理将其放入一个队列中,消息接收者从队列中获取消息内容, 消息读取后被移出队列 – 消息只有唯一的发送者和接受者,但并不是说只能有一个接收者

5. 发布订阅式: – 发送者(发布者)发送消息到主题,多个接收者(订阅者)监听(订阅)这个主题,那么 就会在消息到达时同时收到消息

6. JMS(Java Message Service)java消息服务: – 基于JVM消息代理的规范。ActiveMQ、HornetMQ是JMS实现

7. AMQP(Advanced Message Queuing Protocol) – 高级消息队列协议,也是一个消息代理的规范,兼容JMS – RabbitMQ是AMQP的实现

8. Spring支持 – spring-jms提供了对JMS的支持 – spring-rabbit提供了对AMQP的支持 – 需要ConnectionFactory的实现来连接消息代理 – 提供JmsTemplate、RabbitTemplate来发送消息 – @JmsListener(JMS)、@RabbitListener(AMQP)注解在方法上监听消息代理发 布的消息 – @EnableJms、@EnableRabbit开启支持

9. Spring Boot自动配置 – JmsAutoConfiguration – RabbitAutoConfiguration

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

核心概念:

Producer&Consumer 

producer指的是消息生产者,

consumer消息的消费者。

Broker – 它提供一种传输服务,它的角色就是维护一条从生产者到消费者的路线,保 证数据能按照指定的方式进行传输,

Queue – 消息队列,提供了FIFO的处理机制,具有缓存消息的能力。rabbitmq中, 队列消息可以设置为持久化,临时或者自动删除。 – 设置为持久化的队列,queue中的消息会在server本地硬盘存储一份,防止 系统crash,数据丢失 – 设置为临时队列,queue中的数据在系统重启之后就会丢失 – 设置为自动删除的队列,当不存在用户连接到server,队列中的数据会被自 动删除

Exchange – 消息交换机,它指定消息按什么规则,路由到哪个队列。 – Exchange有4种类型:direct(默认),fanout, topic, 和headers,不同类型 的Exchange转发消息的策略有所区别:

Binding – 将一个特定的 Exchange 和一个特定的 Queue 绑定起来。 – Exchange 和Queue的绑定可以是多对多的关系。

virtual host( vhosts ) – 在rabbitmq server上可以创建多个虚拟的message broker,又叫做 virtual hosts (vhosts) – 每一个vhost本质上是一个mini-rabbitmq server,分别管理各自的 exchange,和bindings – vhost相当于物理的server,可以为不同app提供边界隔离 – producer和consumer连接rabbit server需要指定一个vhost

三、RabbitMQ运行机制:

Pub发消息,消息进入服务器(代理)通过exchang额(路由)由消息的路由键同binding找到对应的消息队列写入,consumer通过connection(里的信道可节省开销实质为多路由复用)。获取消息。

四、RabbitMQ整合:

1. 引入spring-boot-starter-amqp 2. application配置 3. 测试RabbitMQ

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

2.配置application:

spring.rabbitmq.host=192.168.1.106 
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest

在测试之前我们先看下springboot自动配置rabbiMq原理:

第一步、搜索RabbitAutoConfiguration看里边的内容,主要有:

/**
 *探索。rabbitmq的自动配置原理
 * 1.RabbitAutoConfiguration
 * 2.里面有自动的连接工厂,@ConfigurationProperties(prefix = "spring.rabbitmq")。
 * RabbitProperties里面封装了配置的属性
 * 3.RabbitTemplate发送接收消息
 * 4.AmqpAdmin系统管理组件,声明队列。交换器等
 *
 */

3,。测试:

package com.rabbitmq.springbootrabbitmqs;

import com.rabbitmq.springbootrabbitmqs.bean.Book;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.omg.CORBA.PUBLIC_MEMBER;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import javax.xml.bind.SchemaOutputResolver;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootRabbitmqsApplicationTests {
   @Autowired
   RabbitTemplate rabbitTemplate;
   @Test
   public void contextLoads() {
      //Message 需要自己构造;定义消息体内容和消息头
      Map<String,Object>map=new HashMap<>();
      map.put("msg","这是第一个消息");
      map.put("data", Arrays.asList("hellow",123,true));
      //路由名+路邮键+要发送的消息
      rabbitTemplate.convertAndSend("exchange.dircett","demo",new Book("西游记","吴承恩"));
   }

   /**
    * 接收数据
    * 收到消息之后消息队列里就没有这个消息了
    */
   @Test
   public void recive(){
      //demos是消息队列的名字
      Object o=rabbitTemplate.receiveAndConvert("demo");
      //打印得到的类型
      System.out.println(o.getClass());
      System.out.println(o);
      ;
   }

}

测试之前如果要获得json数据需要自定义config:

通过查看RabbitTemplate发现MessageConverter(消息转化器)点击去发现是个接口,ctrl+h发现其现,在其抽象实现中发现有转json的实现,接下来我们编写config

package com.rabbitmq.springbootrabbitmqs.config;

import org.springframework.amqp.core.AmqpAdmin;
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;
/**
 * 数据转化json发送出去
 * 1.进入RabbitTemplate看MessageConverter(消息转化器)
 *
 */
@Configuration
public class MyAMQPConfig {
    @Bean
    public MessageConverter messageConverter(){
        return new Jackson2JsonMessageConverter();
    }
}

new Jackson2JsonMessageConverter();并且rerturn。

基本上就可以了。如果要使用监听功能则需要在启动类上加上注解:

package com.rabbitmq.springbootrabbitmqs;

import org.springframework.amqp.rabbit.annotation.EnableRabbit;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 *探索。rabbitmq的自动配置原理
 * 1.RabbitAutoConfiguration
 * 2.里面有自动的连接工厂,@ConfigurationProperties(prefix = "spring.rabbitmq")。
 * RabbitProperties里面封装了配置的属性
 * 3.RabbitTemplate发送接收消息
 * 4.AmqpAdmin系统管理组件,声明队列。交换器等
 *@EnableRabbit开启基于注解的RabbitMq模式
 */
@EnableRabbit
@SpringBootApplication
public class SpringbootRabbitmqsApplication {

   public static void main(String[] args) {
      SpringApplication.run(SpringbootRabbitmqsApplication.class, args);
   }
}

并编写对应的service:

package com.rabbitmq.springbootrabbitmqs.service;

import com.rabbitmq.springbootrabbitmqs.bean.Book;

import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.SocketUtils;

@Service
public class BookService {
    @Autowired
    RabbitTemplate rabbitTemplate;
    @RabbitListener(queues = "hotnews")
    public void recive(Book book){
        System.out.println("收到消息"+book);
    }
    @RabbitListener(queues = "suquan")
    public void recive02(Message message){
        System.out.println(message.getBody());
        System.out.println(message.getMessageProperties());
    }
}

service层加上 @RabbitListener 第一个方法是获得book信息,第二个是获得消息体,消息头。

如果想添加消息交换机,队列,和绑定规则也很简单:


@Autowired AmqpAdmin amqpAdmin; @Test public void creatExchange(){ // amqpAdmin.declareExchange(new DirectExchange("amqpadmin.exchange")); //队列名字和是否持久化 // amqpAdmin.declareQueue(new Queue("amqpadmin.queue",true)); //绑定规则,目的地,类型;队列,给哪个exchange绑定,路由键:haha,路由参数没有就写null amqpAdmin.declareBinding(new Binding("amqpadmin.queue",Binding.DestinationType.QUEUE,"amqpadmin.exchange","hahha",null)); }


注入AmqpAdmin,编写交换器时候使用的是接口的实现默认传入一个交换器名,队列时候传入队列名,和是否持久化,绑定规则,有目的地,类型,路由键,参数.....