一)RabbitMQ简介
RabbitMQ是实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间件)。
1、可伸缩性:集群服务
2、消息持久化:从内存持久化消息到硬盘,再从硬盘加载到内存
备注:该软件需自行到RabbitMQ官网下载,并启动注册账号。
安装说明:
第一步: 从官网下载RabbitMQ配套的Erlang, 该版本为otp_win64_21.1.exe,一直默认安装。
第二步: 配置环境变量-->系统变量,配置如下:
ERLANG_HOME
C:\Program Files\erl10.1
第三步: 从官网下载RabbitMQ,该版本为rabbitmq-server-3.7.9.exe,一直默认安装。
第四步: 以管理员身份打开cmd命令窗口,输入以下命令,
"C:\Program Files\RabbitMQ Server\rabbitmq_server-3.7.9\sbin\rabbitmq-plugins.bat" enable rabbitmq_management
第五步: 在浏览器中输入: http://localhost:15672/,访问(现只能访问到登陆页面,继续下面步骤)。
第六步: 以管理员身份运行cmd命令窗口,输入: net stop RabbitMQ && net start RabbitMQ
第七步: 切换到,C:\Program Files\RabbitMQ Server\rabbitmq_server-3.7.9\sbin下
查看用户命令: rabbitmqctl.bat list_users
新增用户命令: rabbitmqctl.bat add_user username password
添加用户权限: rabbitmqctl.bat set_user_tags username administrator
rabbitmqctl.bat set_user_tags username tag1 tag2
注意: 权限包括,超级管理员(administrator)、监控者(monitoring)、策略制定者(policymaker)、普通管理者(management)、其他的(无法登陆)
更改用户密码: rabbitmqctl.bat change_password userName newPassword
删除用户: rabbitmqctl.bat delete_user username
二)集成RabbitMQ
在pom.xml文件中引入RabbitMQ相关jar
<?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.oysept.springboot</groupId>
<artifactId>oysept-springboot-rabbitmq</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>oysept-springboot-rabbitmq</name>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.0.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>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<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-starter-web</artifactId>
</dependency>
<!-- rabbitmq -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
在application.properties引入RabbitMQ的配置
server.port=8080
spring.application.name=spring-boot-rabbitmq
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=rabbitmq
spring.rabbitmq.password=rabbitmq
三)Direct模式
该模式规则是:先匹配,再发送。
第一步:先创建一个Direct配置类,该配置主要是注册两个队列
package com.oysept.springboot.direct.config;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Direct: 先匹配,再发送。
* @author ouyangjun
*/
@Configuration
public class DirectRabbitMQConfig {
// 注册一个发送String的队列
@Bean
public Queue queueString() {
return new Queue("helloOneToOne-String");
}
// 注册一个发送Object的队列
@Bean
public Queue queueObject() {
return new Queue("helloOneToOne-Object");
}
}
第二步:再创建两个消费者队列
package com.oysept.springboot.direct.receiver;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
@RabbitListener(queues = "helloOneToOne-String")
public class HelloStringReceiver {
// 接收字符串消息
@RabbitHandler
public void process(String str) {
System.out.println("-->HelloStringReceiver Println: " + str);
}
}
package com.oysept.springboot.direct.receiver;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
@RabbitListener(queues = "helloOneToOne-Object")
public class HelloObjectReceiver {
// 接收Object消息
@RabbitHandler
public void process(Object obj) {
System.out.println("-->HelloObjectReceiver Println: " + obj);
}
}
第三步:创建一个生产者队列
package com.oysept.springboot.direct.sender;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* Direct模式, @Component中的命名主要是为了避免冲突
* @author ouyangjun
*/
@Component(value="directSender")
public class HelloSender {
@Autowired
private AmqpTemplate amqpTemplate;
// 往String队列发送消息
public void sendString() {
String str = "Hello String![" +new Date() + "]";
this.amqpTemplate.convertAndSend("helloOneToOne-String", str);
}
// 往Object队列发送消息
public void sendObject() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("one", "oneValue");
map.put("two", 2222);
map.put("three", 9999.99);
this.amqpTemplate.convertAndSend("helloOneToOne-Object", map);
}
}
第四步:创建一个Direct测试工具类(需要先运行springboot项目,再运行该测试类,然后再去RabbitMQ界面查看)
package com.oysept.springboot.test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.oysept.springboot.direct.sender.HelloSender;
@RunWith(SpringRunner.class)
@SpringBootTest
public class DirectHelloTest {
@Autowired
private HelloSender helloSender;
// 测试
@Test
public void hello() throws Exception {
// 发送String消息
helloSender.sendString();
// 发送Object消息
helloSender.sendObject();
}
}
四)Fanout Exchange: 广播模式或订阅模式
给Fanout交换机发送消息,绑定了这个交换机的所有队列都收到这个消息。
第一步:创建三个Fanout队列
package com.oysept.springboot.fanout.config;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Fanout Exchange: 广播模式或者订阅模式,给Fanout交换机发送消息,绑定了这个交换机的所有队列都收到这个消息。
* @author ouyangjun
*/
@Configuration
public class FanoutRabbitMQConfig {
@Bean
public Queue AMsg() {
return new Queue("fanout.A");
}
@Bean
public Queue BMsg() {
return new Queue("fanout.B");
}
@Bean
public Queue CMsg() {
return new Queue("fanout.C");
}
@Bean
FanoutExchange fanoutExchange() {
return new FanoutExchange("fanoutExchange");
}
@Bean
Binding bindingExchangeA(Queue AMsg, FanoutExchange fanoutExchange) {
return BindingBuilder.bind(AMsg).to(fanoutExchange);
}
@Bean
Binding bindingExchangeB(Queue BMsg, FanoutExchange fanoutExchange) {
return BindingBuilder.bind(BMsg).to(fanoutExchange);
}
@Bean
Binding bindingExchangeC(Queue CMsg, FanoutExchange fanoutExchange) {
return BindingBuilder.bind(CMsg).to(fanoutExchange);
}
}
第二步:创建三个Fanout消费者队列
消费者A:
package com.oysept.springboot.fanout.receiver;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
/**
* 给fanout.A队列推送消息
* @author ouyangjun
*/
@Component
@RabbitListener(queues = "fanout.A")
public class HelloAMsgReceiver {
// 接收字符串消息
@RabbitHandler
public void process(String str) {
System.out.println("-->HelloAMsgReceiver AAAA Println: " + str);
}
}
消费者B:
package com.oysept.springboot.fanout.receiver;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
/**
* 给fanout.B队列推送消息
* @author ouyangjun
*/
@Component
@RabbitListener(queues = "fanout.B")
public class HelloBMsgReceiver {
@RabbitHandler
public void process(String str) {
System.out.println("-->HelloBMsgReceiver BBBB Println: " + str);
}
}
消费者C:
package com.oysept.springboot.fanout.receiver;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
/**
* 给fanout.C队列推送消息
* @author ouyangjun
*/
@Component
@RabbitListener(queues = "fanout.C")
public class HelloCMsgReceiver {
@RabbitHandler
public void process(String str) {
System.out.println("-->HelloCMsgReceiver CCCC Println: " + str);
}
}
第三步:创建一个Fanout生产者队列
package com.oysept.springboot.fanout.sender;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* Fanout Exchange模式, @Component中的命名主要是为了避免冲突
* @author ouyangjun
*/
@Component(value="fanoutSender")
public class HelloSender {
@Autowired
private AmqpTemplate amqpTemplate;
public void send() {
String str = "Hello Fanout Exchange Msgs!";
this.amqpTemplate.convertAndSend("fanoutExchange", "", str);
}
}
第四步:创建一个Fanout测试工具类
package com.oysept.springboot.test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.oysept.springboot.fanout.sender.HelloSender;
@RunWith(SpringRunner.class)
@SpringBootTest
public class FanoutHelloTest {
@Autowired
private HelloSender helloSender;
// 测试
@Test
public void helloMsgOne() throws Exception {
helloSender.send();
}
}
五)Topic Exchange
转发消息主要是根据通配符。
第一步:创建Topic Exchange队列
package com.oysept.springboot.topic.config;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Topic Exchange: 转发消息主要是根据通配符。
* 匹配规则:
* 一、路由键必须是一串字符,用句号(.) 隔开,比如说 aaa.bbb,或者 aaa.bbb.ccc 等。
* 二、路由模式必须包含一个 星号(*),主要用于匹配路由键指定位置的一个单词,比如说,一个路由模式是这样子:aaa..b.*,那么就只能匹配路由键是这样子的:第一个单词是 aaa,第四个单词是 b。
* #号(#)就表示相当于一个或者多个单词,例如一个匹配模式是aaa.bbb.ccc.#,那么,以aaa.bbb.ccc开头的路由键都是可以的。
* @author ouyangjun
*/
@Configuration
public class TopicRabbitMQConfig {
final static String msg = "topic.msg";
final static String msgs = "topic.msgs";
@Bean
public Queue queueMsg() {
return new Queue(TopicRabbitMQConfig.msg);
}
@Bean
public Queue queueMsgs() {
return new Queue(TopicRabbitMQConfig.msgs);
}
@Bean
TopicExchange exchange() {
return new TopicExchange("exchange");
}
@Bean
Binding bindingExchangeMsg(Queue queueMsg, TopicExchange exchange) {
return BindingBuilder.bind(queueMsg).to(exchange).with("topic.msg");
}
@Bean
Binding bindingExchangeMsgs(Queue queueMsgs, TopicExchange exchange) {
return BindingBuilder.bind(queueMsgs).to(exchange).with("topic.#");
}
}
第二步:创建Topic Exchange消费者队列
package com.oysept.springboot.topic.receiver;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
@RabbitListener(queues = "topic.msg")
public class HelloMsgOneReceiver {
@RabbitHandler
public void process(String str) {
System.out.println("-->HelloMsgOneReceiver Println: " + str);
}
}
package com.oysept.springboot.topic.receiver;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
@RabbitListener(queues = "topic.msgs")
public class HelloMsgTwoReceiver {
// 接收字符串消息
@RabbitHandler
public void process(String str) {
System.out.println("-->HelloMsgTwoReceiver Println: " + str);
}
}
第三步:创建Topic Exchange生产者队列
package com.oysept.springboot.topic.sender;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* Topic Exchange模式, @Component中的命名主要是为了避免冲突
* @author ouyangjun
*/
@Component(value="topicSender")
public class HelloSender {
@Autowired
private AmqpTemplate amqpTemplate;
// 发送sendOne会匹配到topic.#和topic.msg,两个Receiver都可以收到消息
public void sendOne() {
String str = "Hello this is msg one!";
this.amqpTemplate.convertAndSend("exchange", "topic.msg", str);
}
// 发送sendTwo只会匹配到topic.msgs,只有Receiver2监听到消息
public void sendTwo() {
String str = "Hello this is msg two!";
this.amqpTemplate.convertAndSend("exchange", "topic.msgs", str);
}
}
第四步:创建Topic Exchange测试工具类
package com.oysept.springboot.test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.oysept.springboot.topic.sender.HelloSender;
@RunWith(SpringRunner.class)
@SpringBootTest
public class TopicHelloTest {
@Autowired
private HelloSender helloSender;
// 测试
@Test
public void helloMsgOne() throws Exception {
helloSender.sendOne();
}
// 测试
@Test
public void helloMsgTwo() throws Exception {
helloSender.sendTwo();
}
}
项目结构图:
识别二维码关注个人微信公众号
本章完结,待续,欢迎转载!
本文说明:该文章属于原创,如需转载,请标明文章转载来源!