简单使用rabbitmq 和一些改进

炒鸡辣鸡说RabbitMQ

不求甚解

收取消息

@Service
@Slf4j
public class RabbitMqMessage {

    private static final String EXCHANGE = "html";
    private static final String CHECK_QUEUE = "check-queue";

    @Autowired
    private DoCheckTask doCheckTask;
    
    @Bean
    private Declarables declarables() {
        Queue queue = new Queue(CHECK_QUEUE);
        FanoutExchange exchange = new FanoutExchange(EXCHANGE);
        return new Declarables(queue, exchange, BindingBuilder.bind(queue).to(exchange));
    }
    @RabbitListener(queues = CHECK_QUEUE)
    public void receiverHtml(String urlContent) {
        UrlContent urlContent1 = Json.toObject(urlContent, UrlContent.class);
        doCheckTask.urlContentPriorityBlockingQueue.add(urlContent1);
    }
}

发送消息

@Service
@Slf4j
@Configuration
public class RabbitMqMessage {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 页面内容广播交换机
     */
    private static final String HTML_EXCHANGE = "html";
    
    @Bean
    public Declarables declarables() {
        FanoutExchange exchange = new FanoutExchange(HTML_EXCHANGE);
        return new Declarables(exchange);
    }

    public void sendHtmlToMessageQueue(String urlContent) {
        rabbitTemplate.convertAndSend(HTML_EXCHANGE, "", urlContent);
    }
}

简单来说,我们只需要定义好消息队列的交换器和队列即可。交换器需要首先在你的管理页面中定义好。必不可少的是,我们在配置文件中定义好连接设置

spring.rabbitmq.host=
spring.rabbitmq.port=
spring.rabbitmq.username=
spring.rabbitmq.password=

当然,既然我们使用了消息队列的注解,必不可少的,需要在依赖中安装相关的包,这里使用maven来管理包,所以相关的依赖为

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

是不是很简单?如果你比较忙,只要能用就行,那么抄上面的代码稍微再修改一下,就能满足你的使用条件了。

还要干嘛?

再来看看这段代码,首先使用@Service注解,让springboot在启动的时候,spring容器会加载这个类,注册为一个服务,然后@Bean来绑定我们的队列和交换机。你可以暂时将消息队列想象成带有存储功能的三层路由器。三层路由器具有交换机的功能,通过计算机网络的知识我们知道,交换机的功能是限定在局域网中,那么使用同一个exchange都是同一个局域网的(虚拟局域网也是局域网),所以我们在定义哪些队列绑定哪些交换器的时候,也需要考虑业务消息的相关性,不能一股脑的全部放在同一个交换器下。

@Bean
private Declarables declarables() {
    Queue queue = new Queue(CHECK_QUEUE); // 定义队列对象:从哪个队列中获取信息
    FanoutExchange exchange = new FanoutExchange(EXCHANGE); // 定义交换器对象
    return new Declarables(queue, exchange, BindingBuilder.bind(queue).to(exchange)); // 将两者绑定起来
}

这段代码,在项目启动的时候,@Bean会告诉spring容器去执行这段代码,并生成这样的Declarables,也就是绑定成功了。然后我们只需要定义监听这个队列的函数即可。

@RabbitListener(queues = CHECK_QUEUE)
public void receiverHtml(String urlContent) {
    UrlContent urlContent1 = Json.toObject(urlContent, UrlContent.class);
    doCheckTask.urlContentPriorityBlockingQueue.add(urlContent1);
}

这段代码就是绑定了监听队列CHECK_QUEUE,当监听到该队列中有数据时,receiverHtml方法就会被调用,然后数据被放到urlContent中。

发送消息部分也一样

@Bean
public Declarables declarables() {
    FanoutExchange exchange = new FanoutExchange(HTML_EXCHANGE);
    return new Declarables(exchange);
}

这里也是注册了一个交换器,为啥要在注册一次?如果你是在一个项目中,那么不需要再次声明该exchange。

public void sendHtmlToMessageQueue(String urlContent) {
    rabbitTemplate.convertAndSend(HTML_EXCHANGE, "", urlContent);
}

发送消息到交换器,直接使用rabbitTemplate实现即可。

求甚解

了解交换器和队列

队列

AnonymousQueue:代表一个匿名的,非持久的,排他的,自动删除队列

Queue:默认的队列

交换器

DirectExchange:它会把消息路由到那些 BindingKey RoutingKey 完全匹配的队列中。

FanoutExchange:广播交换器:它会把所有发送到该交换器的消息路由到所有与该交换器绑定的队列中。

TopicExchange:主题交换器

HeadersExchange:不依赖于路由键的匹配规则来路由消息,而是根据发送的消息内容中 headers 属性进行匹配。headers 类型的交换器性能会很差,而且也不实用,基本上不会看到它的存在。

CustomExchange:自定义交换器

AbstractExchange:抽象交换器,作为基础存在

如果队列特别多怎么办

集中控制,在官网的demo中,有一种方案是将全部队列和交换器注册在一起

一共四个文件,一个注册bean的文件叫RabbitMqConfig.java用于注册所有的Bean。然后一个ConstNames用于存放所有的名字。一个sender和一个receiver即可。

就像这样:

@Configuration
public class RabbitMqConfig {

    @Bean
    public Receiver receiver() {
        return new Receiver();
    }

    @Bean
    public DirectExchange exchange(){
        return new DirectExchange(ConstNames.EXCHANGE);
    }

    @Bean
    public Queue queue(){
        return new Queue(ConstNames.QUEUE);
    }

    @Bean
    public Binding bindingEvent(DirectExchange exchange,Queue queue){
        return BindingBuilder.bind(queue).to(exchange).withQueueName();
    }
    
    @Bean
    public xxxx xxxx(){
        // 这里再定义一个Sender即可
    }
}

// Receiver.java
public class Receiver {
    @RabbitListener(queues = ConstNames.QUEUE)
    public void receiveEvent(String in) {
        System.out.println(in);
    }
}

// 管理名字
public class ConstNames{
    public static final String EXCHANGE = "exchange";
    public static final String QUEUE = "queue";
}

这样就避免写大量重复的代码了,同时上面的内容也可以写个东西自动生成代码。

炒鸡辣鸡原创文章,转载请注明来源

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,458评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,030评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,879评论 0 358
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,278评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,296评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,019评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,633评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,541评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,068评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,181评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,318评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,991评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,670评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,183评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,302评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,655评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,327评论 2 358