Springboot集成rabbitmq
流水不争先
Springboot集成rabbitmq
依赖:
<!-- rabbitmq -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
pom文件:
spring:
rabbitmq:
host: 192.168.72.130
port: 5672
username: queue
password: queue
virtual-host: hout_test
cache:
channel:
checkout-timeout: 50000 #超时时间
消息发送:
package com.atguigu.cache.rabbit.intergration;
import com.atguigu.cache.CacheApplicationTests;
import org.junit.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import javax.annotation.Resource;
/**
* @author fengH
* @version 1.0
* @description spring-boot集成rabbitmq 消息生产者
* @date 2021/1/31 14:40
*/
public class Provider extends CacheApplicationTests {
@Resource
private RabbitTemplate rabbitTemplate;
/**
* @author fengH
* @description 点对点消息发送
* @date 2021/2/1 11:05
*/
@Test
public void testMsgToQueue(){
// 消息名称 消息内容
rabbitTemplate.convertAndSend("hello", "hello mess");
}
/**
* @author fengH
* @description work模式。区别点对点在于消息接收者的多少
* 本身支持能者多劳
* 如果异常,消息不被消费。==> 支持手动确认
* @date 2021/2/1 11:15
*/
@Test
public void testMsgToWork(){
for (int i = 0; i < 20; i++) {
rabbitTemplate.convertAndSend("work", "work msg to queue");
}
}
/**
* @author fengH
* @description fanout模式
* 如果消费者异常,消息发送者会报出异常
* @date 2021/2/1 11:22
*/
@Test
public void testFanout(){
// 交换机名称 路有key(广播模式没有意义) 消息内容
rabbitTemplate.convertAndSend("fanout-test", "", "fanout msg to consumer");
}
/**
* @author fengH
* @description direct模式 -- rout路有模式
* 如果消费者异常,消息发送者会报出异常
* @date 2021/2/1 11:22
*/
@Test
public void testDirect(){
// 交换机名称 路有key 消息内容
rabbitTemplate.convertAndSend("direct-test", "error", "direct msg to consumer");
}
/**
* @author fengH
* @description topic模式 -- 动态路由,支持通配符
* * 只支持一个分隔符的通配
* # 支持多个
* @date 2021/2/1 11:57
*/
@Test
public void testTopic(){
// 交换机名称 路有key 消息内容
rabbitTemplate.convertAndSend("rout-test", "error.save", "direct msg to consumer");
}
}
消息接收:
package com.atguigu.cache.rabbit.intergration;
import com.atguigu.cache.CacheApplicationTests;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.stereotype.Component;
/**
* @author fengH
* @version 1.0
* @description spring-boot集成rabbitmq 消息消费者
* @date 2021/1/31 14:41
*/
@Component
public class Consumer extends CacheApplicationTests {
/**
* @author fengH
* @description 点对点消息接收 -- work模式
* @date 2021/2/1 11:04
* @param msg 接收的消息
* @return void
*/
@RabbitListener(queuesToDeclare = @Queue("work"))
private void queueReceiveMess1(String msg) {
System.out.println("consumer1:=============================" + msg);
}
/**
* @author fengH
* @description 点对点消息接收 -- work模式
* @date 2021/2/1 11:04
* @param msg 接收的消息
* @return void
*/
@RabbitListener(queuesToDeclare = @Queue("work"))
private void queueReceiveMess2(String msg) throws InterruptedException {
Thread.sleep(2000);
// 测试是否自动确认
//int i = 10 / 0;
System.out.println("consumer2:=============================" + msg);
}
/**
* @author fengH
* @description fanout工作模式 消费者1
* @date 2021/2/1 11:29
* @param msg 消息内容
* @return void
*/
@RabbitListener(bindings = {
@QueueBinding(
// 队列不指定名称,表示临时队列
value = @Queue,
// 绑定的交换机 交换机名称 工作模式
exchange = @Exchange(value = "fanout-test", type = "fanout")
)
})
public void fanoutReceive1(String msg){
System.out.println("fanout-consumer1=================" + msg);
}
/**
* @author fengH
* @description fanout工作模式 消费者2
* @date 2021/2/1 11:29
* @param msg 消息内容
* @return void
*/
@RabbitListener(bindings = {
@QueueBinding(
// 队列不指定名称,表示临时队列
value = @Queue,
// 绑定的交换机 交换机名称 工作模式
exchange = @Exchange(value = "fanout-test", type = "fanout")
)
})
public void fanoutReceive2(String msg){
System.out.println("fanout-consumer2=================" + msg);
}
/**
* @author fengH
* @description direct工作模式 消费者1
* 接口路由key = info/debug/error
* @date 2021/2/1 11:29
* @param msg 消息内容
* @return void
*/
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue,
exchange = @Exchange(value = "direct-test", type = "direct"),
// 接收哪些路由key
key = {"info", "debug", "error"}
)
})
public void directReceive1(String msg){
System.out.println("direct-consumer1=============" + msg);
}
/**
* @author fengH
* @description direct工作模式 消费者2
* 接口路由key = error
* @date 2021/2/1 11:29
* @param msg 消息内容
* @return void
*/
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue,
exchange = @Exchange(value = "direct-test", type = "direct"),
// 接收哪些路由key
key = {"error"}
)
})
public void directReceive2(String msg){
System.out.println("direct-consumer2=============" + msg);
}
/**
* @author fengH
* @description rout模式消费者1
* @date 2021/2/1 12:07
* @param msg 消息内容
*/
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue,
exchange = @Exchange(value = "rout-test", type = "rout"),
key = {"*.save"}
)
})
public void testRoutReceive1(String msg){
System.out.println("rout-consumer1================" + msg);
}
/**
* @author fengH
* @description rout模式消费者2
* @date 2021/2/1 12:07
* @param msg 消息内容
*/
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue,
exchange = @Exchange(value = "rout-test", type = "rout"),
key = {"#.save"}
)
})
public void testRoutReceive2(String msg){
System.out.println("rout-consumer2================" + msg);
}
}
rabbitmq原生api
获取连接及关闭资源方法:
public class RabbitMqTest{
/**
* @author fengH
* @description 获取rabbitmq连接
* @date 2021/1/29 18:50
*/
public static Connection getConnection(){
ConnectionFactory connectionFactory = new ConnectionFactory();
// ip
connectionFactory.setHost("192.168.72.130");
// 端口号
connectionFactory.setPort(5672);
// 设置哪个虚拟机
connectionFactory.setVirtualHost("host_test");
// 设置访问虚拟机的用户名密码
connectionFactory.setUsername("queue");
connectionFactory.setPassword("queue");
Connection connection = null;
try {
connection = connectionFactory.newConnection();
}catch (Exception e){
e.printStackTrace();
}
return connection;
}
public static void closeConnection(Channel channel, Connection connection){
if(channel != null){
try {
channel.close();
}catch (Exception e){
e.printStackTrace();
}
}
if (connection != null){
try {
connection.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
}
点对点:
/**
* @author fengH
* @description 生产消息
* @date 2021/1/29 17:33
*/
@Test
public void test() throws IOException, TimeoutException {
// 获取连接
Connection connection = getConnection();
// 创建连接通道
Channel channel = connection.createChannel();
// 通道绑定对应消息队列
// 参数1:queueName 队列名称,如果队列不存在则自动创建
// 参数2:durable 用来定义队列特性是否要持久化。true:持久化队列 false:不持久化
// 参数3:exclusive 是否独占队列。true:独占队列 false:不独占
// 独占队列:这个连接只能被当前通道绑定
// 参数4:autoDelete 是否在消费完成后自动删除队列。true:自动删除 false:不自动删除
// 参数5:额外附加参数
channel.queueDeclare("hello", false, false, false, null);
// 发部消息
// 参数1:交换机名称 参数2:队列名称 参数3:传递消息额外设置 参数4:消息的具体内容
channel.basicPublish("", "hello", null, "hello rabbit".getBytes(StandardCharsets.UTF_8));
// 关闭连接
closeConnection(channel, connection);
}
/**
* @author fengH
* @description 消费消息
* test测试时不会回调,所以需要用主方法测试
* @date 2021/1/29 18:48
*/
public static void main(String[] args) throws IOException {
Connection connection = getConnection();
// 创建连接通道
Channel channel = connection.createChannel();
// 通道绑定对象
channel.queueDeclare("hello", false, false, false, null);
// 消费消息
// 参数1:队列名称。
// 参数2:开启消息的自动确认机制
// 参数3:消费时的回调接口
channel.basicConsume("hello", true, new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println(new String(body));
}
});
}
wrork模式:
与点对点区别于接收者的多少
消息生产者:
package com.atguigu.cache.rabbit.work;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.MessageProperties;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
/**
* @author fengH
* @version 1.0
* @description
* @date 2021/1/30 13:36
*/
public class WorkProvider {
public static void main(String[] args) throws IOException {
// 获取连接
Connection connection = RabbitMqTest.getConnection();
// 创建通道
Channel channel = connection.createChannel();
// 绑定消息
// 消息名称
// 队列是否持久化 不保证消息持久化。消息持久化需要在发送消息时指定额外参数:MessageProperties.PERSISTENT_TEXT_PLAIN
// 是否是独占队列
// 消费完成是否自动删除
channel.queueDeclare("work_queue", false, false, false, null);
// 推送消息
// 交换机名称 消息名称 传递消息额外参数 消息内容
for (int i = 0; i < 20; i++) {
channel.basicPublish("", "work_queue", MessageProperties.PERSISTENT_TEXT_PLAIN, (i +"work_queue_test").getBytes(StandardCharsets.UTF_8));
}
RabbitMqTest.closeConnection(channel, connection);
}
}
消息消费者:
// 消费者1:
package com.atguigu.cache.rabbit.work;
import com.rabbitmq.client.*;
import java.io.IOException;
/**
* @author fengH
* @version 1.0
* @description
* @date 2021/1/30 13:50
*/
public class WorkConsumer {
public static void main(String[] args) throws IOException {
Connection connection = RabbitMqTest.getConnection();
Channel channel = connection.createChannel();
// 通道每次只传递一个消息
// 解决一次传递多个消息,当消费者宕机之后消息丢失的问题,还需要在通道绑定消息时关闭自动确认机制
channel.basicQos(1);
channel.queueDeclare("work_queue", false, false, false, null);
// 参数1: 队列名称
// 参数2: 是否开启自动确认
// 自动确认:消费者在接收消息之后直接将消息标记为已消费,不会管业务的处理
// 参数3: 回调接口
channel.basicConsume("work_queue", false, new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println(new String(body));
// 业务处理完成。手动确认接收消息
// 参数1: 确认队列中哪个具体的消息
// 参数2: 是否开启多条消息同时确认。(如果设置通道只发送一条消息,设置为false)
channel.basicAck(envelope.getDeliveryTag(), false);
}
});
}
}
// ===================消费者2==================
package com.atguigu.cache.rabbit.work;
import com.rabbitmq.client.*;
import java.io.IOException;
/**
* @author fengH
* @version 1.0
* @description
* @date 2021/1/30 13:53
*/
public class WorkConsumer1 {
public static void main(String[] args) throws IOException {
Connection connection = RabbitMqTest.getConnection();
Channel channel = connection.createChannel();
channel.queueDeclare("work_queue", false, false, false, null);
channel.basicConsume("work_queue", true, new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println(new String(body));
}
});
}
}
fanout模式:
消息生产者:
package com.atguigu.cache.rabbit.fanout;
import com.atguigu.cache.rabbit.work.RabbitMqTest;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
/**
* @author fengH
* @version 1.0
* @description 广播模式生产者
* @date 2021/1/30 14:39
*/
public class Provider {
public static void main(String[] args) throws IOException {
Connection connection = RabbitMqTest.getConnection();
Channel channel = connection.createChannel();
// 声明交换机 交换机名称 交换机类型:fanout
channel.exchangeDeclare("logs", "fanout");
// 发送消息
// 参数1:交换机名称
// 参数2:路由key,广播模式没有意义
// 参数3:消息持久化特性
// 参数4:消息内容
channel.basicPublish("logs", "", null, "fanout mess test".getBytes(StandardCharsets.UTF_8));
RabbitMqTest.closeConnection(channel, connection);
}
}
消息消费者:
// 消费者1:
package com.atguigu.cache.rabbit.fanout;
import com.atguigu.cache.rabbit.work.RabbitMqTest;
import com.rabbitmq.client.*;
import java.io.IOException;
/**
* @author fengH
* @version 1.0
* @description
* @date 2021/1/30 14:46
*/
public class Consumer1 {
public static void main(String[] args) throws IOException {
Connection connection = RabbitMqTest.getConnection();
Channel channel = connection.createChannel();
// 交换机名称 交换机类型
channel.exchangeDeclare("logs", "fanout");
// 创建临时队列
String queueName = channel.queueDeclare().getQueue();
// 绑定临时队列与交换机
// 临时队列 交换机 路有key:广播模式没有意义
channel.queueBind(queueName, "logs", "");
// 消费消息
channel.basicConsume(queueName, true, new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println(new String(body));
}
});
}
}
// ==================消费者2===================
package com.atguigu.cache.rabbit.fanout;
import com.atguigu.cache.rabbit.work.RabbitMqTest;
import com.rabbitmq.client.*;
import java.io.IOException;
/**
* @author fengH
* @version 1.0
* @description
* @date 2021/1/30 18:06
*/
public class Consumer2 {
public static void main(String[] args) throws IOException {
Connection connection = RabbitMqTest.getConnection();
Channel channel = connection.createChannel();
// 交换机名称 交换机类型
channel.exchangeDeclare("logs", "fanout");
// 创建临时队列
String queueName = channel.queueDeclare().getQueue();
// 绑定临时队列与交换机
// 临时队列 交换机 路有key:广播模式没有意义
channel.queueBind(queueName, "logs", "");
// 消费消息
channel.basicConsume(queueName, true, new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println(new String(body));
}
});
}
}
direct模式:
消息生产者:
package com.atguigu.cache.rabbit.direct;
import com.atguigu.cache.rabbit.work.RabbitMqTest;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import java.io.IOException;
/**
* @author fengH
* @version 1.0
* @description direct模式
* @date 2021/1/31 14:05
*/
public class Provider {
public static void main(String[] args) throws IOException {
Connection connection = RabbitMqTest.getConnection();
Channel channel = connection.createChannel();
// 绑定交换机
channel.exchangeDeclare("direct_test", "direct");
// 发送消息
channel.basicPublish("direct_test", "info", null,"direct mess to consumer".getBytes());
RabbitMqTest.closeConnection(channel, connection);
}
}
消息消费者:
// 消费者1
package com.atguigu.cache.rabbit.direct;
import com.atguigu.cache.rabbit.work.RabbitMqTest;
import com.rabbitmq.client.*;
import java.io.IOException;
/**
* @author fengH
* @version 1.0
* @description
* @date 2021/1/31 14:11
*/
public class Consumer1 {
public static void main(String[] args) throws IOException {
Connection connection = RabbitMqTest.getConnection();
Channel channel = connection.createChannel();
// 声明交换机及模式
channel.exchangeDeclare("direct_test", "direct");
// 临时队列名称
String queueName = channel.queueDeclare().getQueue();
// 交换机与队列绑定
channel.queueBind(queueName, "direct_test", "info");
channel.basicConsume(queueName, true, new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println(new String(body));
}
});
}
}
// ==================消费者2================
package com.atguigu.cache.rabbit.direct;
import com.atguigu.cache.rabbit.work.RabbitMqTest;
import com.rabbitmq.client.*;
import java.io.IOException;
/**
* @author fengH
* @version 1.0
* @description
* @date 2021/1/31 14:19
*/
public class Consumer2 {
public static void main(String[] args) throws IOException {
Connection connection = RabbitMqTest.getConnection();
Channel channel = connection.createChannel();
channel.exchangeDeclare("direct_test", "direct");
String queueName = channel.queueDeclare().getQueue();
channel.queueBind(queueName, "direct_test", "error");
channel.queueBind(queueName, "direct_test", "info");
channel.basicConsume(queueName, true, new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println(new String(body));
}
});
}
}
topic模式
消息生产者:
package com.atguigu.cache.rabbit.topic;
import com.atguigu.cache.rabbit.work.RabbitMqTest;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
/**
* @author fengH
* @version 1.0 topic模式
* @description
* @date 2021/1/31 14:25
*/
public class Provider {
public static void main(String[] args) throws IOException {
Connection connection = RabbitMqTest.getConnection();
Channel channel = connection.createChannel();
channel.exchangeDeclare("topic_test", "topic");
channel.basicPublish("topic_test", "user.log.save", null, "topic mess to consumer".getBytes(StandardCharsets.UTF_8));
RabbitMqTest.closeConnection(channel, connection);
}
}
消息消费者:
// 消费者1
package com.atguigu.cache.rabbit.topic;
import com.atguigu.cache.rabbit.work.RabbitMqTest;
import com.rabbitmq.client.*;
import java.io.IOException;
/**
* @author fengH
* @version 1.0
* @description
* @date 2021/1/31 14:28
*/
public class Consumer1 {
public static void main(String[] args) throws IOException {
Connection connection = RabbitMqTest.getConnection();
Channel channel = connection.createChannel();
channel.exchangeDeclare("topic_test", "topic");
String queueName = channel.queueDeclare().getQueue();
channel.queueBind(queueName, "topic_test", "*.save");
channel.basicConsume(queueName, true, new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println(new String(body));
}
});
}
}
// ====================消费者2====================
package com.atguigu.cache.rabbit.topic;
import com.atguigu.cache.rabbit.work.RabbitMqTest;
import com.rabbitmq.client.*;
import java.io.IOException;
/**
* @author fengH
* @version 1.0
* @description
* @date 2021/1/31 14:32
*/
public class Consumer2 {
public static void main(String[] args) throws IOException {
Connection connection = RabbitMqTest.getConnection();
Channel channel = connection.createChannel();
channel.exchangeDeclare("topic_test", "topic");
String queueName = channel.queueDeclare().getQueue();
channel.queueBind(queueName, "topic_test", "#.save");
channel.basicConsume(queueName, true, new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println(new String(body));
}
});
}
}