springboot activemq stomp實現隊列消息發送/消費

1.添加maven依賴

   <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-activemq</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.activemq</groupId>
            <artifactId>activemq-pool</artifactId>
            <version>5.14.5</version>
        </dependency>
        <dependency>
            <groupId>org.apache.activemq</groupId>
            <artifactId>activemq-stomp</artifactId>
            <version>5.14.5</version>
        </dependency>
    </dependencies>

2.application.properties

#activemq
activemq.host=192.168.1.23
activemq.port=61613
activemq.user=admin
activemq.password=admin
spring.activemq.pool.enabled=true
spring.activemq.pool.max-connections=10
#默認情況下activemq提供的是queue模式,若要使用topic模式需要配置下面配置
spring.jms.pub-sub-domain=true

3.生產者 JmsProducer

package com.yangfeng.msservice.service;

import org.apache.activemq.transport.stomp.Stomp;
import org.apache.activemq.transport.stomp.StompConnection;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.UUID;

/**
 * 消息生產者
 *
 * @author yangfeng
 * @date 2020-03-09
 */
@Component
public class JmsProducer {

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

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

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

    @Value("${activemq.port}")
    private Integer port;


    public StompConnection connectionFactory() throws Exception {
        StompConnection conn = new StompConnection();
        conn.open(host, port);
        conn.connect(userName, password);
        return conn;
    }

    /**
     * 發送JMS消息
     *
     * @throws Exception exception
     */
    public void sendMessage(String queueName, String message)
            throws Exception {
        StompConnection stompConnection = connectionFactory();
        String tx = UUID.randomUUID().toString().replaceAll("-", "");
        HashMap<String, String> headers = new HashMap<>();
        headers.put(Stomp.Headers.Send.PERSISTENT, "true");
        stompConnection.begin(tx);
        stompConnection.send(queueName, message, tx, headers);
        stompConnection.commit(tx);
        stompConnection.disconnect();
    }

}

4.消費者JmsConsumer

import com.alibaba.fastjson.JSONException;
import com.yangfeng.msservice.service.JmsProducer;
import com.yangfeng.service.IAllocationResultService;
import org.apache.activemq.transport.stomp.StompConnection;
import org.apache.activemq.transport.stomp.StompFrame;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.net.SocketTimeoutException;
import java.util.Map;

/**
 * 從消息隊列中消費
 *
 * @author yangfeng
 * @date 2020-04-09
 */

@Component
public class JmsConsumer implements ApplicationListener<ContextRefreshedEvent> {
    private static Logger LOG = LoggerFactory.getLogger(FlightAssignparkConsumer.class);

    @Resource
    private IResultService resultService;

    @Resource
    public JmsProducer jmsProducer;

    private static final String QUEUE_FLIGHT_ASSIGNPARK = "flight_assignpark";

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        try {
            consumeMsg(QUEUE_FLIGHT_ASSIGNPARK);
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
        }
    }


    /**
     * 從mq中消費消息
     *
     * @param queueName
     * @throws Exception
     */
    public void consumeMsg(String queueName) throws Exception {
        LOG.info("*********從消息隊列中獲取機位分配結果、靠橋率結果統計數據**************");
        new Thread(() -> {
            while (true) {
                StompFrame frame;
                String messageId = "";
                StompConnection stompConnection = null;
                try {
                    String ack = "client";
                    stompConnection = jmsProducer.connectionFactory();
                    stompConnection.subscribe(queueName, ack);
                    stompConnection.keepAlive();
                    // 注意,如果沒有接收到消息,
                    // 這個消費者線程會停在這裏,直到本次等待超時
                    long waitTimeOut = 30000;
                    frame = stompConnection.receive(waitTimeOut);
                    Map<String, String> headers = frame.getHeaders();
                    messageId = headers.get("message-id");
                    LOG.info("消息id:{}", messageId);
                    //具體的業務處理......
                    resultService.saveResult(frame.getBody());
                    // 在ack是client標記的情況下,確認消息
                    if ("client".equals(ack)) {
                        stompConnection.ack(messageId);
                    }
                } catch (SocketTimeoutException e) {
                    LOG.error(e.getMessage());
                    continue;
                } catch (JSONException ex) {
                    LOG.error("message_id:{},數據異常:{}", messageId, ex.getMessage());
                    continue;
                } catch (Exception e) {
                    LOG.error(e.getMessage());
                    continue;
                } finally {
                    try {
                        stompConnection.disconnect();
                    } catch (Exception e) {
                        LOG.error(e.getMessage());
                    }
                }
            }
        }).start();
    }
}

 

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