SpringBoot整合activemq實現P2P,pub/sub,activemq默認的持久化kahadb

一.ActiveMQ的安裝啓動

下載路徑:http://archive.apache.org/dist/activemq

下載文件後解壓在bin目錄下使用cmd指令執行activemq.bat start啓動,在瀏覽器輸入http://localhost:8161/admin(用戶名和密碼默認爲admin)

 

tips:8161是後臺管理系統,61616是給java用的tcp端口。

 

 

解壓縮後在文件的bin目錄下執行cmd指令:

activemq.bat start

執行成功如圖:

 

二.springboot整合ActiveMq

項目已上傳gitee:

https://gitee.com/gangye/springboot_activemq

1.項目結構圖,建立springboot項目,引入pom依賴

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-activemq</artifactId>
        <version>1.5.0.RELEASE</version>
    </dependency>
    <!-- 消息隊列連接池 -->
    <dependency>
        <groupId>org.apache.activemq</groupId>
        <artifactId>activemq-pool</artifactId>
        <version>5.15.0</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
</dependencies>

 

 

2.在生產者和消費者定義配置文件

#生產者的服務的端口號

server.port=7001



spring.activemq.broker-url=tcp://localhost:61616

spring.activemq.user=admin

spring.activemq.password=admin

#在考慮結束之前等待的時間

spring.activemq.close-timeout=15s

# 默認代理URL是否應該在內存中。如果指定了顯式代理,則忽略此值。

spring.activemq.in-memory=true

# 是否在回滾回滾消息之前停止消息傳遞。這意味着當啓用此命令時,消息順序不會被保留。

spring.activemq.non-blocking-redelivery=false

# 等待消息發送響應的時間。設置爲0等待永遠。

spring.activemq.send-timeout: 0

spring.activemq.queue-name: active.queue

spring.activemq.topic-name: active.topic.name.model



spring.activemq.pool.enabled=true

#連接池最大連接數

spring.activemq.pool.max-connections=10

#空閒的連接過期時間,默認爲10秒

spring.activemq.pool.idle-timeout=30s

#消息模式 true:廣播(Topic),false:隊列(Queue),默認時false,若要使用topic模式需要配置下面配置,可以再代碼中自定義配置

#spring.jms.pub-sub-domain=true

# 是否信任所有包

#spring.activemq.packages.trust-all=

# 要信任的特定包的逗號分隔列表(當不信任所有包時)

#spring.activemq.packages.trusted=

# 當連接請求和池滿時是否阻塞。設置false會拋“JMSException異常”。

#spring.activemq.pool.block-if-full=true

# 如果池仍然滿,則在拋出異常前阻塞時間。

#spring.activemq.pool.block-if-full-timeout=-1ms

# 是否在啓動時創建連接。可以在啓動時用於加熱池。

#spring.activemq.pool.create-connection-on-startup=true

# 是否用Pooledconnectionfactory代替普通的ConnectionFactory。

#spring.activemq.pool.enabled=false

# 連接過期超時。

#spring.activemq.pool.expiry-timeout=0ms

# 連接空閒超時

#spring.activemq.pool.idle-timeout=30s

# 連接池最大連接數

#spring.activemq.pool.max-connections=1

# 每個連接的有效會話的最大數目。

#spring.activemq.pool.maximum-active-session-per-connection=500

# 當有"JMSException"時嘗試重新連接

#spring.activemq.pool.reconnect-on-exception=true

# 在空閒連接清除線程之間運行的時間。當爲負數時,沒有空閒連接驅逐線程運行。

#spring.activemq.pool.time-between-expiration-check=-1ms

# 是否只使用一個MessageProducer

#spring.activemq.pool.use-anonymous-producers=trues

3.生產者啓動類

 

4.在生產者項目和消費者項目分別編寫BeanConfig.java自定義配置類

/**
 * @Classname BeanConfig
 * @Description 初始化和配置 ActiveMQ 的連接
 * @Date 2020/6/8 17:29
 * @Created by gangye
 */
@Configuration
public class BeanConfig {
    @Value("${spring.activemq.broker-url}")
    private String brokerUrl;

    @Value("${spring.activemq.user}")
    private String username;

    @Value("${spring.activemq.password}")
    private String password;

    @Value("${spring.activemq.queue-name}")
    private String queueName;

    @Value("${spring.activemq.topic-name}")
    private String topicName;

    @Bean(name = "queue")
    public Queue queue(){
        return new ActiveMQQueue(queueName);
    }

    @Bean(name = "topic")
    public Topic topic(){
        return new ActiveMQTopic(topicName);
    }

    @Bean
    public ConnectionFactory connectionFactory(){
        return new ActiveMQConnectionFactory(username,password,brokerUrl);
    }

    @Bean
    public JmsMessagingTemplate jmsMessagingTemplate(){
        return new JmsMessagingTemplate(connectionFactory());
    }

    //在Queue模式中,對消息的監聽需要對containerFactory進行配置
    @Bean("queueListener")
    public JmsListenerContainerFactory<?> queueJmsListenerContainerFactory(ConnectionFactory connectionFactory){
        SimpleJmsListenerContainerFactory factory = new SimpleJmsListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setPubSubDomain(false);
        return factory;
    }

    //在Topic模式中,對消息的監聽需要對containerFactory進行配置
    @Bean("topicListener")
    public JmsListenerContainerFactory<?> topicJmsListenerContainerFactory(ConnectionFactory connectionFactory){
        SimpleJmsListenerContainerFactory factory = new SimpleJmsListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setPubSubDomain(true);
        return factory;
    }
}

 

5.編寫生產者的路由

@RestController
@RequestMapping(value = "/sendMessage")
public class ProviderController {
    @Autowired
    private JmsMessagingTemplate jmsMessagingTemplate;

    @Autowired
    private Queue queue;

    @Autowired
    private Topic topic;

    //發送消息,destination是發送到的隊列,message是待發送的消息
    private void sendMessage (Destination destination,final String message){
        jmsMessagingTemplate.convertAndSend(destination,message);
    }

    @PostMapping(value = "/queue/send")
    public String sendQueue(@RequestBody String text){
        sendMessage(this.queue,text);
        return "success";
    }

    @PostMapping(value = "/topic/send")
    public String sendTopic(@RequestBody String text){
        sendMessage(this.topic,text);
        return "success";
    }
}

 

6.在消費者中分別編寫queue模式以及topic模式的消費者

@Slf4j
@Component
public class QueueConsumerListener {
    //queue模式的消費者
    @JmsListener(destination = "${spring.activemq.queue-name}",containerFactory = "queueListener")
    public void readActiveQueue(String message){
        log.info("queue接受到消息內容:{}",message);
        System.out.println("queue接受的消息內容:"+message);
    }
}
@Slf4j
@Component
public class TopicConsumerListener {
    //topic模式的消費者
    @JmsListener(destination = "${spring.activemq.topic-name}",containerFactory = "topicListener")
    public void readActiveTopic(String message){
        log.info("topic接受到消息內容:{}",message);
        System.out.println("topic接受的消息內容:"+message);
    }
}

7.啓動生產者和消費者項目

使用psotman生產一條數據(queue)

 

查看消費者的日誌:

 

同時在activemq的管理端可以看到數據:

 

再使用生產者生產一條topic的消息

 

消費者的日誌及控制檯:

 

activemq的瀏覽器管理端:

 

三.持久化queue以及topic的操作

1.queue模式下開啓持久化

在生產者項目中添加這三行代碼

jmsTemplate.setDeliveryMode(2);
jmsTemplate.setExplicitQosEnabled(true);
jmsTemplate.setDeliveryPersistent(true);

 

2. 開啓主題持久化,配置類添加如下配置

//topic持久化使用的配置
@Bean(name = "topicListenerFactory")
public JmsListenerContainerFactory<DefaultMessageListenerContainer> topicListenerFactory(ConnectionFactory connectionFactory){
    DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
    factory.setSubscriptionDurable(true);// Set this to "true" to register a durable subscription,
    factory.setClientId("B");
    factory.setConnectionFactory(connectionFactory);
    return factory;
}

在消費者服務中:

//topic模式持久化
//消費者消費  destination隊列或者主題的名字
@JmsListener(destination = "${spring.activemq.topic-name}",containerFactory = "topicListenerFactory")
public void getMessage(TextMessage message, Session session) throws JMSException {
    log.info("消費者獲取到消息:"+message.getText());
}

這裏需要注意,主題的數據不會被消費,會被一直記錄下來,只能手動清除

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章