springboot2整合rabbitmq

这里只是对springboot整合rabbitmq做一个说明,至于rabbitmmq的介绍,请参考rabbitmq的简介
注意:本门使用的版本是springboot2.1.7

一、入门体验

1、首先,导入相关的依赖

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
 </dependency>

2、在application.properties中加入服务器相关配置

spring.rabbitmq.host=自己的服务器ip
spring.rabbitmq.username=登录名
spring.rabbitmq.password=登陆密码
spring.rabbitmq.port=5672

注意:这里端口使用5672,不是15672,15672端口是访问控制台时的端口。当然,也可以不用指定,默认就是5672

3、创建一个配置类,创建一个名字为hello的队列

package com.xyn.config;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author 17715
 */
@Configuration
public class RabbitmqConfig {
    /**
     * 创建队列
     * @return
     */
    @Bean
    public Queue queue(){
        return new Queue("hello");
    }
    /**
     * 创建exchange
     */

}

然后设置发送端

package com.xyn.service.serviceImp;

import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @author 17715
 * 消息队列的发送者
 */
@Component
public class HelloSender {
    @Autowired
    private AmqpTemplate template;      //自动配置
    public void send(){
        String message="hello world";
        System.out.println("要发送消息"+message);
        template.convertAndSend("hello",message);      //这里的hello为队列的名字
    }
}

设置接收端

package com.xyn.service;

import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

/**
 * @author 17715
 * 测试接收消息
 */
@Component
/**
 * 指定监听,并说明监听的队列
 */
@RabbitListener(queues = "hello")       //监听hello这个队列
public class HelloReceiver {
    /**
     * 设置处理器
     */
    @RabbitHandler
    public void handle(String message){         //message参数为要接收的参数,不写将监听不到
        System.out.println("receiver收到了"+message);
    }
}

通过控制器controller调用其方法后,输出如下:
在这里插入图片描述

补充:
这里补充下我尝试时所遇到的坑,配置如上面所示,可是启动的时候连接被拒绝,报org.springframework.amqp.AmqpConnectException: java.net.ConnectException的错误,报错信息如下:
在这里插入图片描述
这使我百思不得其解,服务器上防火墙也关了,可就是连接被拒绝,最无语的是,我可以通过15672这个端口进入rabbitmq的控制台界面。后来,我尝试telnet 5672这个端口,发现既然不通。去到服务器上,通过ss -ntl命令查看被监听的端口,显示如下:
在这里插入图片描述
发现被监听的端口既然没有5672,这样导致了远程访问不了这个端口。我进入docker容器查看我的rabbitmq,如下:
在这里插入图片描述
发现5672这个端口前面没有0.0.0.0,即没有被映射到本地,那远程访问这个端口当然不行。
之后,我把容器中的rabbitmq重新删除,并执行如下命令安装

docker run -d --hostname my-rabbit --name rabbit -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin -p 15672:15672 -p 5672:5672 -p 25672:25672 -p 61613:61613 -p 1883:1883 rabbitmq:management

再此启动之后,查看容器
在这里插入图片描述
这里可以看到,已经将5672这个端口映射到了本机,通过命令netstat -an | grep 5672查看5672是否被监听,如下:
在这里插入图片描述
可以看出5672端口已经被监听。此时再talnet以及访问5672端口就可以远程连接上了。
错误总结:没有注意到docker还需要将容器中的服务映射到本地,即执行docker run时指定-p,将端口映射到本地,否则无法进行远程访问。
在这里插入图片描述

二、通过交换机exchange发送消息以及消费消息

1、想要通过exchange来进行消息管理,首先要创建exchange以及队列queue,并将exchange与队列queue连接起来binding
2、TopicExchange来进行消息管理

  • 首先创建exchange并通过binding将exchange与队列queue连接起来
  • 这里使用两个队列,并让其都与my.topic的exchange连接起来,方便体现TopicExchange的功能展示
package com.xyn.config;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author 17715
 */
@Configuration
public class RabbitmqConfig {
    /**
     * 创建队列1
     * @return
     */
    @Bean
    public Queue queue(){
        return new Queue("hello");
    }
    /**
     * 创建队列2
     */
    @Bean
    public Queue queue2(){
        return new Queue("hi");
    }
    /**
     * 创建exchange
     */
    @Bean
    public TopicExchange topicExchange(){
        return new TopicExchange("my.topic");
    }
    /**
     * 创建binding,用于连接exchnag以及队列queue
     * 将路由与hello队列关联
     */
    @Bean
    public Binding helloBinding(Queue queue,TopicExchange topicExchange){
        //指定连接的路由关键字,当关键字为helloExchang时,将消息给hello队列
        return BindingBuilder.bind(queue).to(topicExchange).with("hello.Exchange");
    }
    /**
     * 连接hi队列
     * 结果:hi会接收到两个,hello只会接收到一个
     */
    @Bean
    public Binding hiBinding(Queue queue2,TopicExchange topicExchange){
        return BindingBuilder.bind(queue2).to(topicExchange).with("#.Exchange");
    }

}

注意:这里的每一个exchange,queue以及binding都要使用@bean注解注入spring容器,否则将会消息管理失败

  • 创建发送者,依旧用amqpTemplate,传入要发送给的路由和自己指定的路由关键字以及要发送的消息,路由会根据你所给的关键字与其设定的路由关键字进行匹配,路由关键字匹配成功则发送给相应的队列,否则将不发送给队列。
package com.xyn.service.serviceImp;

import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @author 17715
 * 消息队列的发送者
 */
@Component
public class HelloSender {
    @Autowired
    private AmqpTemplate template;
    public void send(){
        String message="hello world";
        //发送,指定路由表名字,路由关键字的匹配以及发送的消息
        System.out.println("发送"+message);
        template.convertAndSend("my.topic","hello.Exchange",message);   //指定要发送给的路由的名字以及关键字
    }
    public void send2(){
        String message="hello world2";
        //发送,指定路由表名字,路由关键字的匹配以及发送的消息
        System.out.println("发送"+message);
        template.convertAndSend("my.topic","Hi.Exchange",message);
    }
}

  • 创建监听者,这里创建两个监听者,分别监听hi队列和hello队列
package com.xyn.service.serviceImp;

import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @author 17715
 * 消息队列的发送者
 */
@Component
public class HelloSender {
    @Autowired
    private AmqpTemplate template;
    public void send(){
        String message="hello world";
        //发送,指定交换机名字,路由关键字的匹配以及发送的消息
        System.out.println("发送"+message);
        template.convertAndSend("my.topic","hello.Exchange",message);
    }
    public void send2(){
        String message="hello world2";
        //发送,指定交换机名字,路由关键字的匹配以及发送的消息
        System.out.println("发送"+message);
        template.convertAndSend("my.topic","Hi.Exchange",message);
    }
}


package com.xyn.service;

import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

/**
 * @author 17715
 * 测试接收消息
 */


@Component

/**
 * 指定监听,并说明监听的队列
 */

@RabbitListener(queues = "hello")
public class HelloReceiver {
    /**
     * 设置处理器
     */

    @RabbitHandler
    public void handle(String message) {
        System.out.println("hello队列收到了" + message);
    }
}


  • 运行程序,控制台输出如下:
    在这里插入图片描述

这里说明下为什么hi队列可以接收到两个消息,因为与其匹配的交换机的路由关键字为==#.Exchange==,它会匹配任何字母.Exchange的关键字。这个也就是topicExchang的特点
注意:这里一定要加.,倘若就简单的==#Exchange==这样,它是不会匹配以Exchange结尾的字符串的,例如不匹配HiExchange

  • 交换机的路由关键字的特殊字符还可以用*,可以代替一个字,因为#代表零个或多个单词,当路由关键字为#.Exchange的时候,发送时给Exchange也给以发送给指定的队列

*(星号)可以代替一个字。
#(散列)可以代替零个或多个单词。

三、关于使用其它交换机进行路由交换

rabbitmq的交换机除了TopicExchange以外,还有Direct Exchange(只有给定的关键字与路由关键字完全匹配的时候才会发送给相应的队列)Fanout exchange(不管路由关键字,将消息发给与这个交换机绑定的每一个队列)Header exchange(通过header信息来与队列进行通讯,忽略路由关键字).具体说明请参考rabbitmq的四种交换机
因为这里的代码实现于topicExchange的代码实现本质是相同的,只是每一个路由规则不同而已,所以就不做演示了。

做一个补充,当使用Fanout进行路由的时候,因为此交换机为群发交换机,所以创此交换机的时候无需指定路由关键字,发送的时候也无需指定关键字,传一空字符串即可
在这里插入图片描述
在这里插入图片描述

四、总结

使用rabbitmq进行消息队列的管理有两种方式,一种直接将消息发送给指定的队列,一种是通过交换机的路由将消息发送给指定的队列。这两种都需要对队列进行监听才能取得数据。当一个队列有很多个接收者时,队列的消息将平均分给多个接收者。
此博客参考借鉴了如下博客:springboot整合rabbitmq,在其基础上加上自己所踩坑的记录。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值