RabbitMQ中4种交换机的Java连接代码

目录

1.直连交换机(Direct)

生产者代码示例

消费者代码示例

2.RabbitMQ连接工具类

3.Fanout交换机(扇出交换机,广播)

生产者

消费者

4.Topic交换机(主题交换机)

生产者

消费者

5.Header交换机(头部交换机)

生产者

消费者

6.附录说明

相关依赖


1.直连交换机(Direct)

直连交换机通过routingKey绑定交换机和队列,同时在发送消息时,也是通过routingKey找到相对应的队列,特点是一对一发送

生产者代码示例
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

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

public class DirectProducer {


    public static void main(String[] args) throws IOException, TimeoutException {


        ConnectionFactory connectionFactory = new ConnectionFactory();

        connectionFactory.setHost("xxx.xxx.xxx.xxx");// 这里写上你自己的ip

        connectionFactory.setUsername("admin");  // 这里写上你的MQ服务器对应的账号

        connectionFactory.setPassword("123456");// 这里写上你的MQ服务器对应的密码

        connectionFactory.setPort(5672);

        Connection connection = connectionFactory.newConnection();

        Channel channel = connection.createChannel();


        // 创建交换机,名称为"direct_exchange_test", 并交换机类型为direct(即下面第二个参数)
        channel.exchangeDeclare("direct_exchange_test", BuiltinExchangeType.DIRECT,true,false,null);


        // 创建队列,名称为“direct_queue_test”
        channel.queueDeclare("direct_queue_test",true,false,false,null);

        // 绑定队列,并设置routingKey的名称为 “direct_routing”
        channel.queueBind("direct_queue_test","direct_exchange_test","direct_routing");

        String message = "消息发送成功!";

        //开启监听
        channel.basicPublish("direct_exchange_test","direct_routing",null,message.getBytes());

        channel.close();

        connection.close();

    }


}
消费者代码示例
import com.rabbitmq.client.*;

import java.io.IOException;

public class DirectConsumer {

    public static void main(String[] args) throws Exception{

        ConnectionFactory connectionFactory = new ConnectionFactory();

        connectionFactory.setHost("xxx.xxx.xxx.xxx");

        connectionFactory.setUsername("admin");

        connectionFactory.setPassword("123456");

        connectionFactory.setPort(5672);

        Connection connection = connectionFactory.newConnection();

        Channel channel = connection.createChannel();


        //deliverCallback  消息接收后的回调

        DeliverCallback deliverCallback = (new DeliverCallback() {
            @Override
            public void handle(String s, Delivery delivery) throws IOException {

                System.out.println("接收到的消息:" + new String(delivery.getBody(),"UTF-8"));

            }
        });


        //cancelCallback  消费者取消时的回调
        CancelCallback cancelCallback = (new CancelCallback() {
            @Override
            public void handle(String s) throws IOException {

                System.out.println("消息被拒绝");
            }
        });

        channel.basicConsume("direct_queue_test",true,deliverCallback,cancelCallback);

        channel.close();

        connection.close();

    }

}

2.RabbitMQ连接工具类

可以看到,我们在上面编写direct类型的交换机代码时,无论是生产者还是消费者的一方,都需要先连接上RabbitMQ服务器,并再最后关闭信道和连接,对于每次都需要连接和关闭的重复性代码,我们可以将其封装,打包成工具类:

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

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

public class RabbitUtil {

     private final static String ip = "xxx.xxx.xxx.xxx";  // 你的RabbitMQ服务器ip

     private final static String username = "admin";  //  你的RabbitMQ服务器的用户名

     private final static String password = "123456"; // 你的RabbitMQ服务器的密码

     private final static String port = "5672"; // 你的RabbitMQ服务器的端口

    // 获取连接工厂
    public static Connection getConnectionFactory() throws IOException, TimeoutException {

        ConnectionFactory connectionFactory = new ConnectionFactory();

        connectionFactory.setHost(ip);

        connectionFactory.setPort(Integer.parseInt(port));

        connectionFactory.setUsername(username);

        connectionFactory.setPassword(password);

        Connection connection = connectionFactory.newConnection();


        return connection;
    }

    // 创建通道
    public static Channel getChannel(Connection connection){

        try {
            return connection.createChannel();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

     // 关闭信道和连接
    public static void close(Channel channel, Connection connection) {
        try {
            channel.close();
            connection.close();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
    }

}

3.Fanout交换机(扇出交换机,广播)

Fanout交换机如其名,特点是会广播,即只要发送消息到其中一个交换机中的一个队列,则同个交换机中的其它队列也会收到消息,因此就减少了routingKey设置的必要

生产者
import com.rabbitmq.client.*;
import org.Utils.RabbitUtil;

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

public class FanoutProducer {

    public static void main(String[] args) throws IOException, TimeoutException {


        Connection connection = RabbitUtil.getConnectionFactory();

        Channel channel = RabbitUtil.getChannel(connection);

        channel.exchangeDeclare("fanout_exchange_test", BuiltinExchangeType.FANOUT,true, false, null);


        // 创建队列
        channel.queueDeclare("fanout_queue_test",true,false,false,null);
        channel.queueDeclare("fanout_queue_test2",true,false,false,null);

        channel.queueBind("fanout_queue_test","fanout_exchange_test", "");
        channel.queueBind("fanout_queue_test2","fanout_exchange_test", "");

        String message = "这条消息来自Fanout交换机中的队列!";



        // 发送消息到交换机(广播到所有队列)
        channel.basicPublish("fanout_exchange_test","fanout_queue_test",null,message.getBytes("UTF-8"));
        // 上面我把消息指定发送到
        // fanout_queue_test队列,所以这条消息发送到了所有的队列!等价于
        
       //  channel.basicPublish("fanout_exchange_test","",null,message.getBytes("UTF-8"));
        

        RabbitUtil.close(channel,connection);

    }

}
消费者
import com.rabbitmq.client.*;
import org.Utils.RabbitUtil;

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

public class FanoutConsumer {

    public static void main(String[] args) throws IOException, TimeoutException {


        Connection connection = RabbitUtil.getConnectionFactory();

        Channel channel = RabbitUtil.getChannel(connection);

        DeliverCallback deliverCallback = (new DeliverCallback() {
            @Override
            public void handle(String s, Delivery delivery) throws IOException {

                System.out.println("接收到的消息是:" + new String(delivery.getBody(),"UTF-8"));
            }
        });

        CancelCallback cancelCallback = (new CancelCallback() {
            @Override
            public void handle(String s) throws IOException {

                System.out.println("消息被取消消费了!");
            }
        });


        // 测试是否两个队列都可以收到消息
        channel.basicConsume("fanout_queue_test",true,deliverCallback,cancelCallback);
        channel.basicConsume("fanout_queue_test2",true,deliverCallback,cancelCallback);

        channel.close();

        connection.close();

    }

}

4.Topic交换机(主题交换机)

Topic交换机与Direct交换机是相对的,direct通过routingKey做到了一对一消息发送,而topic交换机更像是通过routingKey的设置来做模糊查询

  1. Topic中,将routingkey通过"."来分为多个部分
  2. "*":代表一个部分(不能为空)
  3. "#":代表0个或多个部分(如果绑定的路由键为 "#" 时,则接受所有消息,因为路由键所有都匹配)

例如:

 

然后发送一条信息,routingkey为"key1.key2.key3.key4",那么根据"."将这个路由键分为了4个部分,此条路由键,将会匹配:

1.key1.key2,key3.*      成功匹配      2.key1.#     成功匹配

3.*.key2.*.key4       成功匹配           4.#.key3.key4  成功匹配

如果发送消息routingkey为"key1",那么将只能匹配中key1.#,#可以代表0个部分

生产者
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import org.Utils.RabbitUtil;

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

public class TopicProducer {

    public static void main(String[] args) throws IOException, TimeoutException {

        Connection connection = RabbitUtil.getConnectionFactory();

        Channel channel = RabbitUtil.getChannel(connection);

        // 创建交换机

        channel.exchangeDeclare("topic_exchange_test", BuiltinExchangeType.TOPIC,true, false, false, null);

        String routingKey = "*.com.zhan";

        String routingKey2 = "#.zhan";

        String routingkey3 = "zhan.com";

        // 创建队列

        channel.queueDeclare("topic_queue_test1",true,false,false,null);

        channel.queueDeclare("topic_queue_test2",true,false,false,null);

        channel.queueDeclare("topic_queue_test3",true,false,false,null);

        // 队列绑定到交换机上

        channel.queueBind("topic_queue_test1", "topic_exchange_test", routingKey);

        channel.queueBind("topic_queue_test2", "topic_exchange_test", routingKey2);

        channel.queueBind("topic_queue_test3", "topic_exchange_test", routingkey3);

        String message = "这条消息来自Fanout交换机";

        // 发送消息到交换机,routingKeyzhan
        channel.basicPublish("topic_exchange_test", "com.com.zhan", null, message.getBytes());
        // 预期结果:
        // topic_queue_test1 接收到消息
        // topic_queue_test2 接收到消息

        // topic_queue_test3 接收不能到消息

       RabbitUtil.close(channel,connection);

    }

}
消费者
import com.rabbitmq.client.*;
import org.Utils.RabbitUtil;

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

public class TopicConsumer {

    public static void main(String[] args) throws IOException, TimeoutException {

        Connection connection = RabbitUtil.getConnectionFactory();

        Channel channel = RabbitUtil.getChannel(connection);

        DeliverCallback deliverCallback = (new DeliverCallback() {
            @Override
            public void handle(String s, Delivery delivery) throws IOException {
                System.out.println("接收到的消息"+new String(delivery.getBody()));
            }
        });

        CancelCallback cancelCallback = (new CancelCallback() {
            @Override
            public void handle(String s) throws IOException {
                System.out.println("消息被拒绝");
            }
        });

        channel.basicConsume("topic_queue_test1",true,deliverCallback,cancelCallback);

        channel.basicConsume("topic_queue_test2",true,deliverCallback,cancelCallback);

        channel.basicConsume("topic_queue_test3",true,deliverCallback,cancelCallback);

        // 预期结果:
        // test1 和  test2 队列里都会消息

        // test3 不会收到

        RabbitUtil.close(channel,connection);

    }

}

5.Header交换机(头部交换机)

Header交换机与Direct交换机的区别在于,前者使用map来作为消息发送的标识,类似于HTTP协议中的消息头,而后者是通过routingKey,此外 基本没区别,但Header交换机性能差很多,如今基本用不上

消费方指定的headers中必须包含一个"x-match"的键。

键"x-match"的值有2个

x-match = all :表示所有的键值对都匹配才能接受到消息
x-match = any :表示只要有键值对匹配就能接受到消息

假设现在发送消息,携带的参数是{"name":"xiaomingXX"}想一想上述queue1和queue2哪个能收到消息?

答案是queue2 

虽然queue1和queue的map中要求的参数信息基本一致,但匹配规则不同,queue1是“x-match:all” ,即需要完全匹配,而后者是“x-match:any”,即只要一个满足就可发送到,从图中可以看到queue2里 " "sex":男" "可以匹配到的。

生产者
import com.rabbitmq.client.*;
import org.Utils.RabbitUtil;

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

public class HeaderProducer {

    public static void main(String[] args) throws IOException, TimeoutException {

        Connection connection = RabbitUtil.getConnectionFactory();

        Channel channel = RabbitUtil.getChannel(connection);

        channel.exchangeDeclare("header_exchange_test", BuiltinExchangeType.HEADERS,true, false, false, null);

        channel.queueDeclare("header_queue_test1",true,false,false,null);

        channel.queueDeclare("header_queue_test2",true,false,false,null);

        channel.queueDeclare("header_queue_test3",true,false,false,null);

        HashMap<String, Object> map = new HashMap<>();

        map.put("x-match","all");

        map.put("name","zhangsan");

        map.put("age","20");

        AMQP.BasicProperties.Builder properties = new AMQP.BasicProperties.Builder().headers(map);

        String message = "这条消息来自Header交换机";

        channel.basicPublish("header_exchange_test","header_queue_test1",properties.build(),message.getBytes());

        RabbitUtil.close(channel,connection);

    }

}
消费者
import com.rabbitmq.client.*;
import org.Utils.RabbitUtil;

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

public class HeaderConsumer {

    public static void main(String[] args) throws IOException, TimeoutException {

        Connection connection = RabbitUtil.getConnectionFactory();

        Channel channel = connection.createChannel();

        DeliverCallback deliverCallback = (consumerTag, delivery) -> {

            System.out.println("Header Consumer 收到消息:" + new String(delivery.getBody()));

        };

        CancelCallback cancelCallback = (consumerTag) -> {
            System.out.println("消息消费被中断");
        };


        channel.basicConsume("header_queue_test1", true, deliverCallback, cancelCallback);


        RabbitUtil.close(channel, connection);
    }


}

6.附录说明

相关依赖
    <dependency>
      <groupId>com.rabbitmq</groupId>
      <artifactId>amqp-client</artifactId>
      <version>5.12.0</version>
    </dependency>

  • 21
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: RabbitMQ是一个基于AMQP协议的消息间件,提供了丰富的Exchange(交换机)类型来进行消息的路由和分发。其,topic类型的交换机可以根据消息的routing key来进行灵活的匹配和分发。 在Spring Boot使用RabbitMQ的topic类型交换机,首先需要在配置文件配置RabbitMQ连接信息,如主机地址、端口号、用户名、密码等。 其次,需要创建一个RabbitMQ的配置类,使用@Configuration注解进行标识,并使用@EnableRabbit注解启用RabbitMQ相关的配置。在配置类,可以使用@Bean注解创建一个RabbitTemplate的实例,用于发送和接收消息。 接下来,在生产者,可以使用@Autowired注解注入RabbitTemplate实例,并调用其convertAndSend方法发送消息到指定的交换机和routing key。生产者可以根据具体的业务需求设置不同的routing key,用于消息的匹配和分发。 在消费者,同样可以使用@Autowired注解注入RabbitTemplate实例,并调用其receiveAndConvert方法接收消息。消费者需要在配置类使用@RabbitListener注解,指定要监听的队列,并根据需要设置不同的routing key或通配符进行匹配。 通过Spring Boot的自动配置,我们可以方便地使用RabbitMQ的topic类型交换机进行消息的发布和订阅。同时,使用Spring AMQP提供的注解和模板类,可以简化开发过程,提高代码的可读性和可维护性。 需要注意的是,使用topic类型交换机时,routing key是由一个或多个单词组成的字符串,用点号(.)进行分隔。其,单词可以包含字母、数字或通配符(#和*)。#用于匹配零个或多个单词,*用于匹配一个单词。 总之,通过使用RabbitMQ的topic类型交换机和Spring Boot提供的自动配置和注解,我们可以方便地实现消息的灵活路由和分发,满足不同业务场景的需求。 ### 回答2: RabbitMQ是一个开源的消息间件,用于实现可靠的消息传递。它使用AMQP(高级消息队列协议)作为消息传输协议,并通过交换机来路由消息。 Topic类型的交换机RabbitMQ是一灵活的交换机类型。它通过使用通配符的方式将消息路由到与匹配的路由键相关联的队列。使用Spring Boot框架与RabbitMQ集成,可以方便地实现Topic类型的交换机。 首先,在Spring Boot项目引入RabbitMQ的依赖,例如: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency> ``` 然后,配置RabbitMQ连接信息,例如: ```yaml spring: rabbitmq: host: localhost port: 5672 username: guest password: guest ``` 接下来,在代码创建一个Topic类型的交换机,例如: ```java @Configuration public class RabbitMQConfig { private static final String TOPIC_EXCHANGE_NAME = "topicExchange"; @Bean public TopicExchange topicExchange() { return new TopicExchange(TOPIC_EXCHANGE_NAME); } } ``` 然后,创建一个消费者来监听队列的消息,例如: ```java @Component public class MessageListener { private static final String QUEUE_NAME = "messageQueue"; private static final String ROUTING_KEY = "message.*"; @RabbitListener(queues = QUEUE_NAME) public void handleMessage(String message) { System.out.println("Received message: " + message); } } ``` 最后,通过发送消息的方式来测试Topic类型的交换机,例如: ```java @Service public class MessageService { private static final String ROUTING_KEY = "message.test"; @Autowired private RabbitTemplate rabbitTemplate; public void sendMessage(String message) { rabbitTemplate.convertAndSend(TOPIC_EXCHANGE_NAME, ROUTING_KEY, message); } } ``` 以上是使用Spring Boot与RabbitMQ实现Topic类型交换机的基本步骤。通过配置交换机、监听队列和发送消息,可以实现灵活的消息路由机制,满足不同的业务需求。 ### 回答3: RabbitMQ是一开源的消息代理,用于在分布式系统之间传递消息。它支持多类型的交换机,其之一就是Topic类型。 在使用Spring Boot集成RabbitMQ时,我们可以通过配置文件或代码的方式来定义Topic类型的交换机。 首先,在配置文件我们需要定义RabbitMQ连接信息,如主机名、端口号、用户名和密码等。同时,我们也需要配置交换机的相关信息,包括交换机名称、类型和持久化等。 例如,我们可以在application.properties文件添加以下配置: spring.rabbitmq.host=localhost spring.rabbitmq.port=5672 spring.rabbitmq.username=guest spring.rabbitmq.password=guest spring.rabbitmq.template.exchange=myExchange spring.rabbitmq.template.routing-key=myTopic 上述配置,我们定义了RabbitMQ连接信息和交换机的相关信息。其,exchange为我们自定义的交换机名称,routing-key为我们自定义的Topic名称。 接下来,在代码我们可以通过使用注解的方式,将RabbitTemplate对象注入到我们的业务逻辑。然后,通过调用RabbitTemplate对象的convertAndSend方法来发送消息。 例如,我们可以通过以下方式来发送消息: @Autowired private RabbitTemplate rabbitTemplate; public void sendMessage(String message) { rabbitTemplate.convertAndSend("myExchange", "myTopic", message); } 上述代码,我们通过调用rabbitTemplate对象的convertAndSend方法来发送消息。其,第一个参数为交换机名称,第二个参数为Topic名称,第三个参数为要发送的消息内容。 总结一下,通过配置文件和代码的方式,我们可以在Spring Boot使用RabbitMQ的Topic类型交换机。只需要定义好RabbitMQ连接信息和交换机的相关信息,然后调用RabbitTemplate对象的convertAndSend方法来发送消息即可。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蜗牛变涡流

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值