RabbitMQ入门demo

RabbitMQ入门demo

1 原生代码

创建新模块
在这里插入图片描述

  1. 引入依赖:spring-boot-starter-amqp
  2. 生产者代码
public class ProducerTest {
    // 交换机名字
    private String exchangeName = "exchange_lxy";
    // 路由键
    private String routingKey = "rout_lxy";
    // 队列名字
    private String queueName = "queue_lxy";
    // host
    private String host = "你的外网Ip";
    // rabbitMQ端口号
    private Integer port = 5672;
    // 虚拟机
    private String vHost = "my_vhost";
    @Test
    public void sendMsg() throws IOException, TimeoutException {
        // 1.准备一个连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        // 设置对应的连接参数
        factory.setHost(host);
        factory.setPort(port);
        factory.setUsername("root");
        factory.setPassword("1111");
        factory.setVirtualHost(vHost);
        // 2.获取连接对象
        Connection connection = factory.newConnection();
        // 3.获取channel
        Channel channel = connection.createChannel();
        // 4.声明一个交换机,type="direct",持久化,非自动删除的交换器
        channel.exchangeDeclare(exchangeName, "direct", true, false, null);
        // 5.声明一个持久化,非排他,非自动删除的队列
        channel.queueDeclare(queueName,true,false,false,null);
        // 6.将交换器和队列通过路由键绑定
        channel.queueBind(queueName,exchangeName,routingKey);
        // 7.发送持久化消息:hello rabbitmq
        String message = "hello rabbitmq";
        channel.basicPublish(exchangeName,routingKey, MessageProperties.PERSISTENT_TEXT_PLAIN,message.getBytes());
        // 8.关闭资源
        channel.close();
        connection.close();
    }
}

交换器根据不同路由键绑定不同队列,查看web管理器
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  1. 消费者代码
public class ConsumerTest {
    // 队列名字
    private String queueName = "queue_lxy";
    // host
    private String ipAddress = "外网IP";
    // rabbitMQ 端口号
    private Integer port = 5672;
    /**
     * 生产者测试
     */
    @Test
    public void consumer() throws Exception {
        // 1. 创建 Address 对象数组
        Address[] addresses = new Address[] {
                new Address(ipAddress,port)
        };
        // 2. 获取连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setUsername("root");
        factory.setPassword("1111");
        // 设置 vhost
        factory.setVirtualHost("my_vhost");
        // 3. 建立连接
        Connection connection = factory.newConnection(addresses);
        // 4. 创建频道
        Channel channel = connection.createChannel();
        // 设置客户端最多接收未被 ack 的消息的个数
        channel.basicQos(64);
        // 创建消费者对象
        Consumer consumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(
                    String consumerTag,
                    Envelope envelope,
                    AMQP.BasicProperties properties,
                    byte[] body) throws IOException {
                // 获取消息
                System.out.println("接收到:"+new String(body));
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        // 消费
        channel.basicConsume(queueName,consumer);
        //等待回调函数执行完毕之后 , 关闭资源
        TimeUnit.SECONDS.sleep(5);
        channel.close();
        connection.close();
    }
}

结果:
在这里插入图片描述

2 重点掌握Springboot写法

了解原生代码,重点掌握Springboot写法,不交给eureka管理

  1. 依赖:spring-boot-starter-amqp
  2. 配置
spring:
  application:
    name: ribbitmq-producer
  rabbitmq:
    host: 你的外网ip
    virtual-host: my_vhost
    username: root
    password: 1111
    port: 5672
    connection-timeout: 6000
server:
  port: 9527
  1. 配置类RabbitConfig.java
@Configuration
public class RabbitConfig {
    // 操作rabbitmq的对象
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory){
        return new RabbitTemplate(connectionFactory);
    }
}
  1. 生产者,新建模块(上面原生代码测试用)rabbitmq-producer
@RestController
public class RabbitController {
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @GetMapping("/rabbit/send/{name}")
    public String sendMsg(@PathVariable String name) {
        rabbitTemplate.convertAndSend("exchange_lxy","rout_lxy",name);
        return "success";
    }
}
  1. 消费者,新建模块rabbitmq-consumer
    配置文件:
spring:
  application:
    name: rabbit-consumer
  rabbitmq:
    host: 你的外网ip
    virtual-host: my_vhost
    username: root
    password: 1111
    port: 5672
    connection-timeout: 6000
    listener:
      simple:
        # 最小并发处理数
        concurrency: 5
        max-concurrency: 10
        # 消费消息的模式
        acknowledge-mode: auto
        # 限流
        prefetch: 1
  server:
    port: 9527

配置类:

@Configuration
public class RabbitConfig {
    // 操作rabbitmq模板对象
    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory){
        return new RabbitTemplate(connectionFactory);
    }
}

消费的方法:一旦队列有消息,自动获取消息出来,马上消费

@Component
public class RabbitMqListener {
    @RabbitListener(queues = "queue_lxy")
    @RabbitHandler
    public void listen(String msg) {
        System.out.println("接收到:" + msg);
    }
    
    @RabbitListener(queues = "queue_lxy2")
    @RabbitHandler
    public void listen2(String msg) {
        System.out.println("接收到:" + msg);
    }
}

3 Springboot rabbitMQ传递对象

依赖中加入pojo
生产者:RabbitController.java

@GetMapping("/rabbit/obj/{name}")
    public String sendObj(@PathVariable String name) {
        User user = new User();
        user.setId(111);
        user.setUserName(name);
        user.setUserAge(1000);
        // 发送
        rabbitTemplate.convertAndSend("java502_obj_exchange","object",user);
        return "success";
    }

消费者:手动ACK(手动确认消息确认),实际开发必用

/**
     * 自动接收对象的监听 : 自动生成队列, 交换机, 绑定
     * @param user
     */
    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue(name = "java502_obj_queue",durable = "true",autoDelete = "false"),
                    exchange = @Exchange(name = "java502_obj_exchange"),
                    key = "object"
            )
    })
    @RabbitHandler
    public void listenObj(@Payload User user){
        System.out.println("接收到了:"+user);
    }
// user:直接接收user 对象必须指定@PayLoad注解
// headers :需要用来获取手动ack的deliveryTag
// channeL :频道用来手动ack

结果:
在这里插入图片描述

扫描二维码关注公众号,回复: 8693833 查看本文章

4 不同交换机类型的路由案例

1. fanout
消费者:

@Component
public class FanoutLintener {

    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue(name = "fanout_queue1",durable = "true",autoDelete = "false"),
                    exchange = @Exchange(name = "fanout_exchange",type = "fanout"),
                    key = "fanout_key"
            )
    })
    @RabbitHandler
    public void listenFanout1(String msg, @Headers Map<String, Object> headers, Channel channel) throws IOException {
        long deliveryTag = (long) headers.get(AmqpHeaders.DELIVERY_TAG);
        System.out.println("消费者1 消费了消息:"+msg);
        channel.basicAck(deliveryTag,true);
    }
    
    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue(name = "fanout_queue2",durable = "true",autoDelete = "false"),
                    exchange = @Exchange(name = "fanout_exchange",type = "fanout"),
                    key = "fanout_key"
            )
    })
    @RabbitHandler
    public void listenFanout2(String msg, @Headers Map<String, Object> headers, Channel channel) throws IOException {
        long deliveryTag = (long) headers.get(AmqpHeaders.DELIVERY_TAG);
        System.out.println("消费者2 消费了消息:"+msg);
        channel.basicAck(deliveryTag,true);
    }
}

生产者RabbitController.java:

    @GetMapping("/rabbit/fanout/{name}")
    public String fanout(@PathVariable String name) {
        rabbitTemplate.convertAndSend("fanout_exchange","fanout_key",name);
        return "success";
    }

访问 localhost:9527/rabbit/fanout/cc
在这里插入图片描述

2. direct
消费者:

@Component
public class DirectListener {

    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue(name = "direct_queue1",durable = "true",autoDelete = "false"),
                    exchange = @Exchange(name = "direct_exchange"),
                    key = "direct_1"
            )
    })
    @RabbitHandler
    public void listenDirect1(String msg, @Headers Map<String, Object> headers, Channel channel) throws IOException {
        long deliveryTag = (long) headers.get(AmqpHeaders.DELIVERY_TAG);
        System.out.println("direct消费者1 消费了消息:"+msg);
        channel.basicAck(deliveryTag,true);
    }

    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue(name = "direct_queue2",durable = "true",autoDelete = "false"),
                    exchange = @Exchange(name = "direct_exchange"),
                    key = "direct_2"
            )
    })
    @RabbitHandler
    public void listenDirect2(String msg, @Headers Map<String, Object> headers, Channel channel) throws IOException {
        long deliveryTag = (long) headers.get(AmqpHeaders.DELIVERY_TAG);
        System.out.println("direct消费者2 消费了消息:"+msg);
        channel.basicAck(deliveryTag,true);
    }
}

生产者:

@GetMapping("/rabbit/direct/{rout}")
    public String sendDirect(@PathVariable String route) {
        rabbitTemplate.convertAndSend("direct_exchange",route,route);
        return "success";
    }

完全匹配,两个队列,取决于用的是哪个routingkey,访问 localhost:9527/rabbit/direct/direct_1 ,这是访问的是第一个routingkey,结果:
在这里插入图片描述
3. topic模糊匹配
消费者:

@Component
public class TopicListener {
    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue(name = "topic_queue1",durable = "true",autoDelete = "false"),
                    exchange = @Exchange(name = "topic_exchange",type = "topic"),
                    key = "com.*.*"
            )
    })
    @RabbitHandler
    public void listenTopic1(String msg, @Headers Map<String, Object> headers, Channel channel) throws IOException {
        long deliveryTag = (long) headers.get(AmqpHeaders.DELIVERY_TAG);
        System.out.println("topic消费者1 消费了消息:"+msg);
        channel.basicAck(deliveryTag,true);
    }

    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue(name = "topic_queue2",durable = "true",autoDelete = "false"),
                    exchange = @Exchange(name = "topic_exchange",type = "topic"),
                    key = "*.hsj.*"
            )
    })
    @RabbitHandler
    public void listenTopic2(String msg, @Headers Map<String, Object> headers, Channel channel) throws IOException {
        long deliveryTag = (long) headers.get(AmqpHeaders.DELIVERY_TAG);
        System.out.println("topic消费者2 消费了消息:"+msg);
        channel.basicAck(deliveryTag,true);
    }

    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue(name = "topic_queue3",durable = "true",autoDelete = "false"),
                    exchange = @Exchange(name = "topic_exchange",type = "topic"),
                    key = "com.#"
            )
    })
    @RabbitHandler
    public void listenTopic3(String msg, @Headers Map<String, Object> headers, Channel channel) throws IOException {
        long deliveryTag = (long) headers.get(AmqpHeaders.DELIVERY_TAG);
        System.out.println("topic消费者3 消费了消息:"+msg);
        channel.basicAck(deliveryTag,true);
    }
}

生产者

GetMapping("/rabbit/topic/{rout}")
    public String sendTopic(@PathVariable String route) {
        rabbitTemplate.convertAndSend("topic _exchange",route,route);
        return "success";
    }
发布了79 篇原创文章 · 获赞 7 · 访问量 1814

猜你喜欢

转载自blog.csdn.net/weixin_45044097/article/details/103959772