1.RabbitMQ简介

   RabbitMQ是一套开源的消息队列服务软件,实现了高级消息队列协议(AMQP),服务器采用Erlang语言开发,支持多种客户端,如:Python、Ruby、Java、JMS、C#、PHP、JavaScript等。

2.Erlang安装

   (1)安装RabbitMQ需要先安装Erlang语言开发包,官网下载地址:https://www.erlang.org/downloads

   (2)配置环境变量:

       新建系统变量:ERLANG_HOME= E:\erl10.5 

       添加到PATH:  %ERLANG_HOME%\bin;

       打开cmd命令框,输入命令:erl

       

       如上图所示,则安装成功

       注意:安装RabbitMQ需要与Erlang版本对应,否则会安装失败。

                 查看版本对应关系地址:https://www.rabbitmq.com/which-erlang.html

3.RabbitMQ安装

   (1)官网下载地址:https://www.rabbitmq.com/download.html

   (2)配置环境变量:

       新建系统变量:RABBITMQ_SERVER:E:\RabbitMQ Server\rabbitmq_server-3.8.1

       添加到PATH:  %RABBITMQ_SERVER%\sbin;

       打开cmd命令框,输入命令:rabbitmq-plugins enable rabbitmq_management

       

        如上图所示,则安装成功,并激活了RabbitMQ可视化管理插件

        安装系统服务:rabbitmq-service install

        启动系统服务:rabbitmq-service start

        启动服务后,访问地址:localhost:15672

        

        如上图所示,则启动成功。默认账号:guest,默认密码:guest

        注意:RabbitMQ修改日志和数据的存放路径默认为C盘的\Users\Administrator\AppData\Roaming\RabbitMQ路径下,该路径不能包含中文,否则会启动服务失败,若包含中文,可配置系统变量RABBITMQ_BASE来手动指定数据存放目录。

如:RABBITMQ_BASE:E:\RabbitMQ Server\rabbitmq_server-3.8.1\data

4.pom.xml添加RabbitMQ依赖

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

5.application.properties添加RabbitMQ配置

#RabbitMQ配置
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.virtual-host=/
#消费者数量
spring.rabbitmq.listener.simple.concurrency=10
#最大消费者数量
spring.rabbitmq.listener.simple.max-concurrency=10
#消费者每次从队列获取的消息数量。写多了,如果长时间得不到消费,数据就一直得不到处理
spring.rabbitmq.listener.simple.prefetch=1
#消费者自动启动
spring.rabbitmq.listener.auto-startup=true
#消费者消费失败,自动重新入队
spring.rabbitmq.listener.simple.default-requeue-rejected=true
#启用发送重试 队列满了发不进去时启动重试
spring.rabbitmq.template.retry.enabled=true
#1秒钟后重试一次
spring.rabbitmq.template.retry.initial-interval=1000
#最大重试次数 3次
spring.rabbitmq.template.retry.max-attempts=3
#最大间隔 10s
spring.rabbitmq.template.retry.max-interval=10000
#等待间隔 的倍数。如果为2  第一次 乘以2 等1秒, 第二次 乘以2 等2秒 ,第三次 乘以2 等4秒
spring.rabbitmq.template.retry.multiplier=1.0

6.创建RabbitMQ配置类

import java.util.HashMap;
import java.util.Map;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.HeadersExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MQConfig {
	
	//Direct模式
	public static final String QUEUE="queue";
	//Topic模式
	public static final String TOPIC_QUEUE1="topic.queue1";
	public static final String TOPIC_QUEUE2="topic.queue2";
	public static final String TOPIC_EXCHANGE="topic.exchange";
	public static final String ROUTINIG_KEY1="topic.key1";
	public static final String ROUTINIG_KEY2="topic.#";
	//Fanout模式
	public static final String FANOUT_QUEUE1="fanout.queue1";
	public static final String FANOUT_QUEUE2="fanout.queue2";
	public static final String FANOUT_EXCHANGE="fanout.exchange";
	//Header模式
	public static final String HEADER_QUEUE="header.queue";
	public static final String HEADER_EXCHANGE="header.exchange";
	
	/**
	 * Direct模式
	 */
	@Bean
	public Queue queue() {
	    //名称,是否持久化
	    return new Queue(QUEUE,true);
	}
	
	/**
	 * Topic模式
	 */
	@Bean
	public Queue topicqueue1() {
	    //名称,是否持久化
	    return new Queue(TOPIC_QUEUE1,true);
	}
	
	@Bean
	public Queue topicqueue2() {
	    //名称,是否持久化
	    return new Queue(TOPIC_QUEUE2,true);
	}
	
	//先将消息放到exchange中去,再把消息放到queue里面去
	@Bean
	public TopicExchange topicExchange() {
	    //名称
	    return new TopicExchange(TOPIC_EXCHANGE);
	}
	
	@Bean
	public Binding topicBinding1() {
	    //绑定到某一个queue上面
	    return BindingBuilder.bind(topicqueue1()).to(topicExchange()).with(ROUTINIG_KEY1);//"topic.key1"
	}
	
	@Bean
	public Binding topicBinding2() {
	    //绑定到某一个queue上面
	    return BindingBuilder.bind(topicqueue2()).to(topicExchange()).with(ROUTINIG_KEY2);//"topic.#"  #匹配一个或者多个字符
	}
	
	/**
	 * Fanout模式(广播模式)
	 */
	@Bean
	public Queue fanoutqueue1() {
	    //名称,是否持久化
	    return new Queue(FANOUT_QUEUE1,true);
	}
	
	@Bean
	public Queue fanoutqueue2() {
	    //名称,是否持久化
	    return new Queue(FANOUT_QUEUE2,true);
	}
	@Bean
	public FanoutExchange fanoutExchange() {
	    //名称
	    return new FanoutExchange(FANOUT_EXCHANGE);
	}
	@Bean
	public Binding fanoutBinding1() {
	    //绑定到某一个queue上面
	    return BindingBuilder.bind(fanoutqueue1()).to(fanoutExchange());//广播,没有key的
	}
	
	@Bean
	public Binding fanoutBinding2() {
	    //绑定到某一个queue上面
	    return BindingBuilder.bind(fanoutqueue2()).to(fanoutExchange());//广播,没有key的
	}
	
	/**
	 * Header模式
	 */
	@Bean
	public Queue headerQueue1() {
	    //名称,是否持久化
	    return new Queue(HEADER_QUEUE,true);
	}
	
	@Bean
	public HeadersExchange headersExchange() {
	    //名称
	    return new HeadersExchange(HEADER_EXCHANGE);
	}
	
	/**
	 * headerbinding
	 * 在这个message里面,会有一个head部分,必须完全满足map里面的key-value,才能放到队列中
	 */
	@Bean
	public Binding headerBinding() {
	    //绑定到某一个queue上面
	    Map<String,Object> map=new HashMap<String,Object>();
	    map.put("header1","value1");
	    map.put("header2","value2");
	    return BindingBuilder.bind(headerQueue1()).to(headersExchange()).whereAll(map).match();
	}
	
}

7.创建RabbitMQ生产者

import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

//生产者
@Service
public class MQSender {
	
    @Autowired
    AmqpTemplate amqpTemplate;

    //Direct模式
    public void send(String msg) {
	System.out.println("Direct模式发送消息>>>:"+msg);
	//第一个参数队列的名字,第二个参数发出的信息
	amqpTemplate.convertAndSend(MQConfig.QUEUE, msg);
    }
	
    //Topic模式
    public void sendTopic(Object msg) {
	System.out.println("Topic模式发送消息>>>:"+msg);
	amqpTemplate.convertAndSend(MQConfig.TOPIC_EXCHANGE,"topic.key1",msg+"1");
	amqpTemplate.convertAndSend(MQConfig.TOPIC_EXCHANGE,"topic.key2",msg+"2");
    }
	
    //Fanout模式
    public void sendFanout(Object msg) {
	System.out.println("Fanout模式发送消息>>>:"+msg);
	//广播,不需要key
	amqpTemplate.convertAndSend(MQConfig.FANOUT_EXCHANGE,"",msg);
    }
	
    //Header模式
    public void sendHeader(String msg) {
	System.out.println("Header模式发送消息>>>:"+msg);
	//properties设置Header需要跟绑定的map完全一致,才能放到队列中
	MessageProperties properties=new MessageProperties();
	properties.setHeader("header1", "value1");
	properties.setHeader("header2", "value2");
	Message obj=new Message(msg.getBytes(),properties);
	//传入一个message的对象,不需要key
	amqpTemplate.convertAndSend(MQConfig.HEADER_EXCHANGE, "", obj);
    }
	
}

8.创建RabbitMQ消费者

import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;

//消费者
@Service
public class MQReceiver {

	@RabbitListener(queues=MQConfig.QUEUE)//指明监听的是哪一个queue
	public void receive(String msg) {
	    System.out.println("Direct模式接收消息:"+msg);
	}
	
	@RabbitListener(queues=MQConfig.TOPIC_QUEUE1)//指明监听的是哪一个queue
	public void receiveTopic1(String msg) {
	    System.out.println("Topic模式1接收消息:"+msg);
	}
	
	@RabbitListener(queues=MQConfig.TOPIC_QUEUE2)//指明监听的是哪一个queue
	public void receiveTopic2(String msg) {
	    System.out.println("Topic模式2接收消息:"+msg);
	}
	
	@RabbitListener(queues=MQConfig.FANOUT_QUEUE1)//指明监听的是哪一个queue
	public void receiveFanout1(String msg) {
	    System.out.println("Fanout模式1接收消息:"+msg);
	}
	
	@RabbitListener(queues=MQConfig.FANOUT_QUEUE2)//指明监听的是哪一个queue
	public void receiveFanout2(String msg) {
	    System.out.println("Fanout模式2接收消息:"+msg);
	}
	
	@RabbitListener(queues=MQConfig.HEADER_QUEUE)//指明监听的是哪一个queue
	public void receiveHeader(byte[] msg) {
	    System.out.println("Header模式接收消息:"+new String(msg));
	}
	
}

9.测试发送消息

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
 
import cn.com.app.rabbitmq.MQSender;
 
@Controller
public class Test {
 
    @Autowired
    private MQSender sender;
	
    @RequestMapping("/sendMsg")
    @ResponseBody
    public void sendMsg() throws Exception {
    	//Direct模式
    	sender.send("Direct Hello");
    	//Topic模式
    	sender.sendTopic("Topic Hello");
    	//Fanout模式
    	sender.sendFanout("Fanout Hello");
    	//Header模式
    	sender.sendHeader("Header Hello");
    }
	
}

 

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐