ActiveMQ的消息接收的问题(使用MessageListener)

villagehead 2013-06-14 04:00:56
在用ActiveMQ的MessageListener消息接收模式的时候,
我setMessageListener了本类,也就是consumer.setMessageListener(this);
然后,又在onMessage里面做了相应消息的处理。
然后提交了session。

我的问题是,
只关闭这个session,
这个class会结束并进入回收环节吗?

因为我这个类是一个TimerTask,
每隔一段时间启动一次来接收消息,
我想知道的是,如果第一次收到消息,调用了onMessage方法以后,
这个任务会不会就彻底结束了?

还是
不只要在onMessage方法里关闭session对象,
还要在里面关闭Connection对象,
这个任务才算完全的执行完。


如果不关,这个链接会不会一直存在,直到整个程序停止,或者ActiveMQ停止了,
才能结束?
这样的话,我接受的内容如果一多,那还不把内存撑暴啊?

PS:
打字的时候突然想到,
这个conn如果设置成static的,
取得conn也在static块里面,
是不是再执行这个任务的时候,
就不用每次都建立链接,
而直接从这个链接里取得session,然后再取consumer就可以了呢?
这个相当于长链接的conn会不会成为系统里的结石??

贴些代码
就是红色的XXXX这里要不要关掉那个conn对象。

import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.MessageProducer;
import javax.jms.Session;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
*
* @author
*
* 1. 数据接收线程监听ActiveMQ队列,并读取消息。。
*
*/
public class ReceiveTask extends TimerTask implements MessageListener {

private static final Log log = LogFactory.getLog(ReceiveTask.class);

private Session session;

private javax.jms.Connection conn = null ;

private MessageConsumer consumer = null;

/**
*
*/
public void run() {

//开始监听设置
try {

log.info("数据消费者开始启动...");

conn = MQConnection.getJmsConnection();

conn.start();

// 得到session
session = conn.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);

// 通过本地节点的接收队列名,监听需要监听的队列名
Destination destination = session.createQueue("QueueName");

MessageProducer replyProducer = session.createProducer(null);

// 设置传送模式为“非持久性消息”
replyProducer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);

// 初始化消息的消费者
consumer = session.createConsumer(destination);

// 设置监听器,有消息来得时候回调MessageListener.onMessage方法
consumer.setMessageListener(this);

log.info("数据消费者启动完成...");

} catch (Exception e) {
log.info("数据消费者启动异常...");
}
}

/**
* MessageListener.onMessage
*/
public void onMessage(Message message) {

try {
// 各种处理,略

//提交session
session.commit();
}
} catch (Exception e) {

MQConnection.rollback(session);

MQUtil.log(e, log);
} finally {
// XXXX
}

}
}
...全文
29303 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
sd4324530 2013-12-26
  • 打赏
  • 举报
回复

<bean id="connectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory"
		destroy-method="stop">
		<property name="connectionFactory">
			<bean class="org.apache.activemq.ActiveMQConnectionFactory">
				<property name="brokerURL"
					value="failover:(tcp://10.60.60.107:61616?wireFormat.maxInactivityDuration=0)&maxReconnectDelay=1000" />
			</bean>
		</property>
		<!-- 连接数 -->
		<property name="maxConnections" value="1" />
		<!-- Session总数 -->
		<property name="maximumActive" value="500" />
	</bean>
	<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
		<property name="connectionFactory" ref="connectionFactory" />
		<!-- 
		<property name="defaultDestination" ref="oamTmpTopic" />
		 -->
		<property name="explicitQosEnabled" value="true" />
		<!-- 1为非持久化,2为持久化 -->
		<property name="deliveryMode" value="1" />
	</bean>
sd4324530 2013-12-26
  • 打赏
  • 举报
回复
con,和session都可以交给spring去管,con只有1个,session用对象池
yuyezitong 2013-12-25
  • 打赏
  • 举报
回复
请问对于activemq接受消息的方法:Receive()和Listener,有什么区别啊?是不是读取了一条消息就会关闭,还是能读取所有的匹配消息啊?对于Topic和Queue两种类型,读取消息,有什么不同啊?我就是创建了一个Topic的持久的订阅者,打开以后,程序到Receive()方法,那就一直停在那里。。Listener方法也一样,他们为什么不能收到离线是的消息呢?只能收到在线消息。。。
daydayup369 2013-11-25
  • 打赏
  • 举报
回复
我也想求解,目前也遇到这样的疑惑
villagehead 2013-06-20
  • 打赏
  • 举报
回复
来人帮帮忙啊~~~
villagehead 2013-06-18
  • 打赏
  • 举报
回复
我顶!!!! 别沉了啊~~~
villagehead 2013-06-17
  • 打赏
  • 举报
回复
感谢1楼的回复和2楼的...捧场,呵呵 不过,我还是有些不太明白。 首先,你说的服务端和客户端, 因为你说服务端实现onMessage接口, 所以我是不是可以理解为 你说的服务端算是消息的接收端, 而客户端是消息的发送端 那么, 也就是说, 一旦消息接收端的程序开始运行,开始接收消息, 就始终要开着这个链接,准备消息发送端随时发来的消息? 但是,我这个工程里, 消息接收端是一个任务(task)对象, 一段时间内只处理一部分发送过来的消息。 (接收固定数量的消息的方法我在ActiveMQ自带的例子里看到过,方法也了解) 按照上面我"一旦"的逻辑, 是不是这个任务在第一次执行的时候就一直执行下去了? 而不会真正的推出, 而受限于jdk的timer的运行机制,(第一个task运行完了,才安排第2个task运行) 这个任务(task)就是不是始终不会被第二次执行了? 比如: 这个任务在第一次被执行的时候, 取得一个consumer->设定了onMessage->被触发后, 这个任务就一直等待发送端发送过来的消息, 而因为它始终是处于活态(忘了什么词了,反正就是一直存在的意思) timer就不会安排第2次,第3次启动? 那么我这个task就没有意义了。 我是不是要考虑其他的方式了呢? 或者直接干脆就执行这个任务一次(直接执行run方法,代码也不改了)?? ... 还是说当发送端关闭了这个session, 接收端的各种资源也就释放了? (应该不会这样吧? 因为发送端和接收端都隔着一个ActiveMQ, 难道ActiveMQ会通知他的其他弟兄关闭关于自己的接收?) 一大嘟噜问题,真是不好意思 有空给在下点拨点拨呗 谢谢了 good luck
Storm-Shadow 2013-06-14
  • 打赏
  • 举报
回复
引用 1 楼 shnulaa 的回复:
一般都是在客户端关闭seesion conection,代码例子

@Override
public void convertAndSend(Event message) {
    // build ConnectionFactory And Queue is necessary
    buildConnectionFactoryAndQueue();
    
    Connection connect = null;
    Session session = null;
    MessageProducer producer = null;
    try {
      connect = jmsConnectionFactory.createConnection();
      session = connect.createSession(false, Session.DUPS_OK_ACKNOWLEDGE);
      producer = session.createProducer(queue);
      // create a JMS message and send it
      ObjectMessage objMsg = session.createObjectMessage(message);
      // set message selector
      String messageSelector = message.getMessageSelector();
      objMsg.setStringProperty("messageReceiver", messageSelector);

      producer.send(objMsg);
    } catch (JMSException e) {
      String errorMessage = "JMSException while queueing HTTP JMS Message";
      throw new EventRuntimeException(errorMessage, e);
    } finally {
      SafeCloseUtil.close(producer); // 这里关闭 producer
      SafeCloseUtil.close(session);  // 这里关闭 producer
      SafeCloseUtil.close(connect);
    }
}
服务端只需要实现MessageListener的onMessage,客户端的 session服务端根本不知道,也无法关闭。
@Override
public void onMessage(Message message) {
    printLogMessage("start public function onMessage()..");
    try {
      if (message instanceof ObjectMessage) {
        ObjectMessage objMsg = (ObjectMessage) message;
        Event event = (Event) objMsg.getObject();
        // if Re deliver message warn the message
        if (message.getJMSRedelivered()) {
          log.warn("...", event.getClass().getSimpleName());
        }
        // out Put Event Log
        outPutEventLog(event);
        // dispatch Event
        dispatchEvent(event);
      } else {
        log.error("This MDB message was not instance of ObjectMessage; ignoring.");
      }

      printLogMessage("end public function onMessage()..");
    } catch (JMSException e) {
      String errorMessage = "JMS Exception while Listener message.errorMessage:"
          + e.getMessage();
      log.error(errorMessage);
      throw new EventRuntimeException(errorMessage, e);
    }
}
楼上正解
晓风吹雾 2013-06-14
  • 打赏
  • 举报
回复
一般都是在客户端关闭seesion conection,代码例子

@Override
public void convertAndSend(Event message) {
    // build ConnectionFactory And Queue is necessary
    buildConnectionFactoryAndQueue();
    
    Connection connect = null;
    Session session = null;
    MessageProducer producer = null;
    try {
      connect = jmsConnectionFactory.createConnection();
      session = connect.createSession(false, Session.DUPS_OK_ACKNOWLEDGE);
      producer = session.createProducer(queue);
      // create a JMS message and send it
      ObjectMessage objMsg = session.createObjectMessage(message);
      // set message selector
      String messageSelector = message.getMessageSelector();
      objMsg.setStringProperty("messageReceiver", messageSelector);

      producer.send(objMsg);
    } catch (JMSException e) {
      String errorMessage = "JMSException while queueing HTTP JMS Message";
      throw new EventRuntimeException(errorMessage, e);
    } finally {
      SafeCloseUtil.close(producer); // 这里关闭 producer
      SafeCloseUtil.close(session);  // 这里关闭 producer
      SafeCloseUtil.close(connect);
    }
}
服务端只需要实现MessageListener的onMessage,客户端的 session服务端根本不知道,也无法关闭。
@Override
public void onMessage(Message message) {
    printLogMessage("start public function onMessage()..");
    try {
      if (message instanceof ObjectMessage) {
        ObjectMessage objMsg = (ObjectMessage) message;
        Event event = (Event) objMsg.getObject();
        // if Re deliver message warn the message
        if (message.getJMSRedelivered()) {
          log.warn("...", event.getClass().getSimpleName());
        }
        // out Put Event Log
        outPutEventLog(event);
        // dispatch Event
        dispatchEvent(event);
      } else {
        log.error("This MDB message was not instance of ObjectMessage; ignoring.");
      }

      printLogMessage("end public function onMessage()..");
    } catch (JMSException e) {
      String errorMessage = "JMS Exception while Listener message.errorMessage:"
          + e.getMessage();
      log.error(errorMessage);
      throw new EventRuntimeException(errorMessage, e);
    }
}
ActiveMQ安装 : 1.下载:http://activemq.apache.org/download.html 最新Windows版本 2.配置jdk环境,解压ActiveMQ到本地 3.启动ActiveMQ服务器: 32位机 : 直接运行\bin\win32\activemq.bat 64位机 : 直接运行\bin\win64\activemq.bat 4.打开ActiveMQ消息管理后台系统 http://localhost:8161/admin/ 参考文章为 : HelloWorld : http://blog.csdn.net/baggio7095586/article/details/5708519 进阶 :http://haohaoxuexi.iteye.com/blog/1893038 helloworld阶段 : 一个发送消息的程序,一个接收消息的程序..实现最简单的JMS交流... 监听器阶段 : ⑴MessageListener,最简单的监听器..只是拿来监听接收信息的 ⑵SessionAwareMessageListener,有个session的参数..可以拿来对接收到的信息再做响应.. ⑶MessageListenerAdapter,将消息委托交给一个普通的java类来处理.. 转化器阶段 : 实现MessageConverter接口来转换JMS对象与java对象.. 其实在使用MessageListenerAdapter时,Spring默认为我们提供了SimpleMessageConverter转换器.. 事务(无代码): 在Spring整合JMS的应用中,如果我们要进行本地的事务管理的话非常简单,只需要在定义对应的消息监听容器时指定其sessionTransacted属性为true,如: 该属性值默认为false,这样JMS在进行消息监听的时候就会进行事务控制,当在接收消息时监听器执行失败时JMS就会对接收到的消息进行回滚, 对于SessionAwareMessageListener接收消息后发送一个返回消息时也处于同一事务下,但是对于其他操作如数据库访问等将不属于该事务控制。 数据库跟JMS挂钩的事务先别理..

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧