我们来回顾一下,使用ActiveMQ需要哪些准备工作,
类似下面的伪代码
生产者
// 连接工厂,用于创建Connection对象
private ConnectionFactory factory;
// activeMQ 连接对象
private Connection connection;
// 一次和ActiveMQ的持久会话对象
private Session session;
factory = new ActiveMQConnectionFactory("admin", "admin", "tcp://192.168.111.188:61616");
// 创建链接对象
connection = factory.createConnection();
// 启动连接对象
connection.start();
/*
* 创建会话对象
* 方法 - connection.createSession(boolean transacted, int acknowledgeMode);
* transacted - 是否使用事务,
* 可选值为true|false
* true - 使用事务, 当设置此变量值, 则acknowledgeMode参数无效,
* 建议传递的acknowledgeMode参数值为 Session.SESSION_TRANSACTED
* false - 不使用事务, 设置此变量值,则acknowledgeMode参数必须设置.
* acknowledgeMode - 消息确认机制, 可选值为:
* Session.AUTO_ACKNOWLEDGE - 自动确认消息机制
* Session.CLIENT_ACKNOWLEDGE -客户端确认消息机制
* Session.DUPS_OK_ACKNOWLEDGE - 有副本的客户端确认消息机制
*/
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 创建目的地,目的地的命名既是队列的命令
destination = session.createQueue("MQueue");
// 创建消息生成者, 创建的消息生成者与某目的地对应, 即方法参数目的地.
// 回收消息发送者资源
if(producer != null) {
producer.close();
}
// 回收会话资源
if(session != null) {
session.close();
}
// 回收链接资源
if(connection != null) {
connection.close();
}
消费者
// 连接工厂,用于创建Connection对象
private ConnectionFactory factory;
// activeMQ 连接对象
private Connection connection;
// 一次和ActiveMQ的持久会话对象
private Session session;
factory = new ActiveMQConnectionFactory("admin", "admin", "tcp://192.168.111.188:61616");
// 创建链接对象
connection = factory.createConnection();
// 启动连接对象
connection.start();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 创建目的地,目的地的命名既是队列的命令
destination = session.createQueue("MQueue");
// 回收消息发送者资源
if(consumer != null) {
consumer.close();
}
// 回收会话资源
if(session != null) {
session.close();
}
// 回收链接资源
if(connection != null) {
connection.close();
}
这部分工作是必须的,但是又是相同的操作,每次都编写,使得代码冗余了。
这个流程
创建ConnectionFactory
通过ConnectionFactory创建Connection
启动Conection start()
通过Connection创建Session
通过Session创建Destination
使用Destination创建MassageProducer消息生产者/MassageConsumer消息消费者
使用Producer生产者发送消息,使用Consumer消费者接收消息(Topic则是发布和订阅)
提交Session
关闭释放各种资源
公共的准备工作部分,我们可以在配置文件中,注册到Spring容器中,给Spring进行管理。
ActiveMQ 连接工厂connectionFactory
用于访问ActiveMQ使用的JmsTemplate
消息监听器
生产者和消费者
所以可以看出来,除了消息和目的地,其他都类似模板,可以这么去理解我们需要动态的传入目的地和消息类
依赖
<!-- ActiveMQ客户端完整jar包依赖 -->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.9.0</version>
</dependency>
<!-- ActiveMQ和Spring整合配置文件标签处理jar包依赖 -->
<dependency>
<groupId>org.apache.xbean</groupId>
<artifactId>xbean-spring</artifactId>
<version>4.5</version>
</dependency>
<!-- Spring-JMS插件相关jar包依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<!-- Spring框架上下文jar包依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
配置文件
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:amq="http://activemq.apache.org/schema/core"
xmlns:jms="http://www.springframework.org/schema/jms"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/jms
http://www.springframework.org/schema/jms/spring-jms-4.0.xsd
http://activemq.apache.org/schema/core
http://activemq.apache.org/schema/core/activemq-core-5.9.0.xsd">
<!-- 添加扫描 -->
<context:component-scan base-package="com.active.*"/>
<!-- ActiveMQ 连接工厂 -->
<!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供 -->
<!-- 需提供访问路径tcp://ip:61616;以及用户名,密码 -->
<amq:connectionFactory id="amqConnectionFactory"
brokerURL="tcp://192.168.111.188:61616" userName="admin" password="admin" />
<!-- Spring Caching连接工厂 -->
<!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory -->
<bean id="connectionFactory"
class="org.springframework.jms.connection.CachingConnectionFactory">
<!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory -->
<property name="targetConnectionFactory" ref="amqConnectionFactory"></property>
<!-- Session缓存数量 -->
<property name="sessionCacheSize" value="100" />
</bean>
<!-- 消息生产者 start -->
<!-- 定义JmsTemplate对象. 此类型由Spring框架JMS组件提供. 用于访问ActiveMQ使用. -->
<bean id="jmsQueueTemplate" class="org.springframework.jms.core.JmsTemplate">
<!-- 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 -->
<constructor-arg ref="connectionFactory" />
<!-- 非pub/sub模型(发布/订阅),即队列模式, 默认数据可省略配置 -->
<!-- <property name="pubSubDomain" value="false" /> -->
</bean>
<!-- 定义生成者对象 -->
<!-- <bean id="mQProducer" class="com.active.producer.MQProducer">
为属性赋值
<property name="template" ref="jmsQueueTemplate"></property>
</bean> -->
<!--消息生产者 end -->
<!-- 消息消费者 start -->
<!-- 定义消息监听器, 此组件为spring-jms组件定义. 可以一次注册若干消息监听器.
属性解释:
destination-type - 目的地类型, queue代表消息队列
可选值: queue | topic | durableTopic
queue - 默认值. 代表消息队列
topic - 代表消息队列集合
durableTopic - 持久化的消息队列集合. ActiveMQ会保证消息的消费者一定接收到此消息.
container-type - 容器类型
可选值: default | simple
default - 默认值. 默认容器类型, 对应DefaultMessageListenerContainer
simple - 简单容器类型, 对应SimpleMessageListenerContainer
connection-factory - 链接工厂, 注入的是Spring-JMS组件提供的链接工厂对象.
acknowledge - 确认方式
可选值: auto | client | dups-ok | transacted
auto - 默认值, 即自动确认消息
client - 客户端确认消息
dups-ok - 可使用副本的客户端确认消息
transacted - 有事务的持久化消息确认机制. 需开启对ActiveMQ的事务控制才可应用.
-->
<jms:listener-container destination-type="queue"
container-type="default" connection-factory="connectionFactory"
acknowledge="auto">
<!-- 注册消息监听器. 如果需要注册多个, 重复定义下述标签. -->
<jms:listener destination="test-spring" ref="MQConsumer" />
</jms:listener-container>
<!-- 容器管理消息监听器实现类对象 -->
<!-- <bean id="mQReciver" class="com.active.consumer.MQConsumer"/> -->
<!-- 消息消费者 end -->
</beans>
pojo
MQOrder
public class MQOrder implements Serializable{
private String id;
private String name;
private String address;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public MQOrder(String id, String name, String address) {
super();
this.id = id;
this.name = name;
this.address = address;
}
public MQOrder() {
super();
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "MQOrder [id=" + id + ", name=" + name + ", address=" + address + "]";
}
}
生产者
@Component
public class MQProducer {
@Autowired
JmsTemplate template;
public void producerSend(String destinationName,MQOrder mqOrder) {
// TODO Auto-generated method stub
template.send(destinationName,new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
// TODO Auto-generated method stub
ObjectMessage objectMessage = session.createObjectMessage(mqOrder);
System.out.println("生产者发送:"+objectMessage);
return objectMessage;
}
});
}
}
消费者
@Component
public class MQConsumer implements MessageListener{
@Override
public void onMessage(Message message) {
// TODO Auto-generated method stub
ObjectMessage objectMessage = (ObjectMessage) message;
try {
MQOrder mqOrder = (MQOrder) objectMessage.getObject();
System.out.println("消费者收到:"+mqOrder);
} catch (JMSException e) {
System.out.println("消费者收到错误");
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
测试
public class ActiveTest {
@SuppressWarnings("resource")
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
MQProducer mqProducer = applicationContext.getBean(MQProducer.class);
MQOrder mqOrder = new MQOrder("111","zsl","地球");
mqProducer.producerSend("test-spring", mqOrder);
}
}