RabbitMQ系列之三 RabbitMQ几种典型模式

版权声明:如需转载,请注明出处。 https://blog.csdn.net/caiqing116/article/details/84032099

本文详细介绍简单模式Simple、工作模式Work、发布订阅模式Publish/Subscribe、路由模式Routing、通配符模式Topics、远程调用模式RPC(暂不对该队列模式进行详解)

模式1:简单模式(Simple / HelloWorld 单生产单消费)
简单的发送与接收,没有特别的处理。
在这里插入图片描述
RabbitMQ连接(公共的连接方法,其他模式共用此方法)

package com.sc.queuemode.connection; 
import java.io.IOException;
import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
public class ConnectionUtil {
	public static Connection getConnection() throws IOException, TimeoutException {
		//定义连接池
		ConnectionFactory connectionFactory = new ConnectionFactory();
		//连接地址
		connectionFactory.setHost("localhost");
		//连接端口
		connectionFactory.setPort(5672);
		//用户名
		connectionFactory.setUsername("guest");
		//密码
		connectionFactory.setPassword("guest");
		//通过连接工厂获取连接
		Connection connection = connectionFactory.newConnection();
		//返回连接
		return connection;
	}
}

Producer:

package com.sc.queuemode.simple;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.sc.queuemode.connection.ConnectionUtil;

public class Producter {
	private final static String QUEUE_NAME = "hello";
	public static void main(String[] args) throws IOException, TimeoutException {
		//获取连接
		Connection connection = ConnectionUtil.getConnection();
		//从连接中声明通道
		Channel channel = connection.createChannel();
		//队列申明
		channel.queueDeclare(QUEUE_NAME, false, false, false, null);
		//消息内容
		String message = "simple queue hello world !";
		//推送发布消息
		//basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body)
		channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
		//信道关闭
		channel.close();
		//连接关闭
		connection.close();
	}
}

Consumer:

package com.sc.queuemode.simple;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.AMQP.BasicProperties;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
import com.sc.queuemode.connection.ConnectionUtil;

public class Consumer1 {
	
	private final static String QUEUE_NAME = "hello_queue";
	
	public static void main(String[] args) throws IOException, TimeoutException{
		//获取连接
		Connection connection = ConnectionUtil.getConnection();
		//声明信道
		Channel channel = connection.createChannel();
		//声明队列
		channel.queueDeclare(QUEUE_NAME, false, false, false, null);
		//声明消费者
		Consumer consumer = new DefaultConsumer(channel) {
			@Override
			public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body) 
					throws IOException {
				String message = new String(body,"UTF-8");
				System.out.println("customer 消费消息:"+message);
			}
		};
		channel.basicConsume(QUEUE_NAME, true,consumer);
	}
}

模式2:工作模式(Work单发送多接收)
一个生产者端,多个消费者端。示例中为了保证消息发送的可靠性,不丢失消息,使消息持久化了。同时为了防止接收端在处理消息时down掉,只有在消息处理完成后才发送消息确认。
在这里插入图片描述
Producer:

package com.sc.queuemode.work;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.sc.queuemode.connection.ConnectionUtil;

public class Producter {
	
	private final static String QUEUE_NAME = "work_queue";

	public static void main(String[] args) throws IOException, TimeoutException {
		//获取连接
		Connection connection = ConnectionUtil.getConnection();
		//声明信道
		Channel channel = connection.createChannel();
		//队列申明,durable:true消息持久化
		channel.queueDeclare(QUEUE_NAME, true, false, false, null);
		//消息内容
		String message = getMessage(args);
		for(int i = 0; i < 20; i++) {
			//发布消息
			//basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body)
			channel.basicPublish("", QUEUE_NAME, null, (i + " " +message).getBytes());
		}
		//关闭通道
		channel.close();
		//连接关闭
		connection.close();
	}
	
	private static String getMessage(String[] strings) {
		if(strings.length < 1) {
			return "Hello World!";
		}
		return joinStrings(strings, "");
	}
	
	private static String joinStrings(String[] strings, String delimiter) {
		int length = strings.length;
		if(length == 0) return "";
		StringBuilder words = new StringBuilder(strings[0]);
		for(int i = 0; i < length; i++) {
			words.append(delimiter).append(strings[i]);
		}
		return words.toString();
	}
}

Consumer:
消费者1

package com.sc.queuemode.work;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.AMQP.BasicProperties;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
import com.sc.queuemode.connection.ConnectionUtil;
/*
* 消费者1
*/
public class Consumer1 {
	
	private final static String QUEUE_NAME = "work_queue";
	public static void main(String[] args) throws IOException, TimeoutException{
		Connection connection = ConnectionUtil.getConnection();
		Channel channel = connection.createChannel();
		channel.queueDeclare(QUEUE_NAME, true, false, false, null);
		
		//同一时刻服务器只发送1条消息给消费者(能者多劳,消费消息快的,会消费更多的消息)
		//保证在接收端一个消息没有处理完时不会接收另一个消息,即消费者端发送了ack后才会接收下一个消息。
		//在这种情况下生产者端会尝试把消息发送给下一个空闲的消费者。
		channel.basicQos(1);
		
		//声明队列的消费者O
		Consumer consumer1 = new DefaultConsumer(channel){
			@Override
			public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body)
					throws IOException {
				//channel.basicConsume(QUEUE_NAME, false, consumer1);
				String message = new String(body, "UTF-8");
				System.out.println("customer1 消费消息:"+message);
				//手动返回结果
				channel.basicAck(envelope.getDeliveryTag(), false);
				try {
					Thread.sleep(50);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		};
		//定义的消费者监听队列 autoAck:true自动返回结果,false手动返回
		channel.basicConsume(QUEUE_NAME, false,consumer1);
	}
}

消费者2

package com.sc.queuemode.work;
    import java.io.IOException;
    import java.util.concurrent.TimeoutException;    
    import com.rabbitmq.client.AMQP.BasicProperties;
    import com.rabbitmq.client.Channel;
    import com.rabbitmq.client.Connection;
    import com.rabbitmq.client.Consumer;
    import com.rabbitmq.client.DefaultConsumer;
    import com.rabbitmq.client.Envelope;
    import com.sc.queuemode.connection.ConnectionUtil;
    /*
    * 消费者2
    */
    public class Consumer2 {
    	private final static String QUEUE_NAME = "work_queue";
    
   	public static void main(String[] args) throws IOException, TimeoutException{
   		Connection connection = ConnectionUtil.getConnection();
   		Channel channel = connection.createChannel();
   		channel.queueDeclare(QUEUE_NAME, true, false, false, null);
   		
   		//同一时刻服务器只发送1条消息给消费者(能者多劳,消费消息快的,会消费更多的消息)
   		channel.basicQos(1);
   		
   		//声明队列的消费者
   		Consumer consumer2 = new DefaultConsumer(channel){
   			@Override
   			public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body)
   					throws IOException {
   				//channel.basicConsume(QUEUE_NAME, false, consumer1);
   				String message = new String(body, "UTF-8");
   				System.out.println("customer2 消费消息:"+message);
   				channel.basicAck(envelope.getDeliveryTag(), false);
   				try {
   					Thread.sleep(100);
   				} catch (InterruptedException e) {
   					e.printStackTrace();
   				}
   			}
   		};
   		//定义的消费者监听队列(第二个参数:true自动返回结果,false手动返回)
   		channel.basicConsume(QUEUE_NAME, false,consumer2);
	}
}

模式3:发布、订阅模式(Publish/Subscribe)
使用场景:发布、订阅模式,生产者端发送消息,多个消费者同时接收所有的消息。
在这里插入图片描述
Producer

package com.sc.queuemode.publish_subscrible;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.sc.queuemode.connection.ConnectionUtil;

public class Producter {

	private final static String EXCHANGE_NAME = "publishSubscrible_exchange";
	
	public static void main(String[] args) throws IOException, TimeoutException {
		Connection connection = ConnectionUtil.getConnection();
		Channel channel = connection.createChannel();
		//声明交换机Exchange类型为fanout
		channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
		
		String message = "publish/subscrible hello world";
		channel.basicPublish(EXCHANGE_NAME, "", null, message.getBytes());
		System.out.println("发布订阅 生产者 发布消息:"+message);
		channel.close();
		connection.close();
	}
}

生产者端发布消息到交换机,使用“fanout”方式发送,即广播消息,不需要使用queue,发送端不需要关心谁接收。
消费者1:

package com.sc.queuemode.publish_subscrible;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.AMQP.BasicProperties;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.ConsumerCancelledException;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
import com.rabbitmq.client.ShutdownSignalException;
import com.sc.queuemode.connection.ConnectionUtil;

public class Customer1 {
	
	//队列1
	private final static String QUEUE_NAME = "publishSubscrible_queue";
	private final static String EXCHANGE_NAME = "publishSubscrible_exchange";

	public static void main(String[] args) throws IOException, TimeoutException{
		Connection connection = ConnectionUtil.getConnection();
		Channel channel = connection.createChannel();
		//声明交换机
		channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
		//声明队列
		channel.queueDeclare(QUEUE_NAME, true, false, false, null);
		//绑定队列到交换机
		channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "");
		
		//同一时刻服务器只发送1条消息给消费者(能者多劳,消费消息快的,会消费更多的消息)
		//保证在接收端一个消息没有处理完时不会接收另一个消息,即消费者端发送了ack后才会接收下一个消息。
		//在这种情况下生产者端会尝试把消息发送给下一个空闲的消费者。
		channel.basicQos(1);
		
		//申明消费者
		Consumer consumer1 = new DefaultConsumer(channel) {
			@Override
			public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body)
					throws IOException {
				String message = new String(body, "UTF-8");
				System.out.println("发布订阅 消费者1 消费消息:"+message);
				//手动返回结果
				channel.basicAck(envelope.getDeliveryTag(), false);
			}
		};
		channel.basicConsume(QUEUE_NAME, false, consumer1);
	}
}

消费者2:

package com.sc.queuemode.publish_subscrible;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.AMQP.BasicProperties;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
import com.sc.queuemode.connection.ConnectionUtil;

public class Customer2 {

	//队列2
	private final static String QUEUE_NAME = "publishSubscrible_queue2";
	private final static String EXCHANGE_NAME = "publishSubscrible_exchange";

	public static void main(String[] args) throws IOException, TimeoutException{
		Connection connection = ConnectionUtil.getConnection();
		Channel channel = connection.createChannel();
		//声明交换机
		channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
		//声明队列
		channel.queueDeclare(QUEUE_NAME, true, false, false, null);
		//绑定队列到交换机
		channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "");
		
		//同一时刻服务器只发送1条消息给消费者(能者多劳,消费消息快的,会消费更多的消息)
		//保证在接收端一个消息没有处理完时不会接收另一个消息,即消费者端发送了ack后才会接收下一个消息。
		//在这种情况下生产者端会尝试把消息发送给下一个空闲的消费者。
		channel.basicQos(1);
		
		//申明消费者
		Consumer consumer2 = new DefaultConsumer(channel) {
			@Override
			public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body)
					throws IOException {
				String message = new String(body, "UTF-8");
				System.out.println("发布订阅 消费者2 消费消息:"+message);
				//手动返回结果
				channel.basicAck(envelope.getDeliveryTag(), false);
			}
		};
		channel.basicConsume(QUEUE_NAME, false, consumer2);
	}

}

消费者端:
1、声明和生产者端一样的交换机。
2、注意binding queue的时候,channel.queueBind()的第三个参数Routing key为空,即所有的消息都接收。如果这个值不为空,在exchange type为“fanout”方式下该值被忽略!
3、消息队列和交换机绑定如下图所示
在这里插入图片描述

模式4:路由模式(Routing)
生产者按routing key发送消息,不同的消费者端按不同的routing key接收消息。
在这里插入图片描述
Producer:

package com.sc.queuemode.routing;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.sc.queuemode.connection.ConnectionUtil;

public class Producter {
	
	private final static String EXCHANGE_NAME = "routing_exchange";

	public static void main(String[] args) throws IOException, TimeoutException {
		Connection connection = ConnectionUtil.getConnection();
		Channel channel = connection.createChannel();
		//声明交换机Exchange类型为direct
		channel.exchangeDeclare(EXCHANGE_NAME, "direct");
		
		//发布消息3种routingKey的消息
		String message = "hello info";
		channel.basicPublish(EXCHANGE_NAME, "info", null, message.getBytes());
		System.out.println("路由模式发布info消息:"+message);
		
		message = "hello warning";
		channel.basicPublish(EXCHANGE_NAME, "warning", null, message.getBytes());
		System.out.println("路由模式发布warning消息:"+message);
		
		message = "hello error";
		channel.basicPublish(EXCHANGE_NAME, "error", null, message.getBytes());
		System.out.println("路由模式发布error消息:"+message);
	}
}

消费者端和模式3(发布订阅模式)的区别:
1、exchange的type为direct
2、发送消息的时候加入了routing key
Consumer:
消费者1

package com.sc.queuemode.routing;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.AMQP.BasicProperties;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
import com.sc.queuemode.connection.ConnectionUtil;

public class Customer1 {

	private final static String QUEUE_NAME = "routing_queue1";
	private final static String EXCHANGE_NAME = "routing_exchange";
	
	public static void main(String[] args) throws IOException, TimeoutException{
		Connection connection = ConnectionUtil.getConnection();
		Channel channel = connection.createChannel();
		//声明交换机
		channel.exchangeDeclare(EXCHANGE_NAME, "direct");
		//申明队列
		channel.queueDeclare(QUEUE_NAME, true, false, false, null);
		
		//队列绑定交换机,指定路由routingKey
		//结束路由routingKey为info和warning的消息
		channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "info");
		channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "warning");
		
		//同一时刻服务器只发送1条消息给消费者(能者多劳,消费消息快的,会消费更多的消息)
		//保证在接收端一个消息没有处理完时不会接收另一个消息,即消费者端发送了ack后才会接收下一个消息。
		//在这种情况下生产者端会尝试把消息发送给下一个空闲的消费者。
		channel.basicQos(1);
		
		//声明消费者
		Consumer consumer = new DefaultConsumer(channel) {
			@Override
			public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body)
					throws IOException {
				String message = new String(body, "UTF-8");
				System.out.println("路由模式 消费者1 消费消息:"+message);
				channel.basicAck(envelope.getDeliveryTag(), false);
			}
		};
		channel.basicConsume(QUEUE_NAME, false, consumer);
	}
}

消费者2

package com.sc.queuemode.routing;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.AMQP.BasicProperties;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
import com.sc.queuemode.connection.ConnectionUtil;

public class Customer2 {
	
	private final static String QUEUE_NAME = "routing_queue2";
	private final static String EXCHANGE_NAME = "routing_exchange";
	
	public static void main(String[] args) throws IOException, TimeoutException{
		Connection connection = ConnectionUtil.getConnection();
		Channel channel = connection.createChannel();
		//声明交换机
		channel.exchangeDeclare(EXCHANGE_NAME, "direct");
		//申明队列
		channel.queueDeclare(QUEUE_NAME, true, false, false, null);
		
		//队列绑定交换机,指定路由routingKey
		//结束路由routingKey为error的消息
		channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "error");
		
		//同一时刻服务器只发送1条消息给消费者(能者多劳,消费消息快的,会消费更多的消息)
		//保证在接收端一个消息没有处理完时不会接收另一个消息,即消费者端发送了ack后才会接收下一个消息。
		//在这种情况下生产者端会尝试把消息发送给下一个空闲的消费者。
		channel.basicQos(1);
		
		//声明消费者
		Consumer consumer2 = new DefaultConsumer(channel) {
			@Override
			public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body)
					throws IOException {
				String message = new String(body, "UTF-8");
				System.out.println("路由模式 消费者2 消费消息:"+message);
				channel.basicAck(envelope.getDeliveryTag(), false);
			}
		};
		channel.basicConsume(QUEUE_NAME, false, consumer2);
	}
}

消费者端和模式3(发布订阅模式)的区别:
在绑定queue和exchange的时候使用了路由routing key,即从该exchange上只接收routing key指定的消息。
队列绑定如下图所示
在这里插入图片描述
模式5:通配符模式(Topics ,按topic发送接收)
生产者端不只按固定的routing key发送消息,而是按字符串“匹配”发送,消费者端同样如此。
与之前的路由模式相比,它将信息的传输类型的key更加细化,以“key1.key2.keyN…”的模式来指定信息传输的key的大类型和大类型下面的小类型,让消费者端可以更加精细的确认自己想要获取的信息类型。而在消费者端,不用精确的指定具体到哪一个大类型下的小类型的key,而是可以使用类似正则表达式(但与正则表达式规则完全不同)的通配符在指定一定范围或符合某一个字符串匹配规则的key,来获取想要的信息。“通配符交换机”(Topic Exchange)将路由键和某模式进行匹配。此时队列需要绑定在一个模式上。符号“#”匹配一个或多个词,符号“*”仅匹配一个词。
在这里插入图片描述
Producer:

package com.sc.queuemode.topics;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.sc.queuemode.connection.ConnectionUtil;

public class Producter {
	
	private static final String EXCHANGE_NAME = "topic_exchange";
	
	public static void main(String[] args) throws IOException, TimeoutException {
		Connection connection = ConnectionUtil.getConnection();
		Channel channel =connection.createChannel();
		//声明交换机类型为topic
		channel.exchangeDeclare(EXCHANGE_NAME, "topic");
		
		String message = "发布了一条中国新闻消息";
		channel.basicPublish(EXCHANGE_NAME, "china.news", null, message.getBytes());
		
		message = "发布了一条中国天气消息";
		channel.basicPublish(EXCHANGE_NAME, "china.weather", null, message.getBytes());
		
		message = "发布了一条美国新闻消息";
		channel.basicPublish(EXCHANGE_NAME, "usa.news", null, message.getBytes());
		
		message = "发布了一条美国天气消息";
		channel.basicPublish(EXCHANGE_NAME, "usa.weather", null, message.getBytes());
	}
}

生产者和模式4(路由模式)的区别:
1、交换机exchange的type为topic
2、发送消息的routing key不是固定的单词,而是匹配字符串,如"china.#",*匹配一个单词,#匹配0个或多个单词。因此如“china.#”能够匹配到“china.news.info”,但是“china.* ”只会匹配到“china.news”

Consumer:
消费者1

package com.sc.queuemode.topics;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.AMQP.BasicProperties;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
import com.sc.queuemode.connection.ConnectionUtil;

public class Customer1 {

	private static final String QUEUE_NAME = "topics_queue1";
	private static final String EXCHANGE_NAME = "topic_exchange";
	
	public static void main(String[] args) throws IOException, TimeoutException{
		Connection connection = ConnectionUtil.getConnection();
		Channel channel = connection.createChannel();
		//交换机申明
		channel.exchangeDeclare(EXCHANGE_NAME, "topic");
		//队列声明
		channel.queueDeclare(QUEUE_NAME, true, false, false, null);
		//队列绑定交换机并制定路由routingKey
		channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "china.#");
		//同一时刻服务器只发送1条消息给消费者(能者多劳,消费消息快的,会消费更多的消息)
		//保证在接收端一个消息没有处理完时不会接收另一个消息,即消费者端发送了ack后才会接收下一个消息。
		//在这种情况下生产者端会尝试把消息发送给下一个空闲的消费者。
		channel.basicQos(1);
		//申明消费者
		Consumer consumer1 = new DefaultConsumer(channel) {
			@Override
			public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body)
					throws IOException {
				String message = new String(body, "UTF-8");
				System.out.println("通配符模式 消费者1消费:"+message);
				channel.basicAck(envelope.getDeliveryTag(), false);
			}
		};
		channel.basicConsume(QUEUE_NAME, false, consumer1);
	}
}

消费者2

package com.sc.queuemode.topics;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.AMQP.BasicProperties;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
import com.sc.queuemode.connection.ConnectionUtil;

public class Customer2 {
	
	private static final String QUEUE_NAME = "topics_queue2";
	private static final String EXCHANGE_NAME = "topic_exchange";
	
	public static void main(String[] args) throws IOException, TimeoutException{
		Connection connection = ConnectionUtil.getConnection();
		Channel channel = connection.createChannel();
		//交换机申明
		channel.exchangeDeclare(EXCHANGE_NAME, "topic");
		//队列声明
		channel.queueDeclare(QUEUE_NAME, true, false, false, null);
		//队列绑定交换机并制定路由routingKey
		channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "usa.#");
		//同一时刻服务器只发送1条消息给消费者(能者多劳,消费消息快的,会消费更多的消息)
		//保证在接收端一个消息没有处理完时不会接收另一个消息,即消费者端发送了ack后才会接收下一个消息。
		//在这种情况下生产者端会尝试把消息发送给下一个空闲的消费者。
		channel.basicQos(1);
		//申明消费者
		Consumer consumer2 = new DefaultConsumer(channel) {
			@Override
			public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body)
					throws IOException {
				String message = new String(body, "UTF-8");
				System.out.println("通配符模式 消费者2消费:"+message);
				channel.basicAck(envelope.getDeliveryTag(), false);
			}
		};
		channel.basicConsume(QUEUE_NAME, false, consumer2);
	}
}

交换机和队列绑定如下图所示
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/caiqing116/article/details/84032099
今日推荐