http://riddickbryant.iteye.com/blog/441890

【发送端】

session = connection.createSession(Boolean.FALSE,  Session.AUTO_ACKNOWLEDGE);

producer.setDeliveryMode(DeliveryMode.PERSISTENT);

 import javax.jms.*;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
/**
*
* @author LIN NP
*/
public class JmsSender{ private ConnectionFactory connectionFactory = null;
private Connection connection = null;
private Session session = null;
private Destination destination = null;
private MessageProducer producer = null; private static final int SEND_NUMBER = 1; public void init()
{
// 构造ConnectionFactory实例对象,此处采用ActiveMq的实现jar
connectionFactory = new ActiveMQConnectionFactory(
ActiveMQConnection.DEFAULT_USER,
ActiveMQConnection.DEFAULT_PASSWORD,"tcp://localhost:61616"); // ActiveMQ默认使用的TCP连接端口是61616 try{
// 构造从工厂得到连接对象
connection = connectionFactory.createConnection();
connection.start();
// 获取操作连接
session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE); //第一种方式:Queue // destination = session.createQueue("xkey"); // "xkey"可以取其他的。
// producer = session.createProducer(destination); // 得到消息生成者【发送者】 //第二种方式:Topic
Topic topic = session.createTopic("xkey.Topic");
producer = session.createProducer(topic); // 持久化
producer.setDeliveryMode(DeliveryMode.PERSISTENT); // 构造消息,此处写死,项目就是参数,或者方法获取
sendMessage(session,producer); //session.commit();
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
try
{
connection.close();
}
catch (JMSException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} private void sendMessage(Session session,MessageProducer producer) throws JMSException
{
for (int i = 1; i <= SEND_NUMBER; i ++)
{
TextMessage message = session.createTextMessage("发送消息" + i); System.out.println("发送消息" + i); // 发送消息
producer.send(message); }
}
/**
* @param args
*/
public static void main(String[] args)
{
// TODO Auto-generated method stub
JmsSender jms = new JmsSender();
jms.init();
}
}

【接收端】

connection = connectionFactory.createConnection();
connection.setClientID("bbb");
connection.start();

session = connection.createSession(Boolean.FALSE,  Session.AUTO_ACKNOWLEDGE);

consumer = session.createDurableSubscriber(topic,"bbb"); //持久订阅

 import javax.jms.*;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
/**
*
* @author LIN NP
*/
public class JmsReceiver
{
private ConnectionFactory connectionFactory = null;
private Connection connection = null;
private Session session = null;
private MessageConsumer consumer = null;
private Destination destination = null;
public void init()
{
connectionFactory = new ActiveMQConnectionFactory(
ActiveMQConnection.DEFAULT_USER,
ActiveMQConnection.DEFAULT_PASSWORD,"tcp://localhost:61616"); // ActiveMQ默认使用的TCP连接端口是61616
try
{
// 构造从工厂得到连接对象
connection = connectionFactory.createConnection();
connection.setClientID("bbb");
connection.start();
// 获取操作连接
session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
/**
* 第一种方式:Queue
*/
// destination = session.createQueue("xkey");
// consumer = session.createConsumer(destination);
/**
* 第二种方式:Topic
*/ Topic topic = session.createTopic("xkey.Topic");
//consumer = session.createConsumer(topic);
consumer = session.createDurableSubscriber(topic,"bbb"); //持久订阅 /**
*
*/
while (true)
{
//设置接收者接收消息的时间,为了便于测试,这里设定为500s
TextMessage message = (TextMessage) consumer.receive(500);
if (null != message)
{
System.out.println("Receiver: " + message.getText());
}
else
{
break;
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
try
{
connection.close();
}
catch (JMSException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* @param args
*/
public static void main(String[] args)
{
// TODO Auto-generated method stub
JmsReceiver jms = new JmsReceiver();
jms.init();
}
}
 //创建JMS连接和会话
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(url);
connection = factory.createConnection();
connection.setClientID(Constant.JMS_CLIENT_ID);
session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
// 创建消息发送主题和发送者
Topic jmsSendTopic = session.createTopic(sendTopic);
sendTopicProducer = session.createProducer(jmsSendTopic);
sendTopicProducer.setDeliveryMode(DeliveryMode.PERSISTENT);
sendTopicProducer.setTimeToLive(Message.DEFAULT_TIME_TO_LIVE);
// 创建消息接收主题和接收者
Topic jmsReceiveTopic = session.createTopic(receiveTopic);
receiveTopicConsumer = session.createDurableSubscriber(jmsReceiveTopic,Constant.JMS_SUBSCRIBE_NAME);
receiveTopicConsumer.setMessageListener(this);
connection.start();

解答:问题原因在于这段代码在接收到JMS消息时不会向ActiveMQ服务器确认消息的接收,故而ActiveMQ服务器一直认为该消息没有成功发送给接收者,因而每次接收者重启之后就会收到ActiveMQ服务器发送过来的消息。在这里要解释一下session的创建。

session = connection.createSession(true,Session.Auto_ACKNOWLEDGE);

当createSession第一个参数为true时,表示创建的session被标记为transactional的,确认消息就通过确认和校正来自动地处理,第二个参数应该是没用的。

当createSession的第一个参数为false时,表示创建的session没有标记为transactional,此时有三种用于消息确认的选项:
**AUTO_ACKNOWLEDGE session将自动地确认收到的一则消息;
**CLIENT_ACKNOWLEDGE 客户端程序将确认收到的一则消息,调用这则消息的确认方法;
**DUPS_OK_ACKNOWLEDGE 这个选项命令session“懒散的”确认消息传递,可以想到,这将导致消息提供者传递的一些复制消息可能出错。

JMS有两种消息传递方式。标记为NON_PERSISTENT的消息最多传递一次,而标记为PERSISTENT的消息将使用暂存后再转发的机理投递。如果一个JMS服务离线,那么持久性消息不会丢失,但是得等到这个服务恢复联机的时候才会被传递。所以默认的消息传递方式是非持久性的,虽然使用非持久性消息可能降低内存和需要的存储器,但这种传递方式只有当你不需要接收所有消息时才使用。
因此正确的代码只需改动一处就行了,即将true改为false

 //创建JMS连接和会话
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(url);
connection = factory.createConnection();
connection.setClientID(Constant.JMS_CLIENT_ID);
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 创建消息发送主题和发送者
Topic jmsSendTopic = session.createTopic(sendTopic);
sendTopicProducer = session.createProducer(jmsSendTopic);
sendTopicProducer.setDeliveryMode(DeliveryMode.PERSISTENT);
sendTopicProducer.setTimeToLive(Message.DEFAULT_TIME_TO_LIVE);
// 创建消息接收主题和接收者
Topic jmsReceiveTopic = session.createTopic(receiveTopic);
receiveTopicConsumer = session.createDurableSubscriber(jmsReceiveTopic,Constant.JMS_SUBSCRIBE_NAME);
receiveTopicConsumer.setMessageListener(this);
connection.start();

ActiveMQ的消息确认问题的更多相关文章

  1. activemq的消息确认机制ACK

    一.简介 消息消费者有没有接收到消息,需要有一种机制让消息提供者知道,这个机制就是消息确认机制. ACK(Acknowledgement)即确认字符,在数据通信中,接收站发给发送站的一种传输类控制字符 ...

  2. Activemq消息确认机制 --转载

      转自:http://blog.csdn.net/czp11210/article/details/47022639 ActiveMQ消息传送机制以及ACK机制详解 AcitveMQ是作为一种消息存 ...

  3. ActiveMQ发消息和收消息

    来自:http://blog.163.com/chengwei_1104/blog/static/53645274201382315625329/ ActiveMQ 是Apache出品,最流行的,能力 ...

  4. JAVA消息确认机制之ACK模式

    JMS API中约定了Client端可以使用四种ACK模式,在javax.jms.Session接口中: AUTO_ACKNOWLEDGE = 1    自动确认 CLIENT_ACKNOWLEDGE ...

  5. RabbitMQ 消息确认机制

    消息确认机制 在之前异常处理部分就已经写了,对于consumer的异常退出导致消息丢失,可以时候consumer的消息确认机制.重复的就不说了,这里说一些不一样的. consumer的消息确认机制 当 ...

  6. (转)RabbitMQ消息队列(九):Publisher的消息确认机制

    在前面的文章中提到了queue和consumer之间的消息确认机制:通过设置ack.那么Publisher能不到知道他post的Message有没有到达queue,甚至更近一步,是否被某个Consum ...

  7. ActiveMQ之消息指针

    消息指针(Message cursor)是activeMQ里一个非常重要的核心类,它是提供某种优化消息存储的方法.消息中间件的实现一般都是当消费者准备好消费消息的时候,它会从持久化存储中一批一批的读取 ...

  8. JMS - 消息确认

    消息确认机制 消息确认协议是保证消息传送的关键所在,同时,支持确认也是 JMS API 语义的要求.以下将分别从消息生产者.消息服务器.消息消费者的角度,来考察消息确认机制. 从消息生产者的角度考察 ...

  9. RabbitMQ消息队列(九):Publisher的消息确认机制

    在前面的文章中提到了queue和consumer之间的消息确认机制:通过设置ack.那么Publisher能不到知道他post的Message有没有到达queue,甚至更近一步,是否被某个Consum ...

随机推荐

  1. mysql 1130 ERROR 1130: Host xxx.xxx.xxx.xxx is not allowed to connect to this MySQL server

    mysql -u root -p  mysql;use mysql;  mysql;select 'host' from user where user='root';  mysql;update u ...

  2. Http中Cookie和Session介绍

    先介绍下B/S系统的工作的完整过程.首先客户端的浏览器发出请求,服务端的webserver接受到请求后,调用相关请求的页面进行处理,处理完后将结果发送给客户端的浏览器进行显示.只能是浏览器向webse ...

  3. 记录一次cefsharp1输入法在win7下异常解决定位

    最近几天都被基于cefSharp封装的浏览器控件搞疯了!对于cefSharp基本满足当前所做项目的需求,但是有一个问题一直困扰我,那就是系统中偶尔会出现输入法不能转换到中文.而且这个问题似乎没有什么规 ...

  4. int (*p)[4] p 是二级指针 二维数组 二级指针 .xml

    pre{ line-height:1; color:#2f88e4; background-color:#e9ffff; font-size:16px;}.sysFunc{color:#3d7477; ...

  5. SQL Server 2008 备份改进版

    1.Add compressing function with 7-Zip 2.With tool win.rar code so you can change it if you want USE ...

  6. Asp.net MVC4 使用EF实现数据库的增删改查

    EF的使用 步骤: (1)将EF添加到项目:在Model右击添加新建项 找到ADO.NET实体数据模型,接着... (2)实现数据库的增删改查       查询 (因为在Model中已经添加EF实体了 ...

  7. DOM笔记(六):怎么进行JQuery扩展?

    一.全局函数的扩展 全局函数是将独立的函数添加到JQuery的命名空间中区.在使用的时候,可以通过$.fucnName(param)或者jQuery.funcName(param)方式进行调用. 1. ...

  8. The serializable class does not declare a static final serialVersionUID field of type long

    在编译以下Java程序时,出现The serializable class  does not declare a static final serialVersionUID field of typ ...

  9. Excel的 OleDb 连接串的格式

    Excel的 OleDb 连接串的格式(Provider=Microsoft.ACE.OLEDB)(2012-08-02 13:04:20) string strCon = "Provide ...

  10. Maven默认周期与插件

    运行 cmd mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -DarchetypeArtifactId= ...