入门
引入依赖
<dependencies>
<!--引入跟rabbitmq交互的客户端jar包-->
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>4.0.2</version>
</dependency>
</dependencies>
生产者
Producer {
public static void main(String[] args) throws IOException, TimeoutException {
//1.创建连接,连接上MQ服务器
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.142.137");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/java1907");
connectionFactory.setUsername("java1907");
connectionFactory.setPassword("123");
Connection connection = connectionFactory.newConnection();
//2.基于这个连接对象,创建对应的通道
Channel channel = connection.createChannel();
//3.声明队列
//如果该队列不存在,则创建该队列,否则,不创建
channel.queueDeclare(
"simple-queue",false,false,false,null);
//4.发送消息到队列上
String message = "消息队列是一个非常重要的中间件";
//我们没有指定交换机
//实际是使用默认交换机
channel.basicPublish("","simple-queue",null,message.getBytes());
/* exchange – the exchange to publish the message to
routingKey – the routing key
props – other properties for the message - routing headers etc
body – the message body*/
System.out.println("发送消息成功!");
}
}
第一个参数是交换机,没有就使用默认direct,转发给第二个参数队列;
消费者
1. 简单队列

public class MyConsumer {
public static void main(String[] args) throws IOException, TimeoutException {
//1.创建连接,连接上MQ服务器
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.142.137");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/java1907");
connectionFactory.setUsername("java1907");
connectionFactory.setPassword("123");
Connection connection = connectionFactory.newConnection();
//2.基于这个连接对象,创建对应的通道
Channel channel = connection.createChannel();
//3.创建一个消费者对象,并且写好处理消息的逻辑
Consumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String message = new String(body);
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("接收到的消息是:"+message);
//手工确认模式,告知MQ服务器,消息已经被正确处理
//multiple表示是否批量确认
//为true,则批量确认,假设envelope.getDeliveryTag()=10,意味着将1-10的消息都确认
//为false,则只确认10
channel.basicAck(envelope.getDeliveryTag(),false);//手工确认模式!
//第一个参数:消息标记;第二个参数multiple.
//long deliveryTag, boolean multiple
}
};
//4.需要让消费者去监听队列
//autoACK=true:自动确认模式
//autoACK=false:手工确认模式 (推荐)
channel.basicConsume("simple-queue",false,consumer);
}
}
autoAck是否自动确认模式
2、work模式
生产者
public class Producer {
private static final String QUEUE_NAME = "work-queue";
public static void main(String[] args) throws IOException, TimeoutException {
//1.创建连接,连接上MQ服务器
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.142.137");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/java1907");
connectionFactory.setUsername("java1907");
connectionFactory.setPassword("123");
Connection connection = connectionFactory.newConnection();
//2.基于这个连接对象,创建对应的通道
Channel channel = connection.createChannel();
//3.声明队列
//如果该队列不存在,则创建该队列,否则,不创建
channel.queueDeclare(
QUEUE_NAME,false,false,false,null);
//4.发送消息到队列上
for (int i = 0; i < 10; i++) {
String message = "这是第"+i+"遍说我爱你";
channel.basicPublish("",QUEUE_NAME,null,message.getBytes());
}
System.out.println("发送消息成功!");
}
}
消费者1
public class MyConsumer1 {
private static final String QUEUE_NAME = "work-queue";
public static void main(String[] args) throws IOException, TimeoutException {
//1.创建连接,连接上MQ服务器
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.142.137");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/java1907");
connectionFactory.setUsername("java1907");
connectionFactory.setPassword("123");
Connection connection = connectionFactory.newConnection();
//2.基于这个连接对象,创建对应的通道
Channel channel = connection.createChannel();
//限流,最多只放行一个消息 //叫号系统 1-10
channel.basicQos(1);
//3.创建一个消费者对象,并且写好处理消息的逻辑
Consumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String message = new String(body);
System.out.println("消费者1:接收到的消息是:"+message);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//手工确认模式,告知MQ服务器,消息已经被正确处理
//multiple表示是否批量确认
//为true,则批量确认,假设envelope.getDeliveryTag()=10,意味着将1-10的消息都确认
//为false,则只确认10
channel.basicAck(envelope.getDeliveryTag(),false);
}
};
//4.需要让消费者去监听队列
//autoACK=true:自动确认模式
//autoACK=false:手工确认模式 (推荐)
channel.basicConsume(QUEUE_NAME,false,consumer);
}
}
消费者2
public class MyConsumer2 {
private static final String QUEUE_NAME = "work-queue";
public static void main(String[] args) throws IOException, TimeoutException {
//1.创建连接,连接上MQ服务器
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.142.137");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/java1907");
connectionFactory.setUsername("java1907");
connectionFactory.setPassword("123");
Connection connection = connectionFactory.newConnection();
//2.基于这个连接对象,创建对应的通道
Channel channel = connection.createChannel();
//限流,最多只放行一个消息
channel.basicQos(1);
//3.创建一个消费者对象,并且写好处理消息的逻辑
Consumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String message = new String(body);
System.out.println("消费者2:接收到的消息是:"+message);
//手工确认模式,告知MQ服务器,消息已经被正确处理
//multiple表示是否批量确认
//为true,则批量确认,假设envelope.getDeliveryTag()=10,意味着将1-10的消息都确认
//为false,则只确认10
channel.basicAck(envelope.getDeliveryTag(),false);
}
};
//4.需要让消费者去监听队列
//autoACK=true:自动确认模式
//autoACK=false:手工确认模式 (推荐)
channel.basicConsume(QUEUE_NAME,false,consumer);
}
}
问题:两个消费者如何抢10条消息?
共享的状态下,第一个消费者消费完后,第二个消费者就消费不到了。
默认情况下是均分的状态,你消费一条我消费一条。
问题:如果一个消费者的服务器特别慢怎么处理?不合理啊
采用限流+手工确认,假如10条消息,A处理的慢,B处理快,那么B就多处理几条。
channel.basicQos(1);
3、发布订阅模式
之前生产者面向的是队列,现在面向的是交换机
交换机的类型为"fanout".
- 生产者
public class Producer {
private static final String EXCHANGE_NAME = "fanout_exchange";
public static void main(String[] args) throws IOException, TimeoutException {
//1.创建连接,连接上MQ服务器
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.142.137");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/java1907");
connectionFactory.setUsername("java1907");
connectionFactory.setPassword("123");
Connection connection = connectionFactory.newConnection();
//2.基于这个连接对象,创建对应的通道
Channel channel = connection.createChannel();
//3.声明交换机
//两个参数:String exchange, String type,“fanout”是转发
channel.exchangeDeclare(EXCHANGE_NAME,"fanout");
//4.发送消息到交换机上
for (int i = 0; i < 10; i++) {
String message = "这是第"+i+"遍说我爱你";
channel.basicPublish(EXCHANGE_NAME,"",null,message.getBytes());
}
System.out.println("发送消息成功!");
}
}
消费者
- 消费者1
public class MyConsumer1 {
private static final String EXCHANGE_NAME = "fanout_exchange";
private static final String QUEUE_NAME = "fanout_exchange-queue-1";
public static void main(String[] args) throws IOException, TimeoutException {
//1.创建连接,连接上MQ服务器
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.142.137");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/java1907");
connectionFactory.setUsername("java1907");
connectionFactory.setPassword("123");
Connection connection = connectionFactory.newConnection();
//2.基于这个连接对象,创建对应的通道
Channel channel = connection.createChannel();
//限流,最多只放行一个消息 //叫号系统 1-10
channel.basicQos(1);
//申明队列和绑定交换机
channel.queueDeclare(QUEUE_NAME,false,false,false,null);
channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,"");
//3.创建一个消费者对象,并且写好处理消息的逻辑
Consumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String message = new String(body);
System.out.println("消费者1:接收到的消息是:"+message);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//手工确认模式,告知MQ服务器,消息已经被正确处理
//multiple表示是否批量确认
//为true,则批量确认,假设envelope.getDeliveryTag()=10,意味着将1-10的消息都确认
//为false,则只确认10
channel.basicAck(envelope.getDeliveryTag(),false);
}
};
//4.需要让消费者去监听队列
//autoACK=true:自动确认模式
//autoACK=false:手工确认模式 (推荐)
channel.basicConsume(QUEUE_NAME,false,consumer);
}
}
- 消费者2
public class MyConsumer2 {
private static final String EXCHANGE_NAME = "fanout_exchange";
private static final String QUEUE_NAME = "fanout_exchange-queue-2";
public static void main(String[] args) throws IOException, TimeoutException {
//1.创建连接,连接上MQ服务器
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.142.137");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/java1907");
connectionFactory.setUsername("java1907");
connectionFactory.setPassword("123");
Connection connection = connectionFactory.newConnection();
//2.基于这个连接对象,创建对应的通道
Channel channel = connection.createChannel();
//限流,最多只放行一个消息 //叫号系统 1-10
channel.basicQos(1);
//申明队列和绑定交换机
channel.queueDeclare(QUEUE_NAME,false,false,false,null);
channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,"");
//3.创建一个消费者对象,并且写好处理消息的逻辑
Consumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String message = new String(body);
System.out.println("消费者2:接收到的消息是:"+message);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//手工确认模式,告知MQ服务器,消息已经被正确处理
//multiple表示是否批量确认
//为true,则批量确认,假设envelope.getDeliveryTag()=10,意味着将1-10的消息都确认
//为false,则只确认10
channel.basicAck(envelope.getDeliveryTag(),false);
}
};
//4.需要让消费者去监听队列
//autoACK=true:自动确认模式
//autoACK=false:手工确认模式 (推荐)
channel.basicConsume(QUEUE_NAME,false,consumer);
}
}
消费者需要声明队列,并且将队列绑定到交换机上。
不同的消费者,声明的队列不同。
4、routing模式
交换机的类型为:direct
生产者代码
public class Producer {
private static final String EXCHANGE_NAME = "direct_exchange";
public static void main(String[] args) throws IOException, TimeoutException {
//1.创建连接,连接上MQ服务器
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.142.137");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/java1907");
connectionFactory.setUsername("java1907");
connectionFactory.setPassword("123");
Connection connection = connectionFactory.newConnection();
//2.基于这个连接对象,创建对应的通道
Channel channel = connection.createChannel();
//3.声明交换机
channel.exchangeDeclare(EXCHANGE_NAME,"direct");
//4.发送消息到交换机上
String message = "重大足球消息:国足今晚只要打平就能出线";
channel.basicPublish(EXCHANGE_NAME,"football",null,message.getBytes());
String message2 = "重要篮球消息:只要连续赢12场,我们就能出线";
channel.basicPublish(EXCHANGE_NAME,"basketball",null,message2.getBytes());
System.out.println("发送消息成功!");
}
}
交换机类型为direct!!!
消费者
消费者1:
public class MyConsumer1 {
private static final String EXCHANGE_NAME = "direct_exchange";
private static final String QUEUE_NAME = "direct_exchange-queue-1";
public static void main(String[] args) throws IOException, TimeoutException {
//1.创建连接,连接上MQ服务器
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.142.137");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/java1907");
connectionFactory.setUsername("java1907");
connectionFactory.setPassword("123");
Connection connection = connectionFactory.newConnection();
//2.基于这个连接对象,创建对应的通道
Channel channel = connection.createChannel();
//限流,最多只放行一个消息 //叫号系统 1-10
channel.basicQos(1);
//申明队列和绑定交换机
channel.queueDeclare(QUEUE_NAME,false,false,false,null);
channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,"football");
//3.创建一个消费者对象,并且写好处理消息的逻辑
Consumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String message = new String(body);
System.out.println("消费者1:接收到的消息是:"+message);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//手工确认模式,告知MQ服务器,消息已经被正确处理
//multiple表示是否批量确认
//为true,则批量确认,假设envelope.getDeliveryTag()=10,意味着将1-10的消息都确认
//为false,则只确认10
channel.basicAck(envelope.getDeliveryTag(),false);
}
};
//4.需要让消费者去监听队列
//autoACK=true:自动确认模式
//autoACK=false:手工确认模式 (推荐)
channel.basicConsume(QUEUE_NAME,false,consumer);
}
}
消费者2
public class MyConsumer2 {
private static final String EXCHANGE_NAME = "direct_exchange";
private static final String QUEUE_NAME = "direct_exchange-queue-2";
public static void main(String[] args) throws IOException, TimeoutException {
//1.创建连接,连接上MQ服务器
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.142.137");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/java1907");
connectionFactory.setUsername("java1907");
connectionFactory.setPassword("123");
Connection connection = connectionFactory.newConnection();
//2.基于这个连接对象,创建对应的通道
Channel channel = connection.createChannel();
//限流,最多只放行一个消息 //叫号系统 1-10
channel.basicQos(1);
//申明队列和绑定交换机
channel.queueDeclare(QUEUE_NAME,false,false,false,null);
channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,"basketball");
channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,"football");
//可以关注两个消息。打个标记。
//3.创建一个消费者对象,并且写好处理消息的逻辑
Consumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String message = new String(body);
System.out.println("消费者1:接收到的消息是:"+message);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//手工确认模式,告知MQ服务器,消息已经被正确处理
//multiple表示是否批量确认
//为true,则批量确认,假设envelope.getDeliveryTag()=10,意味着将1-10的消息都确认
//为false,则只确认10
channel.basicAck(envelope.getDeliveryTag(),false);
}
};
//4.需要让消费者去监听队列
//autoACK=true:自动确认模式
//autoACK=false:手工确认模式 (推荐)
channel.basicConsume(QUEUE_NAME,false,consumer);
}
}
5、通配符模式
交换机的类型为“topic”
生产者
public class Producer {
private static final String EXCHANGE_NAME = "topic_exchange";
public static void main(String[] args) throws IOException, TimeoutException {
//1.创建连接,连接上MQ服务器
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.142.137");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/java1907");
connectionFactory.setUsername("java1907");
connectionFactory.setPassword("123");
Connection connection = connectionFactory.newConnection();
//2.基于这个连接对象,创建对应的通道
Channel channel = connection.createChannel();
//3.声明交换机
channel.exchangeDeclare(EXCHANGE_NAME,"topic");
//4.发送消息到交换机上
String message = "重大足球消息:国足今晚只要打平就能出线";
channel.basicPublish(EXCHANGE_NAME,"tiyu.football",null,message.getBytes());
String message2 = "重要篮球消息:只要连续赢12场,我们就能出线";
channel.basicPublish(EXCHANGE_NAME,"tiyu.basketball",null,message2.getBytes());
String message3 = "CBA:9冠王能否卫冕,我们拭目以待!";
channel.basicPublish(EXCHANGE_NAME,"tiyu.basketball.cba",null,message3.getBytes());
System.out.println("发送消息成功!");
}
}
消费者1
public class MyConsumer1 {
private static final String EXCHANGE_NAME = "topic_exchange";
private static final String QUEUE_NAME = "topic_exchange-queue-1";
public static void main(String[] args) throws IOException, TimeoutException {
//1.创建连接,连接上MQ服务器
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.142.137");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/java1907");
connectionFactory.setUsername("java1907");
connectionFactory.setPassword("123");
Connection connection = connectionFactory.newConnection();
//2.基于这个连接对象,创建对应的通道
Channel channel = connection.createChannel();
//限流,最多只放行一个消息 //叫号系统 1-10
channel.basicQos(1);
//申明队列和绑定交换机
channel.queueDeclare(QUEUE_NAME,false,false,false,null);
channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,"tiyu.*");
//3.创建一个消费者对象,并且写好处理消息的逻辑
Consumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String message = new String(body);
System.out.println("消费者1:接收到的消息是:"+message);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//手工确认模式,告知MQ服务器,消息已经被正确处理
//multiple表示是否批量确认
//为true,则批量确认,假设envelope.getDeliveryTag()=10,意味着将1-10的消息都确认
//为false,则只确认10
channel.basicAck(envelope.getDeliveryTag(),false);
}
};
//4.需要让消费者去监听队列
//autoACK=true:自动确认模式
//autoACK=false:手工确认模式 (推荐)
channel.basicConsume(QUEUE_NAME,false,consumer);
}
}
用*去统配结果
消费者2
public class MyConsumer2 {
private static final String EXCHANGE_NAME = "topic_exchange";
private static final String QUEUE_NAME = "topic_exchange-queue-2";
public static void main(String[] args) throws IOException, TimeoutException {
//1.创建连接,连接上MQ服务器
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.142.137");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/java1907");
connectionFactory.setUsername("java1907");
connectionFactory.setPassword("123");
Connection connection = connectionFactory.newConnection();
//2.基于这个连接对象,创建对应的通道
Channel channel = connection.createChannel();
//限流,最多只放行一个消息 //叫号系统 1-10
channel.basicQos(1);
//申明队列和绑定交换机
channel.queueDeclare(QUEUE_NAME,false,false,false,null);
channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,"tiyu.#");
//3.创建一个消费者对象,并且写好处理消息的逻辑
Consumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String message = new String(body);
System.out.println("消费者2:接收到的消息是:"+message);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//手工确认模式,告知MQ服务器,消息已经被正确处理
//multiple表示是否批量确认
//为true,则批量确认,假设envelope.getDeliveryTag()=10,意味着将1-10的消息都确认
//为false,则只确认10
channel.basicAck(envelope.getDeliveryTag(),false);
}
};
//4.需要让消费者去监听队列
//autoACK=true:自动确认模式
//autoACK=false:手工确认模式 (推荐)
channel.basicConsume(QUEUE_NAME,false,consumer);
}
}
用#去匹配