083:SpringBoot整合RabbitMQ
1 简单回顾RabbitMQ为什么是高级队列
课题内容
- RabbitMQ交换机四种类型
- RabbitMQ路由键的作用
- RabbitMQ实现发布订阅队列
- SpringBoot整合RabbitMQ实现通讯
- RabbitMQ相关课程疑问解答
2 四种交换机类型与扇形交换机
RabbitMQ交换机类型
Direct exchange(直连交换机)
Fanout exchange(扇型交换机)
Topic exchange(主题交换机)
Headers exchange(头交换机)
交换机核心作用:分发路由消息、中转
队列:容器 存放多个不同消息 遵循先进先出的原则
消息:传递的参数
扇型交换机主要的特征:只要队列绑定同一个交换机,生产者将消息投递到交换机中,交换机会将消息发送给所有绑定的队列进行存放消息。
3 直连交换机类型设计原理
路由键:交换机根据路由键的值,发送不同的队列中 匹配过程
Direct exchange(直连交换机):根据生产者投递不同的路由键,交换机匹配路由键发送到具体的队列中存放消息。
4 通过代码形式演示直连交换机
public class ExProducer {
private static final String QUEUE_NAME = "mayikt";
/**
* 定义交换机的名称
*/
private static final String DIRECT_EXCHANGE_NAME = "direct_exchange";
public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
System.out.println("生产者启动成功..");
// 1.创建连接
Connection connection = RabitMQConnection.getConnection();
// 2.创建通道
Channel channel = connection.createChannel();
// 不需要关心队列,只关注交换机
channel.exchangeDeclare(DIRECT_EXCHANGE_NAME, "direct", true);
String routingKey = "mayikt.email";
String msg = "生产者群发消息" + routingKey;
channel.basicPublish(DIRECT_EXCHANGE_NAME, routingKey, null, msg.getBytes());
channel.close();
connection.close();
// 如果交换机没有绑定队列,消息可能丢失
}
}
public class EmailConsumer {
/**
* 定义短信队列
*/
private static final String QUEUE_NAME = "consumer_direct_email";
/**
* 定义交换机的名称
*/
private static final String DIRECT_EXCHANGE_NAME = "direct_exchange";
public static void main(String[] args) throws IOException, TimeoutException {
System.out.println("邮件消费者...");
// 创建我们的连接
Connection connection = RabitMQConnection.getConnection();
// 创建我们通道
final Channel channel = connection.createChannel();
// 关联队列消费者关联队列
channel.queueBind(QUEUE_NAME, DIRECT_EXCHANGE_NAME, "mayikt.email");
DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String msg = new String(body, "UTF-8");
System.out.println("邮件消费者获取消息:" + msg);
}
};
// 开始监听消息 自动签收
channel.basicConsume(QUEUE_NAME, true, defaultConsumer);
}
}
public class SmsConsumer {
/**
* 定义短信队列
*/
private static final String QUEUE_NAME = "consumer_direct_sms";
/**
* 定义交换机的名称
*/
private static final String DIRECT_EXCHANGE_NAME = "direct_exchange";
public static void main(String[] args) throws IOException, TimeoutException {
System.out.println("短信消费者...");
// 创建我们的连接
Connection connection = RabitMQConnection.getConnection();
// 创建我们通道
final Channel channel = connection.createChannel();
// 关联队列消费者关联队列
channel.queueBind(QUEUE_NAME, DIRECT_EXCHANGE_NAME, "mayikt.sms");
DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String msg = new String(body, "UTF-8");
System.out.println("短信消费者获取消息:" + msg);
}
};
// 开始监听消息 自动签收
channel.basicConsume(QUEUE_NAME, true, defaultConsumer);
}
}
运行结果:
5 主题交换机类型实现模糊匹配
当交换机类型为topic类型时,根据队列绑定的路由键模糊转发到具体的队列中存放。
#号表示支持匹配多个词;
*号表示只能匹配一个词
生产者:
channel.basicPublish(EXCHANGE_NAME, "mayikt.meite.sms", null, msg.getBytes());
消费者:
channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "mayikt.#");
6 SpringBoot整合Rabbitmq配置
SpringBoot整合RabbitMQ
Maven相关依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
</parent>
<dependencies>
<!-- springboot-web组件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 添加springboot对amqp的支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!--fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.49</version>
</dependency>
</dependencies>
项目核心配置类
application.yml配置
spring:
rabbitmq:
####连接地址
host: 127.0.0.1
####端口号
port: 5672
####账号
username: guest
####密码
password: guest
### 地址
virtual-host: /mayikt_rabbitmq
RabbitMQConfig
@Component
public class RabbitMQConfig {
/**
* springboot项目整合队列
*/
/**
* 定义交换机
*/
private String EXCHANGE_SPRINGBOOT_NAME = "mayikt_springboot_exchange";
/**
* 短信队列
*/
private String FANOUT_QUEUE_SMS = "mayikt_fanout_sms_queue";
/**
* 邮件队列
*/
private String FANOUT_QUEUE_EMAIL = "mayikt_fanout_email_queue";
/**
* 声明sms队列
*
* @return
*/
@Bean
public Queue smsQueue() {
return new Queue(FANOUT_QUEUE_SMS);
}
/**
* 声明email队列
*
* @return
*/
@Bean
public Queue emailQueue() {
return new Queue(FANOUT_QUEUE_EMAIL);
}
/**
* 声明交换机
*
* @return
*/
@Bean
public FanoutExchange fanoutExchange() {
return new FanoutExchange(EXCHANGE_SPRINGBOOT_NAME);
}
/**
* 短信队列绑定交换机
*
* @param smsQueue 通过方法名字找到beanId,再找到对应队列
* @param fanoutExchange
* @return
*/
@Bean
public Binding smsBindingExchange(Queue smsQueue, FanoutExchange fanoutExchange) {
return BindingBuilder.bind(smsQueue).to(fanoutExchange);
}
/**
* 邮件队列绑定交换机
*
* @param emailQueue
* @param fanoutExchange
* @return
*/
@Bean
public Binding emailBindingExchange(Queue emailQueue, FanoutExchange fanoutExchange) {
return BindingBuilder.bind(emailQueue).to(fanoutExchange);
}
}
7 使用SpringBoot自动创建队列和交换机
生产者与消费者
@RestController
public class FanoutProducer {
@Autowired
private AmqpTemplate amqpTemplate;
/**
* 定义交换机
*/
private String EXCHANGE_SPRINGBOOT_NAME = "mayikt_springboot_exchange";
@RequestMapping("/sendMsg")
public String sendMsg(String msg) {
// 参数1 交换机名称、参数2路由key、参数3 消息内容
amqpTemplate.convertAndSend(EXCHANGE_SPRINGBOOT_NAME, "", msg);
// 投递消息,客户端不会立马知道消息是否被消费,能够确认知道是否投递到消息中间件
// 可以根据消息全局Id主动查询 前端ajax
return "success";
}
}
@Component
@RabbitListener(queues = "mayikt_fanout_sms_queue")
public class FanoutSmsConsumer {
/**
* 监听队列回调的方法
*
* @param msg
*/
@RabbitHandler
public void process(String msg) {
System.out.println("短信消费者消息msg:" + msg);
}
}
@Component
@RabbitListener(queues = "mayikt_fanout_email_queue")
public class FanoutEmailConsumer {
/**
* 监听队列回调的方法
*
* @param msg
*/
@RabbitHandler
public void process(String msg) {
System.out.println("邮件消费者消息msg:" + msg);
}
}
@SpringBootApplication
public class SpringApp {
public static void main(String[] args) {
SpringApplication.run(SpringApp.class);
}
}
8 实现路由分发多个不同队列
运行结果: