前言
最近博主在自學activeMQ,在學習過程遇到了很多坑,跟大家分享一下。版本信息:SpringBoot2.1.5
ActiveMQ 5.15.10
升級版本:
pringboot整合activeMQ系列之Queue(二) 加入websocket自動推送和持久化、手動簽收、重複
主題(Topic)地址:
springboot整合activeMQ系列之Topic
消息隊列中間件MQ簡介
消息隊列中間件是分佈式系統中重要的組件,主要解決應用耦合,異步消息,流量削鋒等問題。實現高性能,高可用,可伸縮和最終一致性架構。是大型分佈式系統不可缺少的中間件。消息形式支持點對點(Queue)和訂閱-發佈(Topic)。
MQ產品種類
kafka、RabbitMQ、RocketMQ、ActiveMQ等種類。
今天主要和大家講ActiveMQ系列之隊列(Queue)。
ActiveMQ是什麼?
ActiveMQ是消息隊列技術,爲解決高併發問題而生
ActiveMQ生產者消費者模型(生產者和消費者可以跨平臺、跨系統)
ActiveMQ支持如下兩種消息傳輸方式:
1.點對點模式(QUeue),生產者生產了一個消息,只能由一個消費者進行消費(支持持久化,事務、簽收機制)
2.發佈/訂閱模式(Topic),生產者生產了一個消息,可以由多個消費者進行消費,消費者要先訂閱(先啓動消費者,再啓動生產者,否則否則該消息就會成爲廢消息)
SpringBoot整合ActiveMQ
在整合前大家點這個地址下載自己喜歡的ActiveMQ版本ActiveMQ下載地址
這是我的下載的版本,安裝成功後,CMD(win +r)進入到解壓目錄下的bin目錄下,執行 activemq.bat start 啓動。
如果能成功訪問 http://localhost:8161/admin(用戶名和密碼默認爲admin),則啓動成功。準備工作搞完之後我們就開始進入正式工作。
1.分別建生產者(Provider)和消費者(Customer)兩個工程
兩個工程相同之處
pom文件
因爲是分佈式,所以博主建了生產者和消費者兩個工程,兩個pom文件一模一樣
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
</dependencies>
2.配置yml文件格式
兩個工程的yml幾乎都是一樣的,只有端口號不一致
server:
port: 8091
spring:
activemq:
broker-url: tcp://localhost:61616
user: admin
password: admin
jms:
pub-sub-domain: false #目的地是隊列(Queue)還是主題(Topic) fasle = queue true = topic
# 定義自己的隊列名字
myQueue: boot-activemq-queue
兩個工程不同之處
生產者工程目錄
BeanConfig文件
package com.example.provider.config;
import org.apache.activemq.command.ActiveMQQueue;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.stereotype.Component;
import javax.jms.Queue;
/**
* @Date 2019/10/31 14:22
* @Desc
*/
@Component
@EnableJms //自動配置jms
public class BeanConfig {
@Value("${myQueue}")
private String myQueue;
//定義存放消息的隊列
@Bean
public Queue queue() {
return new ActiveMQQueue(myQueue);
}
}
Queue_Produce(生產者)類
package com.example.provider.produce;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.jms.Queue;
import java.util.UUID;
/**
* @Desc 生產者
*/
@Component
public class Queue_Produce {
@Autowired
private JmsMessagingTemplate jmsMessagingTemplate;
@Autowired
private Queue queue;
/**
* 點一次發送一次
*/
public void produceMsg() {
jmsMessagingTemplate.convertAndSend(queue, "$$$$$$$:" + UUID.randomUUID().toString().substring(0, 7));
}
/**
* 間隔10秒鐘定投
*/
@Scheduled(fixedDelay = 10000)
public void produceMsgScheduled() {
jmsMessagingTemplate.convertAndSend(queue, "$$$$$$$:" + UUID.randomUUID().toString().substring(0, 7));
System.out.println("produceMsgScheduled send ok");
}
}
啓動類
package com.example.provider;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
}
測試用例
package com.example.provider;
import com.example.provider.produce.Queue_Produce;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import javax.annotation.Resource;
@SpringBootTest(classes = ProviderApplication.class)
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
public class ProviderApplicationTests {
@Resource
private Queue_Produce queue_produce;
@Test
public void testSend() {
queue_produce.produceMsgScheduled();
}
}
定時發送結果:
消費者工程目錄
Queue_Customer(消費者)類
package com.example.bootcustomer.customer;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;
import javax.jms.JMSException;
import javax.jms.TextMessage;
/**
* @Desc 消費者
*/
@Component
public class Queue_Customer {
@JmsListener(destination = "${myQueue}") //監聽
public void receive(TextMessage textMessage) throws JMSException {
System.out.println("消費者" + textMessage.getText());
}
}
啓動類
package com.example.bootcustomer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class BootCustomerApplication {
public static void main(String[] args) {
SpringApplication.run(BootCustomerApplication.class, args);
}
}
測試結果
圖中的數字可能不是很準確,因爲在操作的時候,程序還在運行,所以前後不一致,我設定的是10s發送一次消息。