RabbitMQ的六种消息发送模式(Java开发)

本文详细介绍RabbitMQ中五种队列的使用方法,包括简单队列、工作队列、发布订阅模式、路由模式及主题模式。涵盖依赖引入、队列创建、消息发送与接收的全过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

要使用RabbitMQ要在pom.xml中引入依赖,如下:

<!-- Rabbitmq -->
<dependency>
    <groupId>com.rabbitmq</groupId>
    <artifactId>amqp-client</artifactId>
    <version>5.6.0</version>
</dependency>

接下来介绍RabbitMQ的几种队列的使用:

1、简单队列,一个消息的生产者对应一个消费者

                                    

首先,创建获取连接Connection的工具类

public class ConnectionUtil {
    //连接工厂
    public static ConnectionFactory factory;
    //连接
    private static Connection connection;

    private ConnectionUtil(){ }

    public static Connection getInstance(){
        if(connection == null){
            factory = new ConnectionFactory();
            //IP
            factory.setHost("localhost");
            try {
                //通过连接工厂获取连接
                connection = factory.newConnection();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (TimeoutException e) {
                e.printStackTrace();
            }
        }
        return connection;
    }
}

第二步:创建生产者,并加入到Spring容器

@Component
public class Publisher {
    //队列名称
    private String queue = "hello_queue";

    public void sender(){
        Connection connection = null;
        Channel channel = null;
        try{
            connection = ConnectionUtil.getInstance();
            channel = connection.createChannel();
            //声明一个队列,只有在队列不存在的情况下去创建队列
            channel.queueDeclare(queue, false, false, false, null);
            String message = "Hello World!";
            //向队列发送消息
            channel.basicPublish("", queue, null, message.getBytes());
            System.out.println(" [Pbulisher] Sent '" + message + "'");
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

第三步:创建消费者,并加入到Spring容器

@Component
public class Receiver {

    private String queue = "hello_queue";
    public void receiver(){
        Connection connection = null;
        Channel channel = null;
        try{
            connection = ConnectionUtil.getInstance();
            channel = connection.createChannel();
            channel.queueDeclare(queue, false, false, false, null);
            Consumer consumer = new DefaultConsumer(channel){
                /**
                 * envelope主要存放生产者相关信息(比如交换机、路由key等)body是消息实体。
                 * @throws IOException
                 */
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    String message = new String(body, "UTF-8");
                    System.out.println("Customer Received '" + message + "'");
                }
            };
            //监听队列,自动回复队列应答 -- RabbitMQ中的消息确认机制
            final String s = channel.basicConsume(queue, true, consumer);
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

第四步:编写Controller测试,注意消费者启动后,会一直监听队列中的消息,不会关闭连接,所以/reciever请求只需要发送一次即可。(下边所有的测试与之相同)

@Controller
public class sendController {
    
    @Autowired
    private Publisher publisher;
    @Autowired
    private Receiver receiver;
    
    @RequestMapping("/sender")
    @ResponseBody
    public void send(){
        publisher.sender();
    }
    
    @RequestMapping("/reciever")
    @ResponseBody
    public void reciever(){
        receiver.receiver();
    }
}

2、Work queues(工作队列)一个生产者对应多个消费者(一个消息只能被一个消费者消费,两个消费者消费消息的数量为消息队列消息的总和)

                                

第一步:创建新的队列和生产者

@Component
public class WQ_Publisher {
    public String WQ_QUEUE = "workqueue";
    public void publicsher(){
        //获取连接
        Connection connection = ConnectionUtil.getInstance();
        try{
            Channel channel = connection.createChannel();
            //队列持久存在,即使RabbitMQ退出或崩溃
            boolean durable = true;
            //声明队列
            channel.queueDeclare(WQ_QUEUE,durable,false,false,null);
            for(int i=0;i<100;i++){
                String message = "Hello WorkQueue "+i;
                System.out.println("[WorkQueue 生产者:]" + message);
                //MessageProperties.PERSISTENT_TEXT_PLAIN  将消息持久化,保证消息不会丢失
                channel.basicPublish("",
                                        WQ_QUEUE,
                                        MessageProperties.PERSISTENT_TEXT_PLAIN,
                                         message.getBytes());
                //阻塞1秒模拟发送大消息
                Thread.sleep(1000);
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

第二步:创建两个生产者

@Component
public class WQ_Receiver {
    public String WQ_QUEUE = "workqueue";
    public void receiver(){
        Connection connection = ConnectionUtil.getInstance();
        try{
            Channel channel = connection.createChannel();
            channel.queueDeclare(WQ_QUEUE,false,false,false,null);
            //创建customer
            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,"utf-8");
                    System.out.println("消费者1:"+message);
                }
            };
            channel.basicConsume(WQ_QUEUE,true,consumer);
        }catch(Exception e){
            e.printStackTrace();
        }

    }
}
@Component
public class WQ_Receiver1 {
    public String WQ_QUEUE = "workqueue";

    public void receiver(){
        Connection connection = ConnectionUtil.getInstance();
        try{
            Channel channel = connection.createChannel();
            channel.queueDeclare(WQ_QUEUE,false,false,false,null);

            //创建customer
            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,"utf-8");
                    System.out.println("消费者2:"+message);
                    try {
                        Thread.sleep(1000);
                    }catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            };
            channel.basicConsume(WQ_QUEUE,true,consumer);
        }catch(Exception e){
            e.printStackTrace();
        }

    }
}

第三步:编写controller测试

@Controller
public class WQ_sendController {
    @Autowired
    private WQ_Publisher wq_publisher;
    @Autowired
    private WQ_Receiver wq_receiver;
    @Autowired
    private WQ_Receiver1 wq_receiver1;

    //发送消息
    @RequestMapping("/wqsender")
    @ResponseBody
    public void send(){
        wq_publisher.publicsher();
    }

    //消费者1
    @RequestMapping("/wqreceiver")
    @ResponseBody
    public void receiver(){
        wq_receiver.receiver();
    }
    //消费者2
    @RequestMapping("/wqreceiver1")
    @ResponseBody
    public void receiver1(){
        wq_receiver1.receiver();
    }
}

注意:此种消费者的分发方式为轮询分发,即RabbitMQ将按顺序将每条消息发送给下一个消费者。平均而言,每个消费者将获得相同数量的消息。

我们可以将RabbitMQ实现 公平分发,即消费快的消费者多消费几条消息,消费慢的消费者少消费几条消息。要实现公平分发,必须关闭消息自动应答,改为手动应答。则我们需要对上边的代码做一定的修改。

     在队列的生产者中使用basicQos(1)确保每次只发送一条消息,代码如下:

            /*
                公平分发,消息队列对消费者发送消息之前,如果没有收到该消费者的消息确认,
                则不会对该消费者发送消息。确保每次只发送一条消息
             */
            channel.basicQos(1);

     消费者中同样需要添加如下代码:

            /*
                公平分发,消息队列对消费者发送消息之前,如果没有收到该消费者的消息确认,
                则不会对该消费者发送消息。确保每次只发送一条消息
             */
            channel.basicQos(1);

     同时消费者中还需要关闭消息的自动应答,改为手动应答。

//关闭消息自动应答
            boolean autoAck = false;
            channel.basicConsume(WQ_QUEUE,autoAck,consumer);
//手动应答
                        channel.basicAck(envelope.getDeliveryTag(),false);

修改后的完整代码如下:

生产者代码:

/**
 * 消息的公平分发
 */
@Component
public class WQ_Publisher {
    public String WQ_QUEUE = "work_queue";
    public void publicsher(){
        //获取连接
        Connection connection = ConnectionUtil.getInstance();
        try{
            Channel channel = connection.createChannel();
            //队列持久存在,即使RabbitMQ退出或崩溃
            boolean durable = true;
            /*
                公平分发,消息队列对消费者发送消息之前,如果没有收到该消费者的消息确认,
                则不会对该消费者发送消息。确保每次只发送一条消息
             */
            channel.basicQos(1);
            //声明队列
            channel.queueDeclare(WQ_QUEUE,durable,false,false,null);
            for(int i=0;i<100;i++){
                String message = "Hello WorkQueue "+i;
                System.out.println("[WorkQueue 生产者:]" + message);
                //MessageProperties.PERSISTENT_TEXT_PLAIN  将消息持久化,保证消息不会丢失
                channel.basicPublish("",
                                        WQ_QUEUE,
                                        MessageProperties.PERSISTENT_TEXT_PLAIN,
                                         message.getBytes());
                //阻塞1秒模拟发送大消息
                Thread.sleep(5);
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

消费者代码:

@Component
public class WQ_Receiver {
    public String WQ_QUEUE = "work_queue";
    public void receiver(){
        Connection connection = ConnectionUtil.getInstance();
        try{
            Channel channel = connection.createChannel();
            //队列持久存在,即使RabbitMQ退出或崩溃
            boolean durable = true;
            //公平分发,消息队列对消费者发送消息之前,如果没有收到该消费者的消息确认,则不会对该消费者发送消息
            channel.basicQos(1);
            channel.queueDeclare(WQ_QUEUE,durable,false,false,null);
            //创建customer
            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,"utf-8");
                    System.out.println("消费者1:"+message);
                    try {
                        Thread.sleep(2000);
                    }catch (Exception e) {
                        e.printStackTrace();
                    }finally{
                        //手动应答
                        channel.basicAck(envelope.getDeliveryTag(),false);
                    }
                }
            };
            //关闭消息自动应答
            boolean autoAck = false;
            channel.basicConsume(WQ_QUEUE,autoAck,consumer);
        }catch(Exception e){
            e.printStackTrace();
        }

    }
}
@Component
public class WQ_Receiver1 {
    public String WQ_QUEUE = "work_queue";

    public void receiver(){
        Connection connection = ConnectionUtil.getInstance();
        try{
            Channel channel = connection.createChannel();
            //队列持久存在,即使RabbitMQ退出或崩溃
            boolean durable = true;
            //公平分发,消息队列对消费者发送消息之前,如果没有收到该消费者的消息确认,则不会对该消费者发送消息
            channel.basicQos(1);
            channel.queueDeclare(WQ_QUEUE,durable,false,false,null);
            //创建customer
            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,"utf-8");
                    System.out.println("消费者2:"+message);
                    try {
                        Thread.sleep(1000);
                    }catch (Exception e) {
                        e.printStackTrace();
                    }finally{
                        channel.basicAck(envelope.getDeliveryTag(),false);
                    }
                }
            };
            //关闭消息自动应答
            boolean autoAck = false;
            channel.basicConsume(WQ_QUEUE,autoAck,consumer);
        }catch(Exception e){
            e.printStackTrace();
        }

    }
}

Controller中的代码没有修改,为了例子的完整性,代码如下:

@Controller
public class WQ_sendController {
    @Autowired
    private WQ_Publisher wq_publisher;
    @Autowired
    private WQ_Receiver wq_receiver;
    @Autowired
    private WQ_Receiver1 wq_receiver1;

    //发送消息
    @RequestMapping("/wqsender")
    @ResponseBody
    public void send(){
        wq_publisher.publicsher();
    }

    //消费者1
    @RequestMapping("/wqreceiver")
    @ResponseBody
    public void receiver(){
        wq_receiver.receiver();
    }
    //消费者2
    @RequestMapping("/wqreceiver1")
    @ResponseBody
    public void receiver1(){
        wq_receiver1.receiver();
    }
}

3、Publish/Subscribe(订阅模式)

                                

订阅模式解读:

     1)、一个生产者,多个消费者

     2)、每一个消费者有自己的消息队列

     3)、生产者(P)没有把消息直接发送到消息队列,而是发送到了转发器(X)

     4)、每一个队列都需要绑定到转发器上

     5)、一条消息会被多个消费者消费

 

##讲订阅模式前先搞清楚什么是转发器?

Exchange(转发器),一方面是接受生产者发送的消息,另一方面是将接受到的消息推送到队列。

转发器有两种类型:

     fanout   :   不处理路由密钥

     direct    : 处理路由密钥

     topic     :    通配符匹配密钥

##本次讲解的订阅模式使用的是fanout类型的转发器,至于什么是路由密钥,将在下面讲的第四种模式时给大家讲解。

 

第一步,声明转发器(fanout类型),创建生产者发送消息

@Component
public class ExchangePublisher {
    private static final String EXCHANGE_FANOUT = "exchange_fanout";
    public void send(){
        Connection connection = ConnectionUtil.getInstance();
        try {
            Channel channel = connection.createChannel();
            //声明转发器
            channel.exchangeDeclare(EXCHANGE_FANOUT,"fanout");
            String message = "exchange word!";
            channel.basicPublish(EXCHANGE_FANOUT,"",null,message.getBytes());
            System.out.println("发送给转发器的消息:"+message);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

注意:转发器并没有存储功能,如果你只是声明了一个转发器,没有消费者队列绑定该转发器。消息会消失,并不会存在转发器中。

第二步:声明两个消费者,绑定上边声明的转发器。

@Component
public class ExchangeReceiver {
    private static final String QUQUE_NAME = "exchange_queue";
    private static final String EXCHANGE_NAME = "exchange_fanout";
    public void receiver(){
        Connection connection = ConnectionUtil.getInstance();
        try {
            Channel channel = connection.createChannel();
            channel.basicQos(1);
            //声明队列
            channel.queueDeclare(QUQUE_NAME,false,false,false,null);
            //绑定队列到转发器
            channel.queueBind(QUQUE_NAME,EXCHANGE_NAME,"");
            //创建customer
            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,"utf-8");
                    System.out.println("消费者1:"+message);
                    try {
                        Thread.sleep(2000);
                    }catch (Exception e) {
                        e.printStackTrace();
                    }finally{
                        //手动应答
                        channel.basicAck(envelope.getDeliveryTag(),false);
                    }
                }
            };
            //关闭消息自动应答
            boolean autoAck = false;
            channel.basicConsume(QUQUE_NAME,autoAck,consumer);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
@Component
public class ExchangeReceiver2 {
    private static final String QUQUE_NAME = "exchange_queue2";
    private static final String EXCHANGE_NAME = "exchange_fanout";
    public void receiver(){
        Connection connection = ConnectionUtil.getInstance();
        try {
            Channel channel = connection.createChannel();
            channel.basicQos(1);
            //声明队列
            channel.queueDeclare(QUQUE_NAME,false,false,false,null);
            //绑定队列到转发器
            channel.queueBind(QUQUE_NAME,EXCHANGE_NAME,"");
            //创建customer
            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,"utf-8");
                    System.out.println("消费者2:"+message);
                    try {
                        Thread.sleep(2000);
                    }catch (Exception e) {
                        e.printStackTrace();
                    }finally{
                        //手动应答
                        channel.basicAck(envelope.getDeliveryTag(),false);
                    }
                }
            };
            //关闭消息自动应答
            boolean autoAck = false;
            channel.basicConsume(QUQUE_NAME,autoAck,consumer);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

第三步:编写Controller发送请求测试

@Controller
public class Ex_sendController {

    @Autowired
    private ExchangePublisher exchangePublisher;
    @Autowired
    private ExchangeReceiver exchangeReceiver;
    @Autowired
    private ExchangeReceiver2 exchangeReceiver2;

    @RequestMapping("/exsender")
    @ResponseBody
    public void send(){
        exchangePublisher.send();
    }

    @RequestMapping("/exreceiver")
    @ResponseBody
    public void exreceiver(){
        exchangeReceiver.receiver();
    }

    @RequestMapping("/exreceiver2")
    @ResponseBody
    public void exreceiver2(){
        exchangeReceiver2.receiver();
    }
}

4、Routing(路由模式)

                                    

路由模式解读:

     1)、我们的消息发送者,发送消息的时候要指定routting key(路由密钥),为了方便大家理解,下文中描述routting key的时候,我都会用中文“路由密钥”。

String routingKey = "info";//路由密钥
channel.basicPublish(EXCHANGE_NAME,routingKey,null,message.getBytes());

     2)、消费者绑定队列到转发器的时候,需要提供一个参数binding key(绑定密钥),同样为了方便大家理解,下文中描述binding key的时候,我都会用中文“绑定密钥”。

String bindKey = "info";//绑定密钥
channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,bindKey);

一个队列是可以绑定多个不同绑定密钥的,不同的队列也可以绑定相同的绑定密钥(多重绑定),功能相当于Publish/Subscribe(订阅模式)。

    3)、如果你想一个消息能到达这个队列,需要绑定密钥和路由密钥正好能匹配得上。需要注意的是:如果你的转发器类型是"fanout",会忽略绑定密钥。导致即使你的绑定密钥和路由密钥正好匹配,但是消费者也无法接受到生产者发送的消息。所以,我们需要创建一个"direct"类型的转换器。

channel.exchangeDeclare(EXCHANGE_NAME,"direct");

完整代码如下:

第一步:创建生产者,指定路由密钥,发送消息

@Component
public class RoutingPublisher {

    private static final String EXCHANGE_NAME = "routing_exchange";
    public void send(){
        Connection connection = ConnectionUtil.getInstance();
        Channel channel = null;
        try{
            channel = connection.createChannel();
            //公平分发
            channel.basicQos(1);
            //声明转发器
            channel.exchangeDeclare(EXCHANGE_NAME,"direct");
            String message = "message for info!";
            String routingKey = "info";//路由的key
            channel.basicPublish(EXCHANGE_NAME,routingKey,null,message.getBytes());
            System.out.println("["+routingKey+"]发送的消息:"+message);
        }catch (Exception e){

        }
    }
}

第二步:创建两个消费者,一个绑定密钥"info",另一个绑定密钥"error"。

@Component
public class RoutingReceiver {

    private static final String EXCHANGE_NAME = "routing_exchange";
    private static final String QUEUE_NAME ="routing_queue";

    public void receiver(){
        Connection connection = ConnectionUtil.getInstance();
        Channel channel = null;
        try{
            channel = connection.createChannel();
            channel.basicQos(1);
            //声明队列
            channel.queueDeclare(QUEUE_NAME,false,false,false,null);
            //绑定队列到转发器
            String bindKey = "info";//绑定的key
            channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,bindKey);
            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,"utf-8");
                    System.out.println("绑定队列["+bindKey+"]接收的消息:"+message);
                }
            };
            channel.basicConsume(QUEUE_NAME,true,consumer);
        }catch (Exception e){
            e.printStackTrace();
        }

    }
}
@Component
public class RoutingReceiver2 {
    private static final String EXCHANGE_NAME = "routing_exchange";
    private static final String QUEUE_NAME ="routing_queue2";

    public void receiver(){
        Connection connection = ConnectionUtil.getInstance();
        Channel channel = null;
        try{
            channel = connection.createChannel();
            channel.basicQos(1);
            //声明队列
            channel.queueDeclare(QUEUE_NAME,false,false,false,null);
            //绑定队列到转发器
            String bindKey = "error";//绑定的key
            channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,bindKey);
            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,"utf-8");
                    System.out.println("绑定队列["+bindKey+"]接收的消息:"+message);
                }
            };
            channel.basicConsume(QUEUE_NAME,true,consumer);
        }catch (Exception e){
            e.printStackTrace();
        }

    }
}

第三步:创建controller,发送请求测试

@Controller
public class RoutingController {
    @Autowired
    private RoutingPublisher routingPublisher;
    @Autowired
    private RoutingReceiver routingReceiver;
    @Autowired
    private RoutingReceiver2 routingReceiver2;

    @RequestMapping("/rosender")
    @ResponseBody
    public void send(){
        routingPublisher.send();
    }

    @RequestMapping("/roreceiver")
    @ResponseBody
    public void receiver(){
        routingReceiver.receiver();
    }

    @RequestMapping("/roreceiver2")
    @ResponseBody
    public void receiver2(){
        routingReceiver2.receiver();
    }


}

发送请求会发现,只有绑定密钥为info的消费者可以收到消息。

5、Topic(主题模式)

                                         

主题模式解读:

       主题模式实际上与路由模式大致相同,它俩的区别是:

         1)、主题模式采用的转发器是topic类型的转发器。

channel.exchangeDeclare(EXCHANGE_NAME,"topic");

         2)、主题模式在队列绑定转发器的时候可以使用通配符 * 或 #来做为绑定密钥,达到能够匹配多个路由密钥的效果。

     比如:一个商城的消息有:goods.add、goods.change、goods.delete三种路由密匙。

     下面这种方法只能接受到goods.add路由密匙发送的消息:

 channel.queueDeclare(QUEUE_NAME,false,false,false,null);
 channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,"goods.add");

     而下面只能接受到goods.add、goods.change、goods.delete三个路由密匙发送的消息:

channel.queueDeclare(QUEUE_NAME,false,false,false,null);
channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,"goods.*");

     主题模式的通配符有两种:

     * :可以替代一个单词

     #:可以替代零个或多个单词

     完整代码如下:

第一步:定义生产者和topic模式的转发器

@Component
public class TopicPublisher {

    private static final String EXCHANGE_NAME = "topic_exchange";
    public void send(){
        Connection connection = ConnectionUtil.getInstance();
        Channel channel = null;
        try{
            channel = connection.createChannel();
            channel.basicQos(1);
            channel.exchangeDeclare(EXCHANGE_NAME,"topic");
            String message = "good add message!";
            channel.basicPublish(EXCHANGE_NAME,"goods.add",null,message.getBytes());
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

第二步:定义两个消费者,一个是绑定密钥为"goods.*",另一个绑定密钥为"goods.add"

@Component
public class TopicReceiver {
    private static final String QUEUE_NAME = "topic_queue";
    private static final String EXCHANGE_NAME = "topic_exchange";
    public void receiver(){
        Connection connection = ConnectionUtil.getInstance();
        Channel channel = null;
        try{
            channel = connection.createChannel();
            channel.basicQos(1);
            channel.queueDeclare(QUEUE_NAME,false,false,false,null);
            channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,"goods.*");
            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,"utf-8");
                    System.out.println("good.*:"+message);
                }
            };
            channel.basicConsume(QUEUE_NAME,true,consumer);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

     

@Component
public class TopicReceiver2 {
    private static final String QUEUE_NAME = "topic_queue2";
    private static final String EXCHANGE_NAME = "topic_exchange";
    public void receiver(){
        Connection connection = ConnectionUtil.getInstance();
        Channel channel = null;
        try{
            channel = connection.createChannel();
            channel.basicQos(1);
            channel.queueDeclare(QUEUE_NAME,false,false,false,null);
            channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,"goods.add");
            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,"utf-8");
                    System.out.println("good.add:"+message);
                }
            };
            channel.basicConsume(QUEUE_NAME,true,consumer);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

3、编写Controller测试

@Controller
public class TopicController {

    @Autowired
    private TopicPublisher topicPublisher;
    @Autowired
    private TopicReceiver topicReceiver;
    @Autowired
    private TopicReceiver2 topicReceiver2;

    @RequestMapping("/tosender")
    @ResponseBody
    public void send(){
        topicPublisher.send();
    }

    @RequestMapping("/toreceiver")
    @ResponseBody
    public void receiver(){
        topicReceiver.receiver();
    }

    @RequestMapping("/toreceiver2")
    @ResponseBody
    public void receiver2(){
        topicReceiver2.receiver();
    }


}

 

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值