消息类型\事务消息\确认机制\应用场景\消息过滤\监听器接收

  • 11 ActiveMQ消息类型
  • 12 ActiveMQ事务消息和非事务消息
  • 13 ActiveMQ消息确认机制
  • 14 ActiveMQ消息持久化
  • 15 MQ技术的应用场景
  • 16 ActiveMQ消息过滤
  • 17 ActiveMQ接收消息方式



  

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;事务提交并确认。 配合事务消息的

activeMQ topic消息 客户端负载均衡 activemq消息类型_AcitveMq消息过滤

注意:
发送者如果使用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) {
        }
    }
}