文章目录
maven坐标
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.7.2</version>
</dependency>
简单的工具类
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
/**
* @Author: czn
* @Date 2021/2/6 14:46
*/
public class RabbitMQUtils {
private static ConnectionFactory connectionFactory;
static {
connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.174.134");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/ems");
connectionFactory.setUsername("ems");
connectionFactory.setPassword("123");
}
public static Connection getConnection(){
try {
return connectionFactory.newConnection();
}catch (Exception e){
e.printStackTrace();
}
return null;
}
public static void closeConnectionAndChanel(Channel channel,Connection conn){
try {
if (channel!=null) {
channel.close();
}
if (conn!=null) {
conn.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
1 简单队列/HelloWorld模式
一个生产者对应一个消费者
1.1生产者
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import org.junit.Test;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class Provider {
@Test
public void testSendMessage() throws IOException, TimeoutException {
//1.创建mq的连接工厂
ConnectionFactory connectionFactory = new ConnectionFactory();
//设置连接mq主机
connectionFactory.setHost("192.168.174.134");
//设置端口号
connectionFactory.setPort(5672);
//设置连接那个虚拟机
connectionFactory.setVirtualHost("/ems");
//设置访问虚拟主机的用户名和密码
connectionFactory.setUsername("ems");
connectionFactory.setPassword("123");
//获取连接对象
Connection connection = connectionFactory.newConnection();
//获取连接中的通道
Channel channel = connection.createChannel();
//通道绑定对应消息队列
//参数1:队列名称,如果队列不存在自动创建
//参数2:用来定义队列特性是否持久化
//参数3:是否独占队列
//参数4:是否在消费完成后自动删除队列
channel.queueDeclare("hello", false, false, false, null);
//发布消息
//参数1:交换机名称
//参数2:队列名称
//参数3:传递消息额外设置
//参数4:消息的具体内容
channel.basicPublish("","hello",null,"emm".getBytes());
channel.close();
connection.close();
}
}
1.2 消费者
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class Customer {
public static void main(String[] args) throws IOException, TimeoutException {
//1.创建mq的连接工厂
ConnectionFactory factory = new ConnectionFactory();
//设置连接mq主机
factory.setHost("192.168.174.134");
//设置端口号
factory.setPort(5672);
//设置连接那个虚拟机
factory.setVirtualHost("/ems");
//设置访问虚拟主机的用户名和密码
factory.setUsername("ems");
factory.setPassword("123");
//获取连接对象
Connection connection = factory.newConnection();
//获取连接中的通道
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));
}
});
channel.close();
connection.close();
}
}
1.3 运行
2 work 模式
一个生产者对应多个消费者,但是一条消息只能有一个消费者获得消息
2.1轮询分配
2.1.1 生产者
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import utils.RabbitMQUtils;
import java.io.IOException;
public class Provider {
public static void main(String[] args) throws IOException {
Connection connection = RabbitMQUtils.getConnection();
Channel channel = connection.createChannel();
channel.queueDeclare("work",true,false,false,null);
for (int i = 0 ; i < 20 ; i++){
channel.basicPublish("","work",null,(i+"===>hello work queue").getBytes());
}
RabbitMQUtils.closeConnectionAndChanel(channel,connection);
}
}
2.1.2 消费者1
import com.rabbitmq.client.*;
import utils.RabbitMQUtils;
import java.io.IOException;
/**
* @Author: czn
* @Date 2021/2/6 16:57
*/
public class Costomer1 {
public static void main(String[] args) throws IOException {
Connection connection = RabbitMQUtils.getConnection();
Channel channel = connection.createChannel();
channel.queueDeclare("work",true,false,false,null);
channel.basicConsume("work",true,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("消费者1:"+new String(body));
}
});
}
}
2.1.3消费者2
import com.rabbitmq.client.*;
import utils.RabbitMQUtils;
import java.io.IOException;
public class Costomer2 {
public static void main(String[] args) throws IOException {
Connection connection = RabbitMQUtils.getConnection();
Channel channel = connection.createChannel();
channel.queueDeclare("work",true,false,false,null);
channel.basicConsume("work",true,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("消费者2:"+new String(body));
}
});
}
}
2.1.4 运行
消费者1
消费者2
2.2 公平分配(能者多劳)
2.2.1 消费者1
import com.rabbitmq.client.*;
import utils.RabbitMQUtils;
import java.io.IOException;
/**
* @Author: czn
* @Date 2021/2/6 16:57
*/
public class Costomer3 {
public static void main(String[] args) throws IOException {
Connection connection = RabbitMQUtils.getConnection();
final Channel channel = connection.createChannel();
//每次只能消费一个消息
channel.basicQos(1);
channel.queueDeclare("work",true,false,false,null);
//参数1:队列名
// 参数2:消息自动确认 true 消费者自动向rabbitmq确认消息消费 false不会自动确认消息
channel.basicConsume("work",false,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
try{
Thread.sleep(2000);
}catch (Exception e){
e.printStackTrace();
}
System.out.println("消费者1:"+new String(body));
//参数1:确认队列中那个具体消息
// 参数2:是否开启多个消息同时确定
channel.basicAck(envelope.getDeliveryTag(),false);
}
});
}
}
2.2.2 消费者4
import com.rabbitmq.client.*;
import utils.RabbitMQUtils;
import java.io.IOException;
/**
* @Author: czn
* @Date 2021/2/6 16:57
*/
public class Costomer4 {
public static void main(String[] args) throws IOException {
Connection connection = RabbitMQUtils.getConnection();
final Channel channel = connection.createChannel();
channel.basicQos(1);
channel.queueDeclare("work",true,false,false,null);
channel.basicConsume("work",false,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("消费者4:"+new String(body));
//手动确认
// 参数1:手动确认标识
// 参数2:false 每次确认一个
channel.basicAck(envelope.getDeliveryTag(),false);
}
});
}
}
2.2.3 生产者
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import utils.RabbitMQUtils;
import java.io.IOException;
/**
* @Author: czn
* @Date 2021/2/6 16:50
*/
public class Provider {
public static void main(String[] args) throws IOException {
Connection connection = RabbitMQUtils.getConnection();
Channel channel = connection.createChannel();
channel.queueDeclare("work",true,false,false,null);
for (int i = 0 ; i < 20 ; i++){
channel.basicPublish("","work",null,(i+"===>hello work queue").getBytes());
}
RabbitMQUtils.closeConnectionAndChanel(channel,connection);
}
}
2.2.4 运行
消费者3(睡眠2s)
消费者4
3 fanout广播模式/发布/订阅模式
一个消费者将消息首先发送到交换器,交换器绑定多个队列,然后被监听该队列的消费者所接收并消费.
3.1 生产者
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import utils.RabbitMQUtils;
import java.io.IOException;
public class Provider {
public static void main(String[] args) throws IOException {
Connection connection = RabbitMQUtils.getConnection();
Channel channel = connection.createChannel();
// 将通道声明指定交换机
// 参数1:交换机名称 如果没有则自动创建
// 参数2:交换机类型
channel.exchangeDeclare("logs", "fanout");
// 发消息
channel.basicPublish("logs","",null,"fanout message".getBytes());
//释放资源
RabbitMQUtils.closeConnectionAndChanel(channel,connection);
}
}
3.2 消费者1,2,3
import com.rabbitmq.client.*;
import utils.RabbitMQUtils;
import java.io.IOException;
public class Costomer1 {
public static void main(String[] args) throws IOException {
Connection connection = RabbitMQUtils.getConnection();
Channel channel = connection.createChannel();
//通道绑定交换机
channel.exchangeDeclare("logs","fanout");
//绑定临时队列
String queueName = channel.queueDeclare().getQueue();
//绑定交换机和队列
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("消费者1: "+new String(body));
}
});
}
}
3.3 运行
当生产者发布消息时,三个消费者都同时消费了
4 Routing 路由模式
在Fanout模式中,一条消息,会被所有订阅的队列都消费。但是,在某些场景下,我们希望不同的消息被不同的队列消费。这时就要用到Direct类型的Exchange.
4.1 生产者
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import utils.RabbitMQUtils;
import java.io.IOException;
public class Provider {
public static void main(String[] args) throws IOException {
Connection connection = RabbitMQUtils.getConnection();
Channel channel = connection.createChannel();
// 参数1:交换机名称
// 参数2:交换机类型
channel.exchangeDeclare("logs_direct","direct");
// 发送消息
String routingKey = "warning";
channel.basicPublish("logs_direct",routingKey,null,("direct模型 route key:["+routingKey+"]发送的消息").getBytes());
RabbitMQUtils.closeConnectionAndChanel(channel,connection);
}
}
4.2 消费者1
import com.rabbitmq.client.*;
import utils.RabbitMQUtils;
import java.io.IOException;
public class Customer1 {
public static void main(String[] args) throws IOException {
Connection connection = RabbitMQUtils.getConnection();
Channel channel = connection.createChannel();
//声明交换机和交换机类型
channel.exchangeDeclare("logs_direct","direct");
//创建临时队列
String queue = channel.queueDeclare().getQueue();
//基于route key绑定队列和交换机
channel.queueBind(queue,"logs_direct","error");
//获取消费的消息
channel.basicConsume(queue,true,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("消费者1:"+new String(body));
}
});
}
}
4.3 消费者2
import com.rabbitmq.client.*;
import utils.RabbitMQUtils;
import java.io.IOException;
public class Customer2 {
public static void main(String[] args) throws IOException {
Connection connection = RabbitMQUtils.getConnection();
Channel channel = connection.createChannel();
//声明交换机和交换机类型
channel.exchangeDeclare("logs_direct","direct");
//创建临时队列
String queue = channel.queueDeclare().getQueue();
//基于route key绑定队列和交换机
channel.queueBind(queue,"logs_direct","info");
channel.queueBind(queue,"logs_direct","error");
channel.queueBind(queue,"logs_direct","warning");
//获取消费的消息
channel.basicConsume(queue,true,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("消费者2:"+new String(body));
}
});
}
}
4.4 运行
生产者分别运行 info,error,warning
消费者1
消费者2
5 Topic
Topic类型的Exchange与Direct相比,都是可以根据Routingkey把消息路由到不同的队列。只不过Topic类型Exchange可以让队列在绑定Routing key的时候使用通配"符!这种模型Routingkey一般都是由一个或多个单词组成,3个单词之间以.分割,例如: item.insert
- 符号#: 表示匹配一个或多个词,
- 符号*: 表示匹配一个词.
5.1 生产者
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import utils.RabbitMQUtils;
import java.io.IOException;
public class Provider {
public static void main(String[] args) throws IOException {
Connection connection = RabbitMQUtils.getConnection();
Channel channel = connection.createChannel();
channel.exchangeDeclare("topics","topic");
//发布消息
String routekey = "user.save.delete";
channel.basicPublish("topics",routekey,null,("topic动态路由["+routekey+"]").getBytes());
RabbitMQUtils.closeConnectionAndChanel(channel,connection);
}
}
5.2 消费者1
import com.rabbitmq.client.*;
import utils.RabbitMQUtils;
import java.io.IOException;
public class Customer1 {
public static void main(String[] args) throws IOException {
Connection connection = RabbitMQUtils.getConnection();
Channel channel = connection.createChannel();
channel.exchangeDeclare("topics","topic");
//创建临时队列
String queue = channel.queueDeclare().getQueue();
//绑定队列及交换机
channel.queueBind(queue,"topics","user.*");
//消费消息
channel.basicConsume(queue,true,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("消费者1:"+new String(body));
}
});
}
}
5.3 消费者2
import com.rabbitmq.client.*;
import utils.RabbitMQUtils;
import java.io.IOException;
/**
* @Author: czn
* @Date 2021/2/7 11:11
*/
public class Customer2 {
public static void main(String[] args) throws IOException {
Connection connection = RabbitMQUtils.getConnection();
Channel channel = connection.createChannel();
channel.exchangeDeclare("topics","topic");
//创建临时队列
String queue = channel.queueDeclare().getQueue();
//绑定队列及交换机
channel.queueBind(queue,"topics","user.#");
//消费消息
channel.basicConsume(queue,true,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("消费者2:"+new String(body));
}
});
}
}
5.4 运行
生产者分别运行 user.sava.delete , user.save
消费者1
消费者2