java手把手教你搭建簡單的后臺(tái)服務(wù)器(五)

后臺(tái)服務(wù)器搭建不懂得先看一下

功能結(jié)構(gòu)圖

springboot集成RabbitMQ非常簡單,如果只是簡單的使用配置非常少,springboot提供了spring-boot-starter-amqp項(xiàng)目對(duì)消息各種支持。

簡單使用

1、配置pom包,主要是添加spring-boot-starter-amqp的支持

注冊(cè)服務(wù)
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>

2、配置文件

配置服務(wù)器
spring.rabbitmq.host=192.168.9.62 

spring.rabbitmq.port=5672

spring.rabbitmq.username=admin

spring.rabbitmq.password=123456

3、隊(duì)列配置

隊(duì)列配置
package com.demo.springboot.config;

import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RabbitConfig {

    /**
     * 消息隊(duì)列對(duì)象
     * @return
     */
    @Bean
    public Queue helloQueue() {
        return new Queue("hello");
    }
}

4、發(fā)送者

rabbitTemplate是springboot 提供的默認(rèn)實(shí)現(xiàn)

public class HelloSender {

    @Autowired
    private AmqpTemplate rabbitTemplate;

    public void send() {
        String context = "hello " + new Date();
        System.out.println("Sender : " + context);
        this.rabbitTemplate.convertAndSend("hello", context);
    }

}

5、接收者

@Component
@RabbitListener(queues = "hello")
public class HelloReceiver {

    @RabbitHandler
    public void process(String hello) {
        System.out.println("Receiver  : " + hello);
    }

}

6、測試

@RunWith(SpringRunner.class)
@SpringBootTest
public class RabbitMqHelloTest {

    @Autowired
    private HelloSender helloSender;

    @Test
    public void hello() throws Exception {
        helloSender.send();
    }

}
  • 注意,發(fā)送者和接收者的queue name必須一致,不然不能接收
啟動(dòng)服務(wù) 打印log輸出
發(fā)送服務(wù)

這個(gè)和android里的EventBus是有區(qū)別的 這個(gè)是脫離了javaContext的 可以通知到所有啟動(dòng)的服務(wù) 且監(jiān)聽事件的服務(wù)器
android里的只能監(jiān)聽app內(nèi)部事件

服務(wù)A 發(fā)送事件 channel hello 服務(wù)器B 和服務(wù)器C 如果監(jiān)聽了 也能收到事件信息

功能結(jié)構(gòu)圖

多對(duì)多使用

一個(gè)發(fā)送者,N個(gè)接收者或者N個(gè)發(fā)送者和N個(gè)接收者會(huì)出現(xiàn)什么情況呢?

一對(duì)多發(fā)送

對(duì)上面的代碼進(jìn)行了小改造,接收端注冊(cè)了兩個(gè)Receiver,Receiver1和Receiver2,發(fā)送端加入?yún)?shù)計(jì)數(shù),接收端打印接收到的參數(shù),下面是測試代碼,發(fā)送一百條消息,來觀察兩個(gè)接收端的執(zhí)行效果

@Test
public void oneToMany() throws Exception {
    for (int i=0;i<100;i++){
        neoSender.send(i);
    }
}

結(jié)果如下:

Receiver 1: spirng boot neo queue ****** 11
Receiver 2: spirng boot neo queue ****** 12
Receiver 2: spirng boot neo queue ****** 14
Receiver 1: spirng boot neo queue ****** 13
Receiver 2: spirng boot neo queue ****** 15
Receiver 1: spirng boot neo queue ****** 16
Receiver 1: spirng boot neo queue ****** 18
Receiver 2: spirng boot neo queue ****** 17
Receiver 2: spirng boot neo queue ****** 19
Receiver 1: spirng boot neo queue ****** 20

根據(jù)返回結(jié)果得到以下結(jié)論

  • 一個(gè)發(fā)送者,N個(gè)接受者,經(jīng)過測試會(huì)均勻的將消息發(fā)送到N個(gè)接收者中

多對(duì)多發(fā)送

復(fù)制了一份發(fā)送者,加入標(biāo)記,在一百個(gè)循環(huán)中相互交替發(fā)送

@Test
    public void manyToMany() throws Exception {
        for (int i=0;i<100;i++){
            neoSender.send(i);
            neoSender2.send(i);
        }
}

結(jié)果如下:

Receiver 1: spirng boot neo queue ****** 20
Receiver 2: spirng boot neo queue ****** 20
Receiver 1: spirng boot neo queue ****** 21
Receiver 2: spirng boot neo queue ****** 21
Receiver 1: spirng boot neo queue ****** 22
Receiver 2: spirng boot neo queue ****** 22
Receiver 1: spirng boot neo queue ****** 23
Receiver 2: spirng boot neo queue ****** 23
Receiver 1: spirng boot neo queue ****** 24
Receiver 2: spirng boot neo queue ****** 24
Receiver 1: spirng boot neo queue ****** 25
Receiver 2: spirng boot neo queue ****** 25
  • 結(jié)論:和一對(duì)多一樣,接收端仍然會(huì)均勻接收到消息

高級(jí)使用

對(duì)象的支持

springboot以及完美的支持對(duì)象的發(fā)送和接收,不需要格外的配置。

//發(fā)送者
public void send(User user) {
    System.out.println("Sender object: " + user.toString());
    this.rabbitTemplate.convertAndSend("object", user);
}

...

//接收者
@RabbitHandler
public void process(User user) {
    System.out.println("Receiver object : " + user);
}

結(jié)果如下:

Sender object: User{name='neo', pass='123456'}
Receiver object : User{name='neo', pass='123456'}

Topic Exchange

topic 是RabbitMQ中最靈活的一種方式,可以根據(jù)routing_key自由的綁定不同的隊(duì)列

首先對(duì)topic規(guī)則配置,這里使用兩個(gè)隊(duì)列來測試

@Configuration
public class TopicRabbitConfig {

    final static String message = "topic.message";
    final static String messages = "topic.messages";

    @Bean
    public Queue queueMessage() {
        return new Queue(TopicRabbitConfig.message);
    }

    @Bean
    public Queue queueMessages() {
        return new Queue(TopicRabbitConfig.messages);
    }

    @Bean
    TopicExchange exchange() {
        return new TopicExchange("exchange");
    }

    @Bean
    Binding bindingExchangeMessage(Queue queueMessage, TopicExchange exchange) {
        return BindingBuilder.bind(queueMessage).to(exchange).with("topic.message");
    }

    @Bean
    Binding bindingExchangeMessages(Queue queueMessages, TopicExchange exchange) {
        return BindingBuilder.bind(queueMessages).to(exchange).with("topic.#");
    }
}

使用queueMessages同時(shí)匹配兩個(gè)隊(duì)列,queueMessage只匹配”topic.message”隊(duì)列

public void send1() {
    String context = "hi, i am message 1";
    System.out.println("Sender : " + context);
    this.rabbitTemplate.convertAndSend("exchange", "topic.message", context);
}

public void send2() {
    String context = "hi, i am messages 2";
    System.out.println("Sender : " + context);
    this.rabbitTemplate.convertAndSend("exchange", "topic.messages", context);
}

發(fā)送send1會(huì)匹配到topic.#和topic.message 兩個(gè)Receiver都可以收到消息,發(fā)送send2只有topic.#可以匹配所有只有Receiver2監(jiān)聽到消息

Fanout Exchange

Fanout 就是我們熟悉的廣播模式或者訂閱模式,給Fanout交換機(jī)發(fā)送消息,綁定了這個(gè)交換機(jī)的所有隊(duì)列都收到這個(gè)消息。

Fanout 相關(guān)配置

@Configuration
public class FanoutRabbitConfig {

    @Bean
    public Queue AMessage() {
        return new Queue("fanout.A");
    }

    @Bean
    public Queue BMessage() {
        return new Queue("fanout.B");
    }

    @Bean
    public Queue CMessage() {
        return new Queue("fanout.C");
    }

    @Bean
    FanoutExchange fanoutExchange() {
        return new FanoutExchange("fanoutExchange");
    }

    @Bean
    Binding bindingExchangeA(Queue AMessage,FanoutExchange fanoutExchange) {
        return BindingBuilder.bind(AMessage).to(fanoutExchange);
    }

    @Bean
    Binding bindingExchangeB(Queue BMessage, FanoutExchange fanoutExchange) {
        return BindingBuilder.bind(BMessage).to(fanoutExchange);
    }

    @Bean
    Binding bindingExchangeC(Queue CMessage, FanoutExchange fanoutExchange) {
        return BindingBuilder.bind(CMessage).to(fanoutExchange);
    }

}

這里使用了A、B、C三個(gè)隊(duì)列綁定到Fanout交換機(jī)上面,發(fā)送端的routing_key寫任何字符都會(huì)被忽略:

public void send() {
        String context = "hi, fanout msg ";
        System.out.println("Sender : " + context);
        this.rabbitTemplate.convertAndSend("fanoutExchange","", context);
}

結(jié)果如下:

Sender : hi, fanout msg 
...
fanout Receiver B: hi, fanout msg 
fanout Receiver A  : hi, fanout msg 
fanout Receiver C: hi, fanout msg 

結(jié)果說明,綁定到fanout交換機(jī)上面的隊(duì)列都收到了消息

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,506評(píng)論 19 139
  • RabbitMQ 即一個(gè)消息隊(duì)列,主要是用來實(shí)現(xiàn)應(yīng)用程序的異步和解耦,同時(shí)也能起到消息緩沖,消息分發(fā)的作用。 消息...
    彩虹之夢閱讀 1,147評(píng)論 2 1
  • 分布式開放消息系統(tǒng)(RocketMQ)的原理與實(shí)踐 來源:http://www.itdecent.cn/p/453...
    meng_philip123閱讀 13,217評(píng)論 6 104
  • 來源 RabbitMQ是用Erlang實(shí)現(xiàn)的一個(gè)高并發(fā)高可靠AMQP消息隊(duì)列服務(wù)器。支持消息的持久化、事務(wù)、擁塞控...
    jiangmo閱讀 10,505評(píng)論 2 34
  • 1、canvas 是H5 新加入的標(biāo)簽 用來在頁面中繪制圖形 一般稱之為畫布。2、canvas的寬高要以屬性的形...
    Simon_s閱讀 591評(píng)論 0 0

友情鏈接更多精彩內(nèi)容