ActiveMQ學習2-消息類型\事務消息\確認機制\應用場景\消息過濾\監聽器接收


  

11 ActiveMQ消息類型

  1、TextMessage 文本消息:攜帶一個java.lang.String作爲有效數據(負載)的消息,可用於字符串類型的信息交換;
  2、ObjectMessage 對象消息:攜帶一個可以序列化的Java對象作爲有效負載的消息,可用於Java對象類型的信息交換;
  3、MapMessage 映射消息:攜帶一組鍵值對的數據作爲有效負載的消息,有效數據值必須是Java原始數據類型(或者它們的包裝類)及String。即:byte, short, int, long, float, double, char, boolean, String
  4、BytesMessage 字節消息 :攜帶一組原始數據類型的字節流作爲有效負載的消息;
  5、StreamMessage 流消息:攜帶一個原始數據類型流作爲有效負載的消息,它保持了寫入流時的數據類型,寫入什麼類型,則讀取也需要是相同的類型;

public class QueueSender {
    public static final String BROKER_URL = "tcp://localhost:61616";
    public static final String DESTINATION = "myQueue";

    public static void main(String[] args) throws JMSException {
        //1、創建連接工廠
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URL);
        Connection connection = null;
        Session session = null;
        MessageProducer producer = null;
        try {
            //2、創建一個連接
            connection = connectionFactory.createConnection();
            //3、創建一個Session,第一個參數表示是否爲事務消息,第二個參數表示消息確認方式
            session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
            //4、創建消息
            Order order = new Order();
            order.setOrderId("123");
            order.setName("訂單");
            order.setPrice("123.22");
            Message message = session.createObjectMessage(order);
            //5、消息目的地
            Destination destination = session.createQueue(DESTINATION);
            //6、消息生產者
            producer = session.createProducer(destination);
            //7、發送消息
            producer.send(message);
        } catch (Exception e) {
        } finally {
            connection.close();
            producer.close();
            session.close();
        }
    }
}
ublic class QueueReceiver {
    public static final String BROKER_URL = "tcp://localhost:61616";
    public static final String DESTINATION = "myQueue";

    public static void main(String[] args) throws JMSException {
        //1、創建連接工廠
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URL);

        Connection connection = null;
        Session session = null;
        MessageConsumer messageConsumer = null;
        try {
            List<String> list = new ArrayList<>();
            list.add("java.lang");
            list.add("com.jms.type");
            //必須設置對象中所有的字段所在的類是受信任的,對象類必須實現序列化接口
            ((ActiveMQConnectionFactory) connectionFactory).setTrustedPackages(list);
            //2、創建一個連接
            connection = connectionFactory.createConnection();
            //接收消息多一個步驟:把連接啓動
            connection.start();
            //3、創建一個Session,第一個參數表示是否爲事務消息,第二個參數表示消息確認方式
            session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
            //4、創建消息
            Message message = session.createObjectMessage("Hello,ActiveMQ");
            //5、消息目的地
            Destination destination = session.createQueue(DESTINATION);
            //6、消息消費者
            messageConsumer = session.createConsumer(destination);
            //7、接收消息:receive方法是一個阻塞方法,它會一直等待,直到接收到消息
            //   receive(Long 超時毫秒數) receiveNoWait()不等待
            Message receiveMessage = messageConsumer.receive();

            if (receiveMessage instanceof TextMessage) {
                String text = ((TextMessage) message).getText();
                System.out.println("接收到的消息爲:" + text);
            } else if (receiveMessage instanceof ObjectMessage) {
                Order order = (Order) ((ObjectMessage) receiveMessage).getObject();
                System.out.println(order.getOrderId());
                System.out.println(order.getName());
                System.out.println(order.getPrice());
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            connection.close();
            messageConsumer.close();
            session.close();
        }
    }
}
123
訂單
123.22

Process finished with exit code 0

12 ActiveMQ事務消息和非事務消息

消息分爲事務消息和非事務消息:
1、事務消息:創建會話Session使用transacted=true
connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
2、非事務消息:創建會話Session使用transacted=false
connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);

事務消息必須在發送和接收完消息後顯式地調用session.commit();
事務性消息,不管設置何種消息確認模式,都會自動被確認;
public class QueueSender {
    public static final String BROKER_URL = "tcp://localhost:61616";
    public static final String DESTINATION = "myQueue";

    public static void main(String[] args) throws JMSException {
        //1、創建連接工廠
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URL);
        Connection connection = null;
        Session session = null;
        MessageProducer producer = null;
        try {
            //2、創建一個連接
            connection = connectionFactory.createConnection();
            //3、創建一個Session,第一個參數表示是否爲事務消息,第二個參數表示消息確認方式
            session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
            //4、創建消息
            Message message = session.createTextMessage("Hello,ActiveMQ");
            //5、消息目的地
            Destination destination = session.createQueue(DESTINATION);
            //6、消息生產者
            producer = session.createProducer(destination);
            //7、發送消息
            producer.send(message);
            //8、session會話需要提交事務,如果不提交消息不能發出,確認方式對事務型消息不起作用
            session.commit();
        } catch (Exception e) {
        } finally {
            producer.close();
            session.close();
            connection.close();
        }
    }
}
public class QueueReceiver {
    public static final String BROKER_URL = "tcp://localhost:61616";
    public static final String DESTINATION = "myQueue";

    public static void main(String[] args) throws JMSException {
        //1、創建連接工廠
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URL);
        Connection connection = null;
        Session session = null;
        MessageConsumer messageConsumer = null;
        try {
            //2、創建一個連接
            connection = connectionFactory.createConnection();
            //接收消息多一個步驟:把連接啓動
            connection.start();
            //3、創建一個Session,第一個參數表示是否爲事務消息,第二個參數表示消息確認方式
            session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
            //4、創建消息
            Message message = session.createTextMessage("Hello,ActiveMQ");
            //5、消息目的地
            Destination destination = session.createQueue(DESTINATION);
            //6、消息消費者
            messageConsumer = session.createConsumer(destination);
            //7、接收消息:receive方法是一個阻塞方法,它會一直等待,直到接收到消息
            //   receive(Long 超時毫秒數) receiveNoWait()不等待
            Message receiveMessage = messageConsumer.receive();
            //8、會話提交事務,如果不提交,消息不會銷燬,會導致重複接收
            session.commit();
            if (receiveMessage instanceof TextMessage) {
                String text = ((TextMessage) message).getText();
                System.out.println("接收到的消息爲:" + text);
            }
        } catch (Exception e) {
        } finally {
            messageConsumer.close();
            session.close();
            connection.close();
        }
    }
}

13 ActiveMQ消息確認機制

消息的成功消費通常包含三個階段:

(1)、客戶接收消息;
(2)、客戶處理消息;
(3)、消息被確認;

(1)、Session.AUTO_ACKNOWLEDGE;客戶(消費者)成功從receive方法返回時,或者從MessageListener.onMessage方法成功返回時,會話自動確認消息。
(2)、Session.CLIENT_ACKNOWLEDGE;客戶通過顯式調用消息的acknowledge方法確認消息。
(3)、Session. DUPS_OK_ACKNOWLEDGE ;不是必須確認,是一種“懶散的”消息確認,消息可能會重複發送,在第二次重新傳送消息時,消息頭的JMSRedelivered會被置爲true標識當前消息已經傳送過一次,客戶端需要進行消息的重複處理控制。
(4)、 Session.SESSION_TRANSACTED;事務提交併確認。 配合事務消息的
在這裏插入圖片描述

注意:
發送者如果使用AUTO_ACKNOWLEDGE機制,接收者使用CLIENT_AACKNOWLEDGE機制,
以接收者爲準。如果接收者沒有手動接收,服務端的消息不會銷燬。

14 ActiveMQ消息持久化

//設置發送的消息是否需要持久化
messageProducer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);//不持久化
//持久化的,activemq發送消息默認都是持久化的
messageProducer.setDeliveryMode(DeliveryMode.PERSISTENT);

15 MQ技術的應用場景

1、異步處理
  使用dubbo是同步的,A調用B,B馬上能返回結果,調用和被調用是在同一個線程完成的,稱爲同步,而A調用MQ只是把請求放在消息中,等待B從消息隊列中去取,然後處理將結果放在MQ中,A再過來拿結果。是一個異步的過程。
2、流量削峯
  當有大量請求併發訪問時,可以先返回一個成功的結果,然後使用MQ異步進行處理,比如秒殺時下單,將訂單消息發送到MQ中,再慢慢消費,插入到訂單表中。
3、系統解耦

16 ActiveMQ消息過濾

  ActiveMQ提供了一種機制,可根據消息選擇器中的標準來執行消息過濾,只接收符合過濾標準的消息;生產者可在消息中放入特有的標誌,而消費者使用基於這些特定的標誌來接收消息;

1、發送消息放入特殊標誌:message.setStringProperty(name, value);
2、接收消息使用基於特殊標誌的消息選擇器:
MessageConsumer createConsumer(Destination destination, String messageSelector);
3、消息選擇器是一個字符串,語法與數據庫的SQL相似,相當於SQL語句where條件後面的內容;
public class QueueSender {
    public static final String BROKER_URL = "tcp://localhost:61616";
    public static final String DESTINATION = "myQueue";

    public static void main(String[] args) throws JMSException {
        //1、創建連接工廠
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URL);
        Connection connection = null;
        Session session = null;
        MessageProducer producer = null;
        try {
            //2、創建一個連接
            connection = connectionFactory.createConnection();
            //3、創建一個Session,第一個參數表示是否爲事務消息,第二個參數表示消息確認方式
            session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
            //4、創建消息
            Message message = session.createTextMessage("Hello,ActiveMQ");
            //5、消息目的地
            Destination destination = session.createQueue(DESTINATION);
            //6、消息生產者
            producer = session.createProducer(destination);

            //添加消息標誌
            message.setIntProperty("age",20);
            message.setStringProperty("name","zhangsan");

            //7、發送消息
            producer.send(message);
        } catch (Exception e) {
        } finally {
            producer.close();
            session.close();
            connection.close();
        }
    }
}
public class QueueReceiver {
    public static final String BROKER_URL = "tcp://localhost:61616";
    public static final String DESTINATION = "myQueue";

    public static void main(String[] args) throws JMSException {
        //1、創建連接工廠
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URL);
        Connection connection = null;
        Session session = null;
        MessageConsumer messageConsumer = null;
        try {
            //2、創建一個連接
            connection = connectionFactory.createConnection();
            //接收消息多一個步驟:把連接啓動
            connection.start();
            //3、創建一個Session,第一個參數表示是否爲事務消息,第二個參數表示消息確認方式
            session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
            //4、創建消息
            Message message = session.createTextMessage("Hello,ActiveMQ");
            //5、消息目的地
            Destination destination = session.createQueue(DESTINATION);

            //定一個選擇器
            String selector = "age = 20 and name = 'zhangsan'";

            //6、消息消費者
            messageConsumer = session.createConsumer(destination,selector);
            //7、接收消息:receive方法是一個阻塞方法,它會一直等待,直到接收到消息
            //   receive(Long 超時毫秒數) receiveNoWait()不等待
            Message receiveMessage = messageConsumer.receive();

            if (receiveMessage instanceof TextMessage) {
                String text = ((TextMessage) message).getText();
                System.out.println("接收到的消息爲:" + text);
            }
        } catch (Exception e) {
        } finally {
            messageConsumer.close();
            session.close();
            connection.close();
        }
    }
}

17 ActiveMQ接收消息方式

1、同步接收
	receive()方法接收消息叫同步接收;
	一個線程在工作,接收到消息後,執行結束
	每次只能接收一個消息
	如果想不斷地接收消息,那麼就需要寫一個while true循環
2、異步接收
	使用監聽器接收消息,這種接收方式叫異步接收
	兩個線程在工作,一個負責接收消息,一個負責處理消息
	可以實現不間斷地接收消息,7*24接收消息(服務沒有宕機的情況下)
注意:
	在同一個consumer中,我們不能同時使用這2種接收方式;
	比如在使用listener的情況下,當調用receive()方法將會獲得一個Exception;
public class QueueReceiver {
    public static final String BROKER_URL = "tcp://localhost:61616";
    public static final String DESTINATION = "myQueue";

    public static void main(String[] args) throws JMSException {
        //1、創建連接工廠
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URL);
        Connection connection = null;
        Session session = null;
        MessageConsumer messageConsumer = null;
        try {
            //2、創建一個連接
            connection = connectionFactory.createConnection();
            //接收消息多一個步驟:把連接啓動
            connection.start();
            //3、創建一個Session,第一個參數表示是否爲事務消息,第二個參數表示消息確認方式
            session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
            //4、創建消息
            Message message = session.createTextMessage("Hello,ActiveMQ");
            //5、消息目的地
            Destination destination = session.createQueue(DESTINATION);
            //6、消息消費者
            messageConsumer = session.createConsumer(destination);

            messageConsumer.setMessageListener(new MessageListener() {

                //監聽器監聽到消息後,主動回調onMessage方法
                @Override
                public void onMessage(Message message) {
                    if (message instanceof TextMessage) {
                        String text = null;
                        try {
                            text = ((TextMessage) message).getText();
                        } catch (JMSException e) {
                            e.printStackTrace();
                        }
                        //省略進行業務邏輯的處理,插入數據庫,更新狀態等
                        System.out.println("接收到的消息爲:" + text);
                    }
                }
            });

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