一、生产者事务
创建session的时候,我们传了两个参数,第一个是事务,第二个是签收,我们来说说事务。
Session session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
方法的第一个参数就是事务,它的值可以是true或false,代表session的提交是事务提交还是非事务提交。
当事务的值是false时,只要执行了messageProducer.send()方法,消息就到了队列中,也就是自动提交了。
当事务的值是true时,在执行完messageProducer.send()方法后,在session关闭之前需要多加一个session.commit()方法提交事务。
事务的提交,用于实际复杂的业务场景,可能有多个消息需要入队列,假设有一条入队列报错了,我希望这一批次的都要回滚,这就要提到session.rollback();方法了,可以将session.rollback();方法放在catch语句块中来执行。
代码
public class JmsProduce_TX {
public static final String ACTIVEMQ_URL = "tcp://10.5.96.48:61616";
public static final String QUEUE_NAME = "queue-atguigu";
public static void main(String[] args) throws JMSException {
//1.创建连接工厂
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
//2.通过 连接工厂,获得连接connection并启动访问
Connection connection = activeMQConnectionFactory.createConnection();
connection.start();
//3.创建会话session
//两个参数 ,第一个叫事务,第二个叫签收
Session session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
//4 .创建目的地
Queue queue = session.createQueue(QUEUE_NAME);
//5.创建消息生产者
MessageProducer messageProducer = session.createProducer(queue);
// 6.通过使用messageProduce生产3条消息发送到MQ队列里面
for (int i = 0; i < 3; i++) {
//7.创建消息
TextMessage textMessage = session.createTextMessage("tx msg --- " + i);
//8 .通过messageProducer发送给mq
messageProducer.send(textMessage);
}
//9.关闭资源
messageProducer.close();
/**如果上面connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
* 1.如果是true 这里需要session.commit()先提交事务,在关闭session ,否则队列中没有
消息
* 2.如果是false ,可以不用提交,会自动提交
*/
session.close();
connection.close();
System.out.println("********tx消息发布到MQ完成");
try {
//如果是批量 消息 ok session.commit();
}catch (Exception e){
e.printStackTrace();
session.rollback(); //事务回滚 要么都成功 要么都失败
}finally {
if(null!=session){
session.close(); //关闭session
}
}
}
}
如果session的第一个参数设置的是true ,没有session.commit();队列如图没有收到消息。
如果是false 可以自动接受到消息
二、消费者事务
事务主要是针对生产者而言的,但是对于消费者,也有事务。
将connection.createSession()的第一个参数改为true,表示消费者消费采用事务的方式,如果开启了事务,就需要手动执行session.commit();来提交事务,假设这时候,我们不提交事务,看看会出现什么情况。
先启动生产者,后启动消费者,控制台可以看到消费者消费了消息,但是我们没有执行commit();方法,再次执行消费者,发现又做了一次消费,也就是说,消费者的消费行为没有提交,也就没有通知到MQ,MQ认为消息还没有被消费,所以会出现重复消费的情况。
对于事务,一般情况下就用false即可,如果此时需要保证事务的一致性,那么就要使用true,另外一定不要忘了session.commit();手动提交,否则会出现比较麻烦的问题。
public class JmsConsumer_TX {
public static final String ACTIVEMQ_URL = "tcp://10.5.96.48:61616";
public static final String QUEUE_NAME = "queue-atguigu";
public static void main(String[] args) throws JMSException {
//1.创建连接工厂,按照给定的url地址,采用默认的用户名和密码
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
//2.通过链接工厂,获得连接connection并启动访问
Connection connection = activeMQConnectionFactory.createConnection();
connection.start();
//3.创建会话
Session session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
//4.创建目的地
Queue queue = session.createQueue(QUEUE_NAME);
//5.创建消费者
MessageConsumer messageConsumer = session.createConsumer(queue);
while (true)
{
TextMessage textMessage = (TextMessage) messageConsumer.receive(4000);
if(null != textMessage){
System.out.println("********消费者接收消息:"+ textMessage.getText());
}else{
break;
}
}
messageConsumer.close();
/** 如果消费者Session session =
connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
* 1.如果设置的是false 消费了消息的话,就不会重复消费
* 2.如果是true 。必须session.commit()否则会出现重复消费的情况
*/
session.close();
connection.close();
}
}
参考
https://blog.csdn.net/qq_36059561/article/details/103812438
https://blog.csdn.net/qq_36059561/article/details/103812598