009_JMS中的事务

1. 本地事务     

1.1. 在一个JMS客户端, 可以使用本地事务来组合消息的发送和接收。JMS Session接口提供了commit和rollback方法。事务提交意味着生产的所有消息被发送, 消费的所有消息被确认; 事务回滚意味着生产的所有消息被销毁, 消费的所有消息被恢复并重新提交, 除非它们已经过期。     

1.2. 事务性的会话总是牵涉到事务处理中, commit或rollback方法一旦被调用, 一个事务就结束了, 而另一个事务被开始。关闭事务性会话将回滚其中的事务。     

1.3. 需要注意的还有一个, 消息的生产和消费不能包含在同一个事务中。

2. 创建事务会话

2.1. 创建事务会话的时候transacted参数要设置为true, acknowledgeMode参数要设置为Session.SESSION_TRANSACTED。

// 1. 创建一个连接工厂
ConnectionFactory cf = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER, ActiveMQConnection.DEFAULT_PASSWORD, ActiveMQConnection.DEFAULT_BROKER_URL);
// 2. 创建连接
Connection conn = cf.createConnection();
// 4. 创建会话
Session session = conn.createSession(true, Session.SESSION_TRANSACTED);

2.2. Session.SESSION_TRANSACTED值是专门为事务会话使用的。

3. 例子

3.1. 创建一个名为JMSTransacted的Java项目, 同时拷入相关jar包

3.2. 编辑MyProducer.java

package com.jmsapp.tra;

import javax.jms.DeliveryMode;
import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.Session;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;

public class MyProducer {
	// 默认连接用户名
	private static final String dftUsr = ActiveMQConnection.DEFAULT_USER;
	// 默认用户密码
	private static final String dftPwd = ActiveMQConnection.DEFAULT_PASSWORD;
	// 默认连接地址
	private static final String dftUrl = ActiveMQConnection.DEFAULT_BROKER_URL;
	// 队列名称
	private static final String queueName = "queueMapMsgTransacted";

	public static void main(String[] args) {
		// 1. 创建一个连接工厂
		QueueConnectionFactory cf = new ActiveMQConnectionFactory(dftUsr, dftPwd, dftUrl);
		// 连接对象
		QueueConnection conn = null;
		// 会话对象
		QueueSession session = null;
		
		try {
			// 2. 创建连接
			conn = cf.createQueueConnection();
			// 3. 启动连接
			conn.start();
			// 4. 创建会话
			session = conn.createQueueSession(true, Session.SESSION_TRANSACTED);
			// 5. 创建消息目的地。如果是点对点, 那么它的实现是Queue; 如果是订阅模式, 那它的实现是Topic。这里我们创建一个名为queueMapMsgTransacted的消息队列。
			Queue queue = session.createQueue(queueName);
			// 6. 消息生产者
			QueueSender sender = session.createSender(null);
			
			// 7. 创建文本消息和发送消息
			MapMessage user = session.createMapMessage();
			user.setLong("id", 100000000000L);
			user.setString("name", "lisi");
			sender.send(queue, user, DeliveryMode.PERSISTENT, 9, 1000 * 60 * 60);
			
			MapMessage userExtend = session.createMapMessage();
			userExtend.setChar("sex", '男');
			userExtend.setBoolean("married", false);
			sender.send(queue, userExtend, DeliveryMode.PERSISTENT, 5, 1000 * 60 * 60);
			
			// 8. 提交事务
			session.commit();
		} catch (JMSException e) {
			if(null != session) {
				try {
					session.rollback();
				} catch (JMSException e1) {
					e1.printStackTrace();
				}
			}
			e.printStackTrace();
		} finally {
			try {
				if (session != null) {
					session.close();
				}
			} catch (JMSException e1) {
				e1.printStackTrace();
			} finally {
				if (conn != null) {
					try {
						conn.close();
					} catch (JMSException e) {
						e.printStackTrace();
					}
				}
			}
		}
	}
}

3.3. 点对点消息过期, 会把它存放到一个ActiveMQ.DLQ的队列中

3.4. 编辑MyConsumer.java

package com.jmsapp.tra;

import java.util.Enumeration;
import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueReceiver;
import javax.jms.QueueSession;
import javax.jms.Session;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;

public class MyConsumer {
	// 默认连接用户名
	private static final String dftUsr = ActiveMQConnection.DEFAULT_USER;
	// 默认用户密码
	private static final String dftPwd = ActiveMQConnection.DEFAULT_PASSWORD;
	// 默认连接地址
	private static final String dftUrl = ActiveMQConnection.DEFAULT_BROKER_URL;
	// 队列名称
	private static final String queueName = "queueMapMsgTransacted";

	public static void main(String[] args) {
		// 1. 创建一个连接工厂
		QueueConnectionFactory cf = new ActiveMQConnectionFactory(dftUsr, dftPwd, dftUrl);
		// 连接对象
		QueueConnection conn = null;
		// 会话对象
		QueueSession session = null;
		
		try {
			// 2. 创建连接
			conn = cf.createQueueConnection();
			// 3. 启动连接
			conn.start();
			// 4. 创建会话
			session = conn.createQueueSession(true, Session.SESSION_TRANSACTED);
			// 5. 创建消息目的地。如果是点对点, 那么它的实现是Queue; 如果是订阅模式, 那它的实现是Topic。这里我们创建一个名为queueMapMsgTransacted的消息队列。
			Queue queue = session.createQueue(queueName);
			// 6. 消息接收者
			QueueReceiver receiver = session.createReceiver(queue);
			
			// 7. 创建文本消息和发送消息
			while(true) {
				MapMessage msg = (MapMessage) receiver.receive(3000);
				if(msg == null) {
					break;
				}
				@SuppressWarnings("unchecked")
				Enumeration<String> e = msg.getMapNames();
				while(e.hasMoreElements()) {
					String name =  e.nextElement();
					System.out.println(name + " = " + msg.getObject(name));
				}
			}
			
			// 8. 提交事务
			session.commit();
		} catch (JMSException e) {
			if(null != session) {
				try {
					session.rollback();
				} catch (JMSException e1) {
					e1.printStackTrace();
				}
			}
			e.printStackTrace();
		} finally {
			try {
				if (session != null) {
					session.close();
				}
			} catch (JMSException e1) {
				e1.printStackTrace();
			} finally {
				if (conn != null) {
					try {
						conn.close();
					} catch (JMSException e) {
						e.printStackTrace();
					}
				}
			}
		}
	}
}

3.5. 再次运行MyProducer.java, 然后运行MyConsumer.java

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值