• ActiveMq(二)


    1、概念

    JMS有两种消息通信模型,点对点模型(point to point)(p2p)和发布/订阅模型(pub/sub),ActiveMq实现了JMS接口,同样,ActiveMq也实现了这两种模型。 点对点模型规定了一个消息只能有一个接收者,而发布/订阅模型允许一个消息可以有多个消息接收者

    点对点模型

    当一个消息生产者产生一个消息时,会把消息放入一个队列(Queue)中,然后消息消费者从Queue中读取消息,如果同时有多个消费者读取消息,ActiveMq保证消息只会被一个消费者读取到,消费者读取到消息之后需要向ActiveMq发送一条确认信息,确认消息已经被接收,此时,队列(Queue)中的消息出队,整个流程就处理完了。

    2、几个重要的类

    > * ConnectionFactory:工厂类接口,通过这个工厂类接口就可以创建一个与ActiveMq的连接,即Connection。 > * Connection:连接,可以通过这个连接创建会话Session,连接默认是关闭的,需要显式调用Connection的start方法。 > * Session:会话,通过会话类可以创建生产者或消费者、创建队列Queue、创建消息对象。 > * MessageProducer:消息生产者,可将消息发送到队列中。 > * Queue:队列,存放消息的队列。 > * MessageConsumer:消费者,从队列中取出消息。 > * Message:消息接口,常用的实现类是TextMessage和ObjectMessage。

    3、三种消息确认机制

    > * Session.AUTO_ACKNOWLEDGE:自动确认,当消费接收到消息时,会自动的向ActiveMq发送收到消息确认 > * Session.CLIENT_ACKNOWLEDGE:消费者手动调用Message的acknowledge方法手动确认收到消息。发生在Session层面,当手动调用确认方法时,会把Session中所有已消费的消息都确认 > * Session.DUPS_OK_ACKNOWLEDGE:不必确认已收到消息。但它可能会引起消息的重复接收,但是降低了Session的开销(不需要再去ACKNOWLEDGE一次),所以只有客户端可以重复接收消息时,才可使用此模式

    4、生产者代码

    ``` package com.activemq;

    import javax.jms.Connection;
    import javax.jms.ConnectionFactory;
    import javax.jms.JMSException;
    import javax.jms.Message;
    import javax.jms.MessageProducer;
    import javax.jms.Queue;
    import javax.jms.Session;
    import javax.jms.TextMessage;

    import org.apache.activemq.ActiveMQConnectionFactory;

    public class Producer {
    public static void main(String[] args) throws JMSException {
    //通过tcp协议获取连接工厂
    ConnectionFactory factory = new ActiveMQConnectionFactory("tcp://server01:61616");

    	//通过连接工厂获取连接
    	Connection connection = factory.createConnection();
    	connection.start();//开启连接
    	
    	/**
    	 * 创建session,此处有两个参数
    	 * 	第一个布尔类型的参数表示是否开启事务
    	 *  第二个表示消息确认签收模式,此处为自动确认
    	 */
    	Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
    	
    	//创建消息队列
    	Queue queue = session.createQueue("queue");
    	
    	//创建消息生产者
    	MessageProducer producer = session.createProducer(queue);
        //producer.setDeliveryMode(DeliveryMode.PERSISTENT);
        //DeliveryMode.PERSISTENT:持久化(默认),当ActiveMq关闭时,队列中的消息会保存
        //DeliveryMode.NON_PERSISTENT:非持久化,当ActiveMq关闭时,队列中的消息会丢失
    	
    	//生产者发送5条消息
    	for(int i = 0 ; i < 5; i++){
    		Message message = session.createTextMessage("消息" + i);
    		producer.send(message);
    		TextMessage text = (TextMessage)message;
    		System.out.println("生产者发送消息:" + text.getText());
    	}
    }
    

    }

    启动生产者,看到控制台打印出5条记录:
    

    生产者发送消息:消息0
    生产者发送消息:消息1
    生产者发送消息:消息2
    生产者发送消息:消息3
    生产者发送消息:消息4

    再访问ActiveMq控制台 http://server01:8161,查看Queues中的消息数量
    ![](https://images2018.cnblogs.com/blog/1373276/201804/1373276-20180415010903949-884323074.png)
    
    此时看到Queues中已经多了5条消息,消费者数量为0
    > * Name:队列名称
    > * Number Of Pending Messages :等待被处理的消息数量
    > * Number Of Consumers :消费者数量
    > * Messages Enqueued :入队的消息数量
    > * Messages Dequeued:出队的消息数量
    
    <h1>5、消费者代码</h1>
    

    package com.activemq;

    import javax.jms.Connection;
    import javax.jms.ConnectionFactory;
    import javax.jms.JMSException;
    import javax.jms.Message;
    import javax.jms.MessageConsumer;
    import javax.jms.Queue;
    import javax.jms.Session;
    import javax.jms.TextMessage;

    import org.apache.activemq.ActiveMQConnectionFactory;

    public class Consumer {
    public static void main(String[] args) throws JMSException {
    //通过tcp协议获取连接工厂
    ConnectionFactory factory = new ActiveMQConnectionFactory("tcp://server01:61616");

    	//通过连接工厂获取连接
    	Connection connection = factory.createConnection();
    	connection.start();////开启连接
    	
    	/**
    	 * 创建session,此处有两个参数
    	 * 	第一个布尔类型的参数表示是否开启事务
    	 *  第二个表示消息确认签收模式,此处为自动签收
    	 */
    	Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
    	
    	//创建消息队列
    	Queue queue = session.createQueue("queue");
    	
    	//创建消费者
    	MessageConsumer consumer = session.createConsumer(queue);
    	
    	while(true){
    		Message message = consumer.receive();
    		if(message == null){
    			break;
    		}
    		TextMessage textMessage = (TextMessage)message;
    		System.out.println("消费者收到消息:" + textMessage.getText());
    	}
    }
    

    }

    启动消费者,看到Eclipse控制台收到5条记录,说明此时消费者已经收到消息了。
    

    消费者收到消息:消息0
    消费者收到消息:消息1
    消费者收到消息:消息2
    消费者收到消息:消息3
    消费者收到消息:消息4

    
    此时再看看ActiveMq控制台,待消费的消息数量已经为0,已经有一个消费者了,出队的消息数量也是5,说明消费者已经向ActiveMq发送确认收到消息的通知了,队列中的消息已经被消费完了。此时若再次启动消费者,Eclipse控制台不会再打印消息。
    ![](https://images2018.cnblogs.com/blog/1373276/201804/1373276-20180415012048914-1223879859.png)
    
    <h1>6、消费者监听模式</h1>
    消费者接收消息有两个方法,上面讲的方式一是调用receive方法来接收,第二种方式是注册监听器的方式来获取消息。
    创建两个消费者,分别监听在Queue上,当消费者产生消息放入Queue中时,两个消费者都会去接收消息,但是ActiveMq会保证一个消息只有一个消费者能收到。
    

    package com.activemq;

    import javax.jms.Connection;
    import javax.jms.ConnectionFactory;
    import javax.jms.JMSException;
    import javax.jms.Message;
    import javax.jms.MessageConsumer;
    import javax.jms.MessageListener;
    import javax.jms.Queue;
    import javax.jms.Session;
    import javax.jms.TextMessage;

    import org.apache.activemq.ActiveMQConnectionFactory;

    public class ConsumerListener {
    public static void main(String[] args) throws JMSException {
    //通过tcp协议获取连接工厂
    ConnectionFactory factory = new ActiveMQConnectionFactory("tcp://server01:61616");

    	//通过连接工厂获取连接
    	Connection connection = factory.createConnection();
    	connection.start();////开启连接
    	
    	/**
    	 * 创建session,此处有两个参数
    	 * 	第一个布尔类型的参数表示是否开启事务
    	 *  第二个表示消息确认签收模式,此处为自动签收
    	 */
    	Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
    	
    	//创建消息队列
    	Queue queue = session.createQueue("queue");
    	
    	//创建消费者
    	MessageConsumer consumer = session.createConsumer(queue);
    
    	//监听模式
    	consumer.setMessageListener(new MessageListener() {
    		
    		public void onMessage(Message message) {
    			TextMessage textMessage = (TextMessage)message;
    			try {
    				System.out.println("消费者一收到消息:" + textMessage.getText());
    			} catch (JMSException e) {
    				e.printStackTrace();
    			}
    		}
    	});
    	
    	MessageConsumer consumer1 = session.createConsumer(queue);
    	consumer1.setMessageListener(new MessageListener() {
    		public void onMessage(Message message) {
    			TextMessage textMessage = (TextMessage)message;
    			try {
    				System.out.println("消费者二收到消息:" + textMessage.getText());
    			} catch (JMSException e) {
    				e.printStackTrace();
    			}
    		}
    	});
    }
    

    }

    先启动消费者程序,此时会看到ActiveMq控制台已经存在两个消费者了,但是还没有消息。
    ![](https://images2018.cnblogs.com/blog/1373276/201804/1373276-20180415013155244-1046460892.png)
    
    再启动生产者,会看到Eclipse控制台打印出5条记录,表明5个消息分别被不同的消费者接收到了,也就是同一个消息只能被一个消费者接收
    

    消费者一收到消息:消息0
    消费者二收到消息:消息1
    消费者一收到消息:消息2
    消费者二收到消息:消息3
    消费者一收到消息:消息4

    此时再看一下ActiveMq控制台,待处理的消息已经为0,入队和出队的消息记录都是5。
    ![](https://images2018.cnblogs.com/blog/1373276/201804/1373276-20180415013445828-567862121.png)
  • 相关阅读:
    AppiumForWin安装
    AppiumForMac安装2
    AppiumForMac安装1
    在MacOS安装puppeteer
    puppeteerExamples
    为什么总有target=_blank?
    Canvas 与 SVG
    HTML5+CSS3兼容收藏夹
    html 5 读取本地文件API
    【Web Audio API】 — 那些年的 web audio
  • 原文地址:https://www.cnblogs.com/lmj612/p/8838764.html
Copyright © 2020-2023  润新知