1. 程式人生 > 實用技巧 >新鮮出爐,這是全網講的最詳細的springboot整合訊息服務了吧,建議收藏!

新鮮出爐,這是全網講的最詳細的springboot整合訊息服務了吧,建議收藏!

springboot整合activeMq

ActiveMq是Apache提供的開源訊息系統採用java實現,

很好地支援JMS(Java Message Service,即Java訊息服務) 規範

ActiveMq安裝:http://activemq.apache.org/components/classic/download/在官網下載安裝對應的版本

下載完成後解壓就可以使用

ActiveMq預設的埠號是8161,使用者名稱和密碼都是admin 在本機可以使用http://localhost:8161去訪問

springboot整合ActiveMq

1、匯入依賴

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

  

2、在properties檔案中配置activeMq

spring.activemq.broker-url=tcp://localhost:61616
#如果是點對點(queue),那麼此處預設應該是false,如果釋出訂閱,那麼一定設定為true
spring.activemq.packages.trust-all=true
spring.activemq.user=admin
spring.activemq.password=admin

  

3、編寫queue(佇列)

@Component
public class QueueBean{
    //建立一個佇列例項
    @Bean
    Queue queue(){
        //這裡設定的訊息是佇列的名稱
        return new ActiveMQQueue("hello.javaboy");
    }
}

  

4、建立訊息的傳送者以及消費者

@Component
public class JmsComponent{
    //springboot提供的訊息模板
    @Autowired
    JmsMessagingTemplate jmsMessagingTemplate;
    //自己建立的佇列例項
    @Autowired
    Queue queue;
    /**
     * 傳送訊息
     * @param message
     */
    public void send(Message message){
        jmsMessagingTemplate.convertAndSend(this.queue,message);
    }
    /**
     * 接收訊息
     * @param message
     */
    //表示監聽該佇列名稱發來的訊息
    @JmsListener(destination = "hello.javaboy")
    public void readMessage(Message message){
        System.out.println(message);
    }
​
}

  

5、上述Message實體類

public class Message implements Serializable {
    private String content;//訊息主體
    private Date sendDate;//訊息傳送的時間
    //省略get、set、tostring方法
}

  

6、進行訊息的傳送以及消費

在測試類中注入JmsComponent 呼叫send()方法進行訊息的轉發

@SpringBootTest
class ActivemqApplicationTests {
    @Autowired
    JmsComponent jmsComponent;
    @Test
    void contextLoads() {
        Message message = new Message();
        message.setContent("hello activeMq");
        message.setSendDate(new Date());
        jmsComponent.send(message);
    }
}

  

首先啟動專案,在執行測試類進行訊息傳送:

控制檯會列印訊息內容:

springboot整合RabbitMQ

rabbitmq安裝比較繁瑣,這裡使用docker容器進行安裝,docker安裝非常方便,一條命令全部搞定

通過docker安裝rabbitmq

-P(大p)表示自動對映到主機埠

docker run -d --hostname my-rabbitmq --name some-rabbitmq -P rabbitmq:3-management

  

首先匯入依賴

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

  

編寫配置檔案:

#配置rabbitMQ
spring.rabbitmq.host=localhost
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.port=32771

  

RabbitMQ 四種交換模式:

直連交換機:Direct exchange

扇形交換機:Fanout exchange

主體交換機:Topic exchange

首部交換機:Headers exchange

下面分別介紹4中交換模式:

1、Direct exchange

//Direct策略(只轉發給routingKey相匹配的使用者)
@Configuration
public class RabbitDirectConfig {
    public final static String DIRECTNAME = "javaboy-direct";
    //訊息佇列
    @Bean
    Queue queue(){
        //name值為佇列名稱,routingKey會與他進行匹配
        return new Queue("hello.RabbitMQ");
    }
    @Bean
    Queue queue1(){
        return new Queue("hello.RabbitMQ1");
    }
    @Bean
    DirectExchange directExchange(){
        //第一個引數為DIRECTNAME、第二個引數表示重啟後是否有效,第三引數表示長時間未使用是否刪除
        return new DirectExchange(DIRECTNAME,true,false);
    }
    @Bean
    Binding binding(){
        //將佇列queue和DirectExchange繫結在一起
        return BindingBuilder.bind(queue()).to(directExchange()).with("direct");
    }
    @Bean
    Binding binding1(){
        //將佇列queue和DirectExchange繫結在一起
        return BindingBuilder.bind(queue1()).to(directExchange()).with("direct");
    }
​
}

  

2、配置消費者DirectReceiver:

//配置消費者
@Component
public class DirectReceiver {
    //只監聽queue()佇列的訊息
    @RabbitListener(queues = "hello.RabbitMQ")
    public void hanlder(String msg){
        System.out.println("hanlder>>>"+msg);
​
    }
    //只監聽queue1()佇列的訊息
    @RabbitListener(queues = "hello.RabbitMQ1")
    public void hanlder1(String msg){
        System.out.println("hanlder1>>>"+msg);
​
    }
}

  

測試程式碼:

在springboot的測試類中注入RabbitTemplate(springboot提供的RabbitMQ模板)

 @Autowired
    RabbitTemplate rabbitTemplate;
    @Test
    void contextLoads() {
        //兩個引數第一個是routingKey、第二個為訊息內容
        rabbitTemplate.convertAndSend("hello.RabbitMQ","hello RabbitMQ test");
        rabbitTemplate.convertAndSend("hello.RabbitMQ1","hello RabbitMQ test222");
    }

  

啟動專案後,執行測試類可以看到只有與routingkey相匹配的消費者受到了對應的訊息:

2、Fanout exchange

Fanout策略(只要是與他繫結的佇列,都會收到訊息與routingKey無關)

1、配置RabbitFanoutConfig:

//Fanout策略(只要是與他繫結的佇列,都會收到訊息與routingKey無關)
@Configuration
public class RabbitFanoutConfig {
    public final static String FANOUTNAME = "javaboy-fanout";
    //配置了兩個訊息佇列queueOne和queueTwo
    @Bean
    Queue queueOne(){
        return new Queue("queue-one");
    }
    @Bean
    Queue queueTwo(){
        return new Queue("queue-two");
    }
    @Bean
    FanoutExchange fanoutExchange(){
        return new FanoutExchange(FANOUTNAME,true,false);
    }
    //將兩個佇列與FanoutExchange繫結
    @Bean
    Binding bindingOne(){
        return BindingBuilder.bind(queueOne()).to(fanoutExchange());
    }
    @Bean
    Binding bindingTwo(){
        return BindingBuilder.bind(queueTwo()).to(fanoutExchange());
    }
}

  

2、配置消費者FanoutReceiver:

//配置消費者
@Component
public class FanoutReceiver {
    //兩個消費者分別監聽兩個不同的佇列
    @RabbitListener(queues = "queue-one")
    public void hanlder1(String msg){
        System.out.println("FanoutReceiver:hanlder1>>>"+msg);
​
    }
    @RabbitListener(queues = "queue-two")
    public void hanlder2(String msg){
        System.out.println("FanoutReceiver:hanlder2>>>"+msg);
​
    }
}

  

3、測試類:

@Test
    void rabbitFanout(){
        //三個引數表示RabbitFanoutConfig的名稱、routingkey、訊息內容
        rabbitTemplate.convertAndSend(RabbitFanoutConfig.FANOUTNAME,null,"hello fanout test");
    }

  

該方式與routingkey無關所有寫null即可

檢視輸出:可以看到兩個消費者都收到了訊息

3、Topic exchange

topic策略可以根據routingKey的規則(萬用字元方式)進行去匹配佇列進行轉發規則為.#. *為單詞,#表示模糊匹配

例如routingkey為:xiaomi.# 那麼帶有xiaomi.開頭的佇列都會收到該訊息

routingkey為:#.phone.# 表示訊息的routingKey中帶有phone時 就會去匹配帶有phone的佇列

1、配置RabbitTopicConfig:

/topic策略可以根據routingKey的規則(萬用字元方式)進行去匹配佇列進行轉發規則為*.#.*
    //*為單詞,#表示模糊匹配
@Configuration
public class RabbitTopicConfig {
    public final static String TOPICNAME = "javaboy-topic";
​
    @Bean
    TopicExchange topicExchange(){
        return new TopicExchange(TOPICNAME,true,false);
    }
    @Bean
    Queue xiaomi(){
        return new Queue("xiaomi");
    }
    @Bean
    Queue huawei(){
        return new Queue("huawei");
    }
    @Bean
    Queue phone(){
        return new Queue("phone");
    }
​
    @Bean
    Binding xiaomiBinding(){
        //xiaomi.#:表示訊息的routingKey是以xiaomi開頭的就會路由到xiaomi的佇列
        return BindingBuilder.bind(xiaomi()).to(topicExchange()).with("xiaomi.#");
    }
    @Bean
    Binding huaweiBinding(){
        return BindingBuilder.bind(huawei()).to(topicExchange()).with("huawei.#");
    }
    @Bean
    Binding phoneBinding(){
        //#.phone.#:表示訊息的routingKey中帶phone的都會路由到phone的佇列
        return BindingBuilder.bind(phone()).to(topicExchange()).with("#.phone.#");
    }
}

  

2、配置消費者TopicReceiver:

@Component
public class TopicReceiver {
    //分別監聽名稱為xiaomi、huawei、phone的佇列
    @RabbitListener(queues = "xiaomi")
    public void handlerXM(String msg){
        System.out.println("TopicReceiver:handlerXM>>>"+msg);
    }
    @RabbitListener(queues = "huawei")
    public void handlerHW(String msg){
        System.out.println("TopicReceiver:handlerHW>>>"+msg);
    }
    @RabbitListener(queues = "phone")
    public void handlerPHONE(String msg){
        System.out.println("TopicReceiver:handlerPHONE>>>"+msg);
    }
}

  

3、測試類:

@Test
    void rabbitTopic(){
        //根據匹配規則該訊息只能被xiaomi的佇列收到
        rabbitTemplate.convertAndSend(RabbitTopicConfig.TOPICNAME,"xiaomi.news","小米新聞");
        //根據匹配規則該訊息只能被phone的佇列收到
        rabbitTemplate.convertAndSend(RabbitTopicConfig.TOPICNAME,"vivo.phone","vivo手機");
        //根據匹配規則該訊息可以別huawei和phone兩個佇列收到
        rabbitTemplate.convertAndSend(RabbitTopicConfig.TOPICNAME,"huawei.phone","華為手機");
​
    }

  

檢視輸出:

可以看到routingkey為huawei.phone的訊息匹配了兩個佇列,其他兩個都只匹配了一個佇列

4、Headers exchange

該模式是根據路由規則的header進行匹配的,在進行匹配的時候需要傳入一個map集合,routingkey去匹配map即可中的key value,匹配規則可以使any或者all,any表示只要包含任意資訊就可以,all表示所有資訊都必須匹配

1、配置RabbitHeaderConfig:

@Configuration
public class RabbitHeaderConfig {
    public final static String HEADERNAME = "javaboy-header";
​
    @Bean
    HeadersExchange headersExchange(){
        return new HeadersExchange(HEADERNAME,true,false);
    }
    //分別建立兩個不同header的佇列
    @Bean
    Queue queueName(){
        return new Queue("name-queue");
    }
    @Bean
    Queue queueAge(){
        return new Queue("age-queue");
    }
    @Bean
    Binding bindingName(){
        Map<String,Object> map = new HashMap<>();
        map.put("name","hello");
        //表示如果routingKey匹配的map集合中的key value 就會將訊息轉發到對應的路由上
        return BindingBuilder.bind(queueName()).to(headersExchange()).whereAny(map).match();
    }
​
    @Bean
    Binding bindingAge(){
        return BindingBuilder.bind(queueAge()).to(headersExchange()).where("age").exists();
    }
}

  

2、建立消費者HeaderReceiver:

@Component
public class HeaderReceiver {
    @RabbitListener(queues = "name-queue")
    public void handlerName(byte[] msg){
        System.out.println("HeaderReceiver:handlerName>>>>"+new String(msg,0,msg.length));
    }
    @RabbitListener(queues = "age-queue")
    public void handlerAge(byte[] msg){
        System.out.println("HeaderReceiver:handlerAge>>>>"+new String(msg,0,msg.length));
    }
}

  

3、測試程式碼:

@Test
    public void rabbitHeader(){
        //設定訊息,並且設定header,setHeader("name","hello")分別表示map集合中的key、value
        Message nameMessage = 
            MessageBuilder.withBody("hello name".getBytes()).setHeader("name","hello").build();
        Message ageMessage =
            MessageBuilder.withBody("hello 99 age".getBytes()).setHeader("age","99").build();
        rabbitTemplate.send(RabbitHeaderConfig.HEADERNAME,null,nameMessage);
        rabbitTemplate.send(RabbitHeaderConfig.HEADERNAME,null,ageMessage);
    }

  

檢視輸出:

改變setheader中的值檢視結果:

 Message nameMessage = 
            MessageBuilder.withBody("hello name".getBytes()).setHeader("name","javaboy").build();

  

可以看到因為key、value匹配不上只打印了一條訊息。

最後

大家看完有什麼不懂的可以在下方留言討論,也可以關注我私信問我,我看到後都會回答的。也歡迎大家關注我的公眾號:前程有光,金三銀四跳槽面試季,整理了1000多道將近500多頁pdf文件的Java面試題資料,文章都會在裡面更新,整理的資料也會放在裡面。謝謝你的觀看,覺得文章對你有幫助的話記得關注我點個贊支援一下!