如何用JAVA使用RabbitMQ,以及四种交换机的介绍

                                          四种交换的介绍

Direct Exchange

处理路由键。需要将一个队列绑定到交换机上,要求该消息与一个特定的路由键完全匹配。这是一个完整的匹配。如果一个队列绑定到该交换机上要求路由键 “abc”,则只有被标记为“abc”的消息才被转发,不会转发abc.def,也不会转发dog.ghi,只会转发abc。

 

 

Fanout Exchange

不处理路由键。你只需要简单的将队列绑定到交换机上。一个发送到交换机的消息都会被转发到与该交换机绑定的所有队列上。很像子网广播,每台子网内的主机都获得了一份复制的消息。Fanout交换机转发消息是最快的。

 

Topic Exchange

将路由键和某模式进行匹配。此时队列需要绑定要一个模式上。符号“#”匹配一个或多个词,符号“”匹配不多不少一个词。因此“abc.#”能够匹配到“abc.def.ghi”,但是“abc.” 只会匹配到“abc.def”。

 

Headers Exchanges

不处理路由键。而是根据发送的消息内容中的headers属性进行匹配。在绑定Queue与Exchange时指定一组键值对;当消息发送到RabbitMQ时会取到该消息的headers与Exchange绑定时指定的键值对进行匹配;如果完全匹配则消息会路由到该队列,否则不会路由到该队列。headers属性是一个键值对,可以是Hashtable,键值对的值可以是任何类型。而fanout,direct,topic 的路由键都需要要字符串形式的。

匹配规则x-match有下列两种类型:

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

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

 

 

                               使用JAVA操作RabbitMQ

1:如果maven项目,在pom.xml文件里配置java操作RabbitMQ的jar包。

        <dependency>
            <groupId>com.rabbitmq</groupId>
            <artifactId>amqp-client</artifactId>
            <version>5.2.0</version>
        </dependency>

 

2:创建连接RabbitMQ的工具类

package com.example.rabbitmq.util;

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

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

public class ConnectionUtils {

    //1:用命令行创建rabbitMQ用户
    //rabbitmqctl add_user luoxu 123456
    //2:赋权 set_permissions [-p <vhostpath>] <user> <conf> <write> <read>
    //rabbitmqctl set_permissions -p / luoxu ".*" ".*" ".*"
    //3:配置角色 rabbitmqctl set_user_tags [user] [role]   关于有几种角色,分别能做什么自己百度
    //rabbitmqctl set_user_tags luoxu administrator

    /**
     * 获取MQ的连接
     * @return MQ连接资源
     */
    public static Connection getConnection() throws IOException,TimeoutException {
        //定义一个连接工厂
        ConnectionFactory factory = new ConnectionFactory();

        //设置服务器地址
        factory.setHost("127.0.0.1");
        // AMQP 端口
        factory.setPort(5672);
        //vhost
        factory.setVirtualHost("zhuji");
        //用户名
        factory.setUsername("luoxu");
        //密码
        factory.setPassword("123456");

        return factory.newConnection();
    }
}

3:建立提供者类

package com.example.rabbitmq.util;

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

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

public class producer {



    /**
     * 测试rabbitmq客户端,制造者端测试
     *
     * 生产者发送信息的过程:
     * 1.创建连接
     * 2.设置虚拟机
     * 3.创建会话通道
     * 4.声明队列
     * 5.声明交换机
     * 6.绑定交换机和队列,创建路由关键字
     * 7.发送消息
     * 8.关闭资源
     * 注明:4-6这三步不是必须的,但是如果直接发送消息而没有队列的话程序会出错,所以,在发送之前先声明,
     * 同理,消费者端也是这样,需要先声明,没有的话就会创建,有的话就不发生什么;
     *
     * 对于工作模式:
     * 1.work queues:不使用交换机,只有一个队列,可以有多个消费端,队列通知采用轮询的方法给监听的多个消费端
     * 发送消息;
     * 2.publish/subscribe:通过交换机进行消息转发,有多个队列,每个队列均可有一个或者多个消费者进行监听,
     * 每次生产者发送消息,则均由交换机转发至各个队列,由各个队列自行通知监听的消费者;
     * 3.Routing:模式同2,区别,为每个队列配备一个,或多个路由关键字,发送消息时指定路由关键字,由交换机根据路由
     * 关键字匹配进行转发;
     * 4.Topics:模式同3,区别在于,配备的路由关键字可以为通配符的形式,通配符有:#和*,区别:#匹配任意个单词,而*
     * 只能匹配单个单词,其中路由关键字指定规则:多个单词使用.隔开;
     * 5.Header:模式同3,区别,匹配的是键值对;
     * 6.RPC:远程异步调用,mq的一个应用,有客户端和服务端,客户端向mq发送一个调用服务端的信息,服务端获得信息,调用
     * 相应服务,将返回结果作为消息发送到另一个队列,客户端监听该队列获取返回信息;
     *
     * 对于消费者,每个消费者监听队列时指定的参数中,有队列名,是否自动回复,以及一个的map属性和一个回调方法;
     * 消费者,单独的消费者无法实现同时监听两个队列的操作;
     * 针对队列:可以给它增加路由key,也可以给一系列的键值对,作为头信息,这些东西都是对队列的标识,当生产者发送消息时,
     * 使用这些标识来决定将消息发送到那个队列,有路由key的话,优先匹配路由key;
     * 消费者的行为很单纯,就是监听一个队列,然后发现消息就回收;
     */

    public static void testSendMessage() throws IOException, TimeoutException {

        try {
             String QUEUE_INFORM_EMAIL = "queue_inform_email";
             String QUEUE_INFORM_SMS = "queue_inform_sms";
             String EXCHANGE_TOPICS_INFORM="exchange_topics_inform";
             String ROUTINGKEY_EMAIL="inform.#.email.#";
             String ROUTINGKEY_SMS="inform.#.sms.#";
            //获取一个链接
            Connection connection = ConnectionUtils.getConnection();

            //从连接中获取一个通道
            Channel channel = connection.createChannel();

            //声明队列,如果队列在mq 中没有则要创建
            //参数:String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments
            /**
             * 参数明细
             * 1、queue 队列名称
             * 2、durable 是否持久化,如果持久化,mq重启后队列还在
             * 3、exclusive 是否独占连接,队列只允许在该连接中访问,如果connection连接关闭队列则自动删除,如果将此参数设置true可用于临时队列的创建
             * 4、autoDelete 自动删除,队列不再使用时是否自动删除此队列,如果将此参数和exclusive参数设置为true就可以实现临时队列(队列不用了就自动删除)
             * 5、arguments 参数,可以设置一个队列的扩展参数,比如:可设置存活时间
             */
            channel.queueDeclare(QUEUE_INFORM_EMAIL,true,false,false,null);
            channel.queueDeclare(QUEUE_INFORM_SMS, true, false, false, null);


            //声明一个交换机
            //参数:String exchange, String type
            /**
             * 参数明细:
             * 1、交换机的名称
             * 2、交换机的类型
             * fanout:对应的rabbitmq的工作模式是 publish/subscribe
             * direct:对应的Routing    工作模式
             * topic:对应的Topics工作模式
             * headers: 对应的headers工作模式
             */
            channel.exchangeDeclare(EXCHANGE_TOPICS_INFORM, BuiltinExchangeType.TOPIC);


            // 绑定交换机和队列
            //参数:String queue, String exchange, String routingKey
            /**
             * 参数明细:
             * 1、queue 队列名称
             * 2、exchange 交换机名称
             * 3、routingKey 路由key,作用是交换机根据路由key的值将消息转发到指定的队列中,在发布订阅模式中调协为空字符串
             */
            channel.queueBind(QUEUE_INFORM_EMAIL,EXCHANGE_TOPICS_INFORM,ROUTINGKEY_EMAIL);
            channel.queueBind(QUEUE_INFORM_SMS,EXCHANGE_TOPICS_INFORM,ROUTINGKEY_SMS);


            for(int i=0;i<5;i++){
                //发送消息的时候指定routingKey
                String message = "send email inform message to user";
                channel.basicPublish(EXCHANGE_TOPICS_INFORM,"inform.email",null,message.getBytes());
                System.out.println("send to mq "+message);
            }
            for(int i=0;i<5;i++){
                //发送消息的时候指定routingKey
                String message = "send sms inform message to user";
                channel.basicPublish(EXCHANGE_TOPICS_INFORM,"inform.sms",null,message.getBytes());
                System.out.println("send to mq "+message);
            }
            for(int i=0;i<5;i++){
                //发送消息的时候指定routingKey
                String message = "send sms and email inform message to user";
                channel.basicPublish(EXCHANGE_TOPICS_INFORM,"inform.sms",null,message.getBytes());
                System.out.println("send to mq "+message);
            }


            /**
             *可以不关闭通道和连接、会一直保持心跳
             * */
            //关闭通道
            channel.close();
            //关闭连接
            connection.close();

        } catch (IOException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }

    }

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

 

4:创建消费者端类

package com.example.rabbitmq.util;

import com.rabbitmq.client.*;

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

public class Comsumer {
    private static final String QUEUE_NAME = "test_simple_queue";

    public static void main(String[] args) throws TimeoutException {
        try {
            String QUEUE_INFORM_EMAIL = "queue_inform_email";
            String QUEUE_INFORM_SMS = "queue_inform_sms";

            //获取连接
            Connection connection = ConnectionUtils.getConnection();

            //创建频道
            Channel channel = connection.createChannel();

            //定义队列的消费者
            //声明队列,如果队列在mq 中没有则要创建
            //参数:String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments
            /**
             * 参数明细
             * 1、queue 队列名称
             * 2、durable 是否持久化,如果持久化,mq重启后队列还在
             * 3、exclusive 是否独占连接,队列只允许在该连接中访问,如果connection连接关闭队列则自动删除,如果将此参数设置true可用于临时队列的创建
             * 4、autoDelete 自动删除,队列不再使用时是否自动删除此队列,如果将此参数和exclusive参数设置为true就可以实现临时队列(队列不用了就自动删除)
             * 5、arguments 参数,可以设置一个队列的扩展参数,比如:可设置存活时间
             */
            channel.queueDeclare(QUEUE_INFORM_EMAIL, true, false, false, null);
            channel.queueDeclare(QUEUE_INFORM_SMS, true, false, false, null);

            //实现消费方法
            DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {

                /**
                 * 当接收到消息后此方法将被调用
                 * @param consumerTag  消费者标签,用来标识消费者的,在监听队列时设置channel.basicConsume
                 * @param envelope 信封,通过envelope
                 * @param properties 消息属性
                 * @param 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("receive message:" + message);
                }
            };


            //监听队列
            //参数:String queue, boolean autoAck, Consumer callback
            /**
             * 参数明细:
             * 1、queue 队列名称
             * 2、autoAck 自动回复,当消费者接收到消息后要告诉mq消息已接收,如果将此参数设置为tru表示会自动回复mq,如果设置为false要通过编程实现回复
             * 3、callback,消费方法,当消费者接收到消息要执行的方法
             */
            channel.basicConsume(QUEUE_INFORM_EMAIL, true, defaultConsumer);
            channel.basicConsume(QUEUE_INFORM_SMS, true, defaultConsumer);




            /**
             *可以不关闭通道和连接、会一直保持心跳
             * */
            //关闭通道
            channel.close();
            //关闭连接
            connection.close();

        } catch (IOException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
    }


}

 

 

 

### 回答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
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值