(二)在項目中如何使用ActiveMQ的具體用法(一些常見的踩坑)?

(1)首先一般在項目中的使用無非不就是把消息發送到ActiveMQ中的消息隊列中去,先要考慮是使用點對點的模式,還是使用topic發佈訂閱的模式來進行發送的。然後就是結合自己的業務,看你放到ActiveMQ中的是什麼類型的數據,然後採用不同的Message類型

  1. TextMessage
  2. MapMessage
  3. BytesMessage(我這裏項目中採用的是字節數組類型的)
  4. StreamMessage
  5. ObjectMessage

(2)然後其實就是封裝send方法,當然你可以用Jmstemeplate這個模板類型來進行使用原生的API,但是我這裏是自己封裝的sendMessage()方法,封裝到ActiveMQService類中,用的時候直接注入ActiveMQService這個類就行了


/**
 * @FileName: ActiveMqService.java
 * @Description: ActiveMqService.java類說明
 * @Author: admin
 * @Date: 2019/5/31 11:56
 */
@Slf4j
@Service
public class ActiveMqServiceImpl implements ActiveMqService{


    @Value("${spring.activemq.broker-url}")
    private  String mBrokerURL;
    @Value("${spring.activemq.user}")
    private   String user;
    @Value("${spring.activemq.password}")
    private  String password;

    @Override
    public Boolean sendMessage(String destinationName, ActiveMqTask activeMqTaskData) {
        MessageProducer producer = null;
        Session session = null;
       try {
           session = getSession();
           Destination destination = session.createQueue(destinationName);
           log.info("發送到MQ的目的隊列爲:{}",destinationName);
           producer = session.createProducer(destination);
           BytesMessage message = session.createBytesMessage();
           byte[] data = objectToBytes(activeMqTaskData);
           message.writeBytes(data);
           producer.send(message);
           log.info("發送到:{}消息隊列中成功!",destinationName);
       }catch (Exception e){
           log.info("發送到:{}消息隊列異常失敗!",destinationName);
           return false;
       }finally {
           if(producer != null){
               try {
                   producer.close();
                   log.info("關閉生產者");
               } catch (JMSException e) {
                   e.printStackTrace();
               }
           }
           if(session != null){
               try {
                   session.close();
                   log.info("關閉session連接");
               } catch (JMSException e) {
                   e.printStackTrace();
               }
           }
       }
        return true;
    }

    /**
     * @Author: wangwei
     * @Description: 這個是用來封裝獲取session的方法
     * @Param:  * @Param: null
     * @Date: 2019-06-04
     */
    public  Session getSession(){
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(user,password,mBrokerURL);
        Connection connection = null;
        Session session = null;
        try {
            connection = connectionFactory.createConnection();
            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        } catch (JMSException e) {
            log.info("沒有成功連接到ActiveMQ的服務器");
            e.printStackTrace();
        }
        log.info("從connection獲取session成功!");
        return session;
    }

    /**
     * @Author: wangwei
     * @Description: 把消息對象轉爲byte數組進行傳輸
     * @Param:  * @Param: null
     * @Date: 2019-06-04
     */
    public  byte[] objectToBytes(ActiveMqTask activeMqTask) throws Exception {
        log.info("把任務名爲:{}的對象轉換爲byte數組",activeMqTask.getName());
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ObjectOutputStream sOut = new ObjectOutputStream(out);
        sOut.writeObject(activeMqTask);
        sOut.flush();
        byte[] bytes = out.toByteArray();
        return bytes;
    }

}

(3)封裝好sendMessage方法之後,就是在項目中具體怎麼去監聽一個ActiveMQ中的Queue或者Topic主題的事件了,這個就是監聽的時候使用到的方法

  /**
     * @Author: wangwei
     * @Description: 監聽任務進度更新的消息隊列
     * @Param: * @Param: null
     * @Date: 2019-06-04
     */
    @JmsListener(destination = "DX_MOBSEC_task_progress_queue")
    public void listerProgressQueueMessage(BytesMessage bytesMessage) {
         TaskProgressBO taskProgressBO = null;
        log.info("*****************************開始監聽DX_MOBSEC_task_progress_queue隊列中的任務*******************************");
        if (bytesMessage != null) {
            try {
                taskProgressBO = ActiveMqUtils.fromMessageToTaskProgress(bytesMessage);
                if (taskProgressBO != null) {
                    int effectResult = fastenProtectExtendMapper.updTaskProgressById(taskProgressBO);
                    if (effectResult > 0) {
                        log.info("更新任務:{}進度信息成功!", taskProgressBO.getId());
                    } else {
                        log.info("更新任務:{}進度信息失敗!", taskProgressBO.getId());
                    }
                }
            } catch (Exception e) {
                log.info("把BytesMessage轉爲實體的過程中失敗!");
            }
        } else {
            log.info("監聽到[DX_MOBSEC_task_progress_queue]的BytesMessage類型的信息爲NULL");
        }

    }

這個是需要把上面監聽到主題的數據內容給轉換成你想要的實體對象(因爲一般和業務結合的話,這個數據都是放在對象實體中的,因爲發送消息的時候使用到的Message類型是BytesMessage類型,所以這裏也需要把接收的Message對象轉爲實體)

  • 這裏有幾個坑需要注意一下:首先你得知道BytesMessage和TextMessage等等,他們都是繼承自Message對象,所以這裏的message其實就是指我們接受到的BytesMessage類型
  • 第一個坑就是發送數據使用到的XXXXMessage類型和接收到的Message類型必須要保持一致,不然是接收不到數據的,還會報錯
  • 第二個坑就是你的ActiveMQ的brokerUrl的地址是 tcp://10.0.0.203:61616這種的,而不是8161的這種端口,不然會報錯 javax.jms.JMSException: Unknown data type: 47
    /**
     * @Author: wangwei
     * @Description: 把消費到的Message信息通過byte[]字節數組過渡到TaskProgressBO對象
     * @Param:  * @Param: null
     * @Date: 2019-06-04
     */
    public static TaskProgressBO fromMessageToTaskProgress(Message message){
        try(ByteArrayOutputStream bos = new ByteArrayOutputStream()){
            byte buff[] = new byte[256];
            int length;
            while((length = ((BytesMessage)message).readBytes(buff)) > 0){
                bos.write(buff, 0, length);
            }
            return ActiveMqUtils.fromBytesToTaskProgress(bos.toByteArray());
        }catch (IOException e){
            e.printStackTrace();
        } catch (JMSException e) {
            e.printStackTrace();
        }
        return null;
    }

把傳輸過來的字節數組轉爲TaskProgressBO對象

    /**
     * @Author: wangwei
     * @Description: 把傳輸過來的字節數組轉爲TaskProgressBO對象
     * @Param:  * @Param: null
     * @Date: 2019-06-04
     */
    public static TaskProgressBO fromBytesToTaskProgress(byte[] bytes){
        try(ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes))){
            return (TaskProgressBO)ois.readObject();
        }catch (IOException | ClassNotFoundException e){
            e.printStackTrace();
        }
        return null;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章