java mq 教程_ActiveMQ入门教程

ActiveMQ入门教程

本博客内容皆为网络搜集而来,不保证任何版权问题,不保证长期有效性(即具有时效性),如有侵权或内容有违相关法律法规,请联系本人邮箱移除

概述与介绍

ActiveMQ 是Apache出品,最流行的. 功能强大的即时通讯和集成模式的开源服务器。

ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现。

提供客户端支持跨语言和协议,带有易于在充分支持JMS 1.1和1.4使用J2EE企业集成模式和许多先进的功能。

特性

多种语言和协议编写客户端。语言: Java. C. C++. C#. Ruby. Perl. Python. PHP。应用协议:OpenWire. Stomp REST. WS Notification. XMPP. AMQP

完全支持JMS1.1和J2EE 1.4规范 (持久化,XA消息,事务)

对Spring的支持,ActiveMQ可以很容易内嵌到使用Spring的系统里面去,而且也支持Spring2.0的特性

通过了常见J2EE服务器(如 Geronimo. JBoss 4. GlassFish. WebLogic)的测试,其中通过JCA 1.5 resource adaptors的配置,可以让ActiveMQ可以自动的部署到任何兼容J2EE 1.4 商业服务器上

支持多种传送协议:in-VM. TCP. SSL. NIO. UDP. JGroups. JXTA

支持通过JDBC和journal提供高速的消息持久化

从设计上保证了高性能的集群,客户端-服务器,点对点

支持Ajax

支持与Axis的整合

可以很容易得调用内嵌JMS provider,进行测试

本文基于最新版的ActiveMQ 5.15.0进行讲解, 期间遇到的问题也是这个版本出现的, 解决方法也会在文中记录

1.下载

2.安装

2.1解压apache-activemq-5.15.0-bin.zip

本文解压在D盘根目录

3a5d671454d800c8b1e205b719a82030.png

activemq-bin

2.2启动activemq

3b165078b318b524d7317d2a5a2c0dfc.png

activemq-start01

2.2.1普通启动命令

按下: win+r, 输入cmd, 进入dos界面:

85ab013d803240781150b78804a38ebc.png

open-cmd

//3条命令的意思分别是:

//1.进入activemq的bin目录

//2.进入d盘

//3.启动activemq

cd D:\apache-activemq-5.15.0\bin

d:

activemq start

如果你启动看到了异常信息:

Caused by: java.io.IOException: Failed to bind to server socket: tcp://0.0.0.0:61616?maximumConnections=1000&wireformat.maxFrameSize=104857600 due to: java.net.SocketException: Unrecognized Windows Sockets error: 0: **JVM_Bind**

原因是:

你的端口被占用了。找到是哪个程序占用了你的端口, 并kill掉该进程或服务。或者尝试修改ActiveMQ的默认端口61616(ActiveMQ使用的默认端口是61616), 在大多数情况下,占用61616端口的是Internet Connection Sharing (ICS) 这个Windows服务,你只需停止它就可以启动ActiveMQ了。

启动成功:

006eMRnQgy1fk30phjfe9j30xr0k9q65.jpg

启动完成访问http://127.0.0.1:8161/

1.访问: http://127.0.0.1:8161/,再点击Manage ActiveMQ broker

006eMRnQgy1fk30pgpx3aj314w0gf0ur.jpg

web管理页面

进入管理页面, 帐号密码都是: admin

006eMRnQgy1fk30twfydrj30ez0ao0t0.jpg

输入帐号密码

进入admin页面, 也可以直接进入http://127.0.0.1:8161/admin/, 输入帐号密码: admin即可

006eMRnQgy1fk30txivcaj310c0p5acw.jpg

进入admin页面

导航菜单中

Queues是队列方式消息

Topics是主题方式消息

Subscribers消息订阅监控查询

Connections可以查看链接数,分别可以查看xmpp、ssl、stomp、openwire、ws和网络链接

Network是网络链接数监控

Send可以发送消息数据。

如果你想修改用户名和密码的话,在conf/jetty-realm.properties中修改即可。

## ---------------------------------------------------------------------------

## Licensed to the Apache Software Foundation (ASF) under one or more

## contributor license agreements. See the NOTICE file distributed with

## this work for additional information regarding copyright ownership.

## The ASF licenses this file to You under the Apache License, Version 2.0

## (the "License"); you may not use this file except in compliance with

## the License. You may obtain a copy of the License at

##

## http://www.apache.org/licenses/LICENSE-2.0

##

## Unless required by applicable law or agreed to in writing, software

## distributed under the License is distributed on an "AS IS" BASIS,

## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

## See the License for the specific language governing permissions and

## limitations under the License.

## ---------------------------------------------------------------------------

# Defines users that can access the web (console, demo, etc.)

# username: password [,rolename ...]

admin: admin, admin

user: user, user

2.2.2运行demo示例

遇到的问题:

使用官方文档提供的启动方式启动ActiveMQ v5.15,

bin/activemq console xbean:examples/conf/activemq-demo.xml

不能启动,activemq中没有console 参数。

解决办法:

不同版本启动命令不一样!

1、V5.8使用下面的命令行启动

D:\apache-activemq-5.8.0\bin>activemq xbean:../conf/activemq-demo.xml

2、V5.9使用下面的命令行启动

D:\apache-activemq-5.9.1\bin>activemq xbean:../examples/conf/activemq-demo.xml

3、V5.15.0使用下面的命令行启动

D:\apache-activemq-5.15.0\bin>activemq start xbean:file:../examples/conf/activemq-demo.xml

当然你还可以用绝对的文件目录方式:activemq start xbean:file:D:\apache-activemq-5.15.0\conf/activemq-demo.xml

输入命令启动

activemq start xbean:file:../examples/conf/activemq-demo.xml

006eMRnQgy1fk319q94d9j30xs0rcgpx.jpg

运行demo示例

006eMRnQgy1fk31hqnq75j314v0riq6h.jpg

demo示例页面

下面还有个发消息和收消息

006eMRnQgy1fk31q70pmfj30he047mxd.jpg

发消息和收消息

发消息

006eMRnQgy1fk31utitaxj30o50bo0tt.jpg

发消息

收消息

006eMRnQgy1fk31utumuaj315h041753.jpg

收消息

进入页面

006eMRnQgy1fk31lr6qk3j314x0lzn03.jpg

连接页

3.使用

3.1消息示例

3.1.1ActiviteMQ消息有3种形式

JMS 公共

点对点域

发布/订阅域

ConnectionFactory

QueueConnectionFactory

TopicConnectionFactory

Connection

QueueConnection

TopicConnection

Destination

Queue

Topic

Session

QueueSession

TopicSession

MessageProducer

QueueSender

TopicPublisher

MessageConsumer

QueueReceiver

TopicSubscriber

点对点方式(point-to-point)

点对点的消息发送方式主要建立在 Message Queue,Sender,reciever上,Message Queue 存贮消息,Sneder 发送消息,receive接收消息.具体点就是Sender Client发送Message Queue ,而 receiver Cliernt从Queue中接收消息和"发送消息已接受"到Quere,确认消息接收。消息发送客户端与接收客户端没有时间上的依赖,发送客户端可以在任何时刻发送信息到Queue,而不需要知道接收客户端是不是在运行

发布/订阅 方式(publish/subscriber Messaging)

发布/订阅方式用于多接收客户端的方式.作为发布订阅的方式,可能存在多个接收客户端,并且接收端客户端与发送客户端存在时间上的依赖。一个接收端只能接收他创建以后发送客户端发送的信息。作为subscriber ,在接收消息时有两种方法,destination的receive方法,和实现message listener 接口的onMessage 方法。

3.1.2ActiviteMQ接收和发送消息基本流程

006eMRnQgy1fk321fc3xaj30bl0o4wm8.jpg

基本流程

发送消息的基本步骤:

(1)、创建连接使用的工厂类JMS ConnectionFactory

(2)、使用管理对象JMS ConnectionFactory建立连接Connection,并启动

(3)、使用连接Connection 建立会话Session

(4)、使用会话Session和管理对象Destination创建消息生产者MessageSender

(5)、使用消息生产者MessageSender发送消息

消息接收者从JMS接受消息的步骤

(1)、创建连接使用的工厂类JMS ConnectionFactory

(2)、使用管理对象JMS ConnectionFactory建立连接Connection,并启动

(3)、使用连接Connection 建立会话Session

(4)、使用会话Session和管理对象Destination创建消息接收者MessageReceiver

(5)、使用消息接收者MessageReceiver接受消息,需要用setMessageListener将MessageListener接口绑定到MessageReceiver消息接收者必须实现了MessageListener接口,需要定义onMessage事件方法。

3.1.3使用java代码实现收发消息

1.使用JMS方式发送接收消息

发送方代码

package com.dragon.activemq.demo;

import org.apache.activemq.ActiveMQConnection;

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.Connection;

import javax.jms.ConnectionFactory;

import javax.jms.DeliveryMode;

import javax.jms.Destination;

import javax.jms.MessageProducer;

import javax.jms.Session;

import javax.jms.TextMessage;

/**

* @author Dragon

* @version V0.1

* @Title: com.dragon.activemq.demo.MessageSender

* @project ActiveMQ-5.15.0

* @Description: 使用JMS方式发送接收消息 - 消息发送者

* @date 2017/10/01 21:16

*/

public class MessageSender {

// 发送次数

public static final int SEND_NUM = 5;

// tcp 地址

public static final String BROKER_URL = "tcp://localhost:61616";

// 目标,在ActiveMQ管理员控制台创建 http://localhost:8161/admin/queues.jsp

public static final String DESTINATION = "sagedragon.mq.queue";

/**

* function: 发送消息

*

* @param session

* @param producer

* @throws Exception

*/

public static void sendMessage(Session session, MessageProducer producer) throws Exception {

for (int i = 0; i < SEND_NUM; i++) {

String message = "发送消息第" + (i + 1) + "条";

TextMessage text = session.createTextMessage(message);

System.out.println(message);

producer.send(text);

}

}

public static void run() throws Exception {

Connection connection = null;

Session session = null;

try {

// 创建链接工厂

ConnectionFactory factory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER, ActiveMQConnection.DEFAULT_PASSWORD, BROKER_URL);

// 通过工厂创建一个连接

connection = factory.createConnection();

// 启动连接

connection.start();

// 创建一个session会话

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

// 创建一个消息队列

Destination destination = session.createQueue(DESTINATION);

// 创建消息制作者

MessageProducer producer = session.createProducer(destination);

// 设置持久化模式

producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);

sendMessage(session, producer);

// 提交会话

session.commit();

} catch (Exception e) {

throw e;

} finally {

// 关闭释放资源

if (session != null) {

session.close();

}

if (connection != null) {

connection.close();

}

}

}

public static void main(String[] args) throws Exception {

MessageSender.run();

}

}

输出

发送消息第1条

21:20:28.651 [main] DEBUG org.apache.activemq.TransactionContext - Begin:TX:ID:xxx-49962-1506864009010-1:1:1

发送消息第2条

发送消息第3条

发送消息第4条

发送消息第5条

接收方

package com.dragon.activemq.demo;

import org.apache.activemq.ActiveMQConnection;

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.Connection;

import javax.jms.ConnectionFactory;

import javax.jms.Destination;

import javax.jms.Message;

import javax.jms.MessageConsumer;

import javax.jms.Session;

import javax.jms.TextMessage;

/**

* @author Dragon

* @version V0.1

* @Title: com.dragon.activemq.demo.MessageSender

* @project ActiveMQ-5.15.0

* @Description: 使用JMS方式发送接收消息 - 消息接收者

* @date 2017/10/01 21:16

*/

public class MessageReceiver {

// tcp 地址

public static final String BROKER_URL = "tcp://localhost:61616";

// 目标,在ActiveMQ管理员控制台创建 http://localhost:8161/admin/queues.jsp

public static final String DESTINATION = "sagedragon.mq.queue";

public static void run() throws Exception {

Connection connection = null;

Session session = null;

try {

// 创建链接工厂

ConnectionFactory factory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER, ActiveMQConnection

.DEFAULT_PASSWORD, BROKER_URL);

// 通过工厂创建一个连接

connection = factory.createConnection();

// 启动连接

connection.start();

// 创建一个session会话

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

// 创建一个消息队列

Destination destination = session.createQueue(DESTINATION);

// 创建消息制作者

MessageConsumer consumer = session.createConsumer(destination);

while (true) {

// 接收数据的时间(等待) 100 ms

Message message = consumer.receive(1000 * 100);

TextMessage text = (TextMessage) message;

if (text != null) {

System.out.println("接收:" + text.getText());

} else {

break;

}

}

// 提交会话

session.commit();

} catch (Exception e) {

throw e;

} finally {

// 关闭释放资源

if (session != null) {

session.close();

}

if (connection != null) {

connection.close();

}

}

}

public static void main(String[] args) throws Exception {

MessageReceiver.run();

}

}

输出

21:25:08.718 [main] DEBUG org.apache.activemq.TransactionContext - Begin:TX:ID:xxx-49992-1506864308500-1:1:1

接收:发送消息第1条

接收:发送消息第2条

接收:发送消息第3条

接收:发送消息第4条

接收:发送消息第5条

2.Queue队列方式发送点对点消息数据

发送方

package com.dragon.activemq.demo;

import org.apache.activemq.ActiveMQConnection;

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.DeliveryMode;

import javax.jms.MapMessage;

import javax.jms.Queue;

import javax.jms.QueueConnection;

import javax.jms.QueueConnectionFactory;

import javax.jms.QueueSession;

import javax.jms.Session;

/**

* @author Dragon

* @version V0.1

* @Title: com.dragon.activemq.demo.QueueSender

* @project ActiveMQ-5.15.0

* @Description: Queue队列方式发送点对点消息数据 - 消息发送者

* @date 2017/10/01 21:16

*/

public class QueueSender {

// 发送次数

public static final int SEND_NUM = 5;

// tcp 地址

public static final String BROKER_URL = "tcp://localhost:61616";

// 目标,在ActiveMQ管理员控制台创建 http://localhost:8161/admin/queues.jsp

public static final String DESTINATION = "sagedragon.mq.queue";

/**

* function: 发送消息

*

* @param session

* @param sender

* @throws Exception

*/

public static void sendMessage(QueueSession session, javax.jms.QueueSender sender) throws Exception {

for (int i = 0; i < SEND_NUM; i++) {

String message = "发送消息第" + (i + 1) + "条";

MapMessage map = session.createMapMessage();

map.setString("text", message);

map.setLong("time", System.currentTimeMillis());

System.out.println(map);

sender.send(map);

}

}

public static void run() throws Exception {

QueueConnection connection = null;

QueueSession session = null;

try {

// 创建链接工厂

QueueConnectionFactory factory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER, ActiveMQConnection.DEFAULT_PASSWORD, BROKER_URL);

// 通过工厂创建一个连接

connection = factory.createQueueConnection();

// 启动连接

connection.start();

// 创建一个session会话

session = connection.createQueueSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);

// 创建一个消息队列

Queue queue = session.createQueue(DESTINATION);

// 创建消息发送者

javax.jms.QueueSender sender = session.createSender(queue);

// 设置持久化模式

sender.setDeliveryMode(DeliveryMode.NON_PERSISTENT);

sendMessage(session, sender);

// 提交会话

session.commit();

} catch (Exception e) {

throw e;

} finally {

// 关闭释放资源

if (session != null) {

session.close();

}

if (connection != null) {

connection.close();

}

}

}

public static void main(String[] args) throws Exception {

QueueSender.run();

}

}

输出

21:27:31.827 [main] DEBUG org.apache.activemq.transport.WireFormatNegotiator - Sending: WireFormatInfo { version=12, properties={StackTraceEnabled=true, PlatformDetails=JVM: 1.8.0_77, 25.77-b03, Oracle Corporation, OS: Windows 10, 10.0, amd64, CacheEnabled=true, Host=localhost, TcpNoDelayEnabled=true, SizePrefixDisabled=false, CacheSize=1024, ProviderName=ActiveMQ, TightEncodingEnabled=true, MaxFrameSize=9223372036854775807, MaxInactivityDuration=30000, MaxInactivityDurationInitalDelay=10000, ProviderVersion=5.15.0}, magic=[A,c,t,i,v,e,M,Q]}

21:27:31.834 [ActiveMQ Transport: tcp://localhost/127.0.0.1:61616@50006] DEBUG org.apache.activemq.transport.WireFormatNegotiator - Received WireFormat: WireFormatInfo { version=12, properties={TcpNoDelayEnabled=true, SizePrefixDisabled=false, CacheSize=1024, ProviderName=ActiveMQ, StackTraceEnabled=true, PlatformDetails=JVM: 1.8.0_77, 25.77-b03, Oracle Corporation, OS: Windows 10, 10.0, amd64, CacheEnabled=true, TightEncodingEnabled=true, MaxFrameSize=9223372036854775807, MaxInactivityDuration=30000, MaxInactivityDurationInitalDelay=10000, ProviderVersion=5.15.0}, magic=[A,c,t,i,v,e,M,Q]}

21:27:31.835 [main] DEBUG org.apache.activemq.transport.InactivityMonitor - Using min of local: WireFormatInfo { version=12, properties={StackTraceEnabled=true, PlatformDetails=JVM: 1.8.0_77, 25.77-b03, Oracle Corporation, OS: Windows 10, 10.0, amd64, CacheEnabled=true, Host=localhost, TcpNoDelayEnabled=true, SizePrefixDisabled=false, CacheSize=1024, ProviderName=ActiveMQ, TightEncodingEnabled=true, MaxFrameSize=9223372036854775807, MaxInactivityDuration=30000, MaxInactivityDurationInitalDelay=10000, ProviderVersion=5.15.0}, magic=[A,c,t,i,v,e,M,Q]} and remote: WireFormatInfo { version=12, properties={TcpNoDelayEnabled=true, SizePrefixDisabled=false, CacheSize=1024, ProviderName=ActiveMQ, StackTraceEnabled=true, PlatformDetails=JVM: 1.8.0_77, 25.77-b03, Oracle Corporation, OS: Windows 10, 10.0, amd64, CacheEnabled=true, TightEncodingEnabled=true, MaxFrameSize=9223372036854775807, MaxInactivityDuration=30000, MaxInactivityDurationInitalDelay=10000, ProviderVersion=5.15.0}, magic=[A,c,t,i,v,e,M,Q]}

21:27:31.836 [ActiveMQ Transport: tcp://localhost/127.0.0.1:61616@50006] DEBUG org.apache.activemq.transport.WireFormatNegotiator - tcp://localhost/127.0.0.1:61616@50006 before negotiation: OpenWireFormat{version=12, cacheEnabled=false, stackTraceEnabled=false, tightEncodingEnabled=false, sizePrefixDisabled=false, maxFrameSize=9223372036854775807}

21:27:31.841 [ActiveMQ Transport: tcp://localhost/127.0.0.1:61616@50006] DEBUG org.apache.activemq.transport.WireFormatNegotiator - tcp://localhost/127.0.0.1:61616@50006 after negotiation: OpenWireFormat{version=12, cacheEnabled=true, stackTraceEnabled=true, tightEncodingEnabled=true, sizePrefixDisabled=false, maxFrameSize=9223372036854775807}

ActiveMQMapMessage {commandId = 0, responseRequired = false, messageId = null, originalDestination = null, originalTransactionId = null, producerId = null, destination = null, transactionId = null, expiration = 0, timestamp = 0, arrival = 0, brokerInTime = 0, brokerOutTime = 0, correlationId = null, replyTo = null, persistent = false, type = null, priority = 0, groupID = null, groupSequence = 0, targetConsumerId = null, compressed = false, userID = null, content = null, marshalledProperties = null, dataStructure = null, redeliveryCounter = 0, size = 0, properties = null, readOnlyProperties = false, readOnlyBody = false, droppable = false, jmsXGroupFirstForConsumer = false} ActiveMQMapMessage{ theTable = {text=发送消息第1条, time=1506864451941} }

21:27:31.966 [main] DEBUG org.apache.activemq.TransactionContext - Begin:TX:ID:Mr-Dragon-50004-1506864451704-1:1:1

ActiveMQMapMessage {commandId = 0, responseRequired = false, messageId = null, originalDestination = null, originalTransactionId = null, producerId = null, destination = null, transactionId = null, expiration = 0, timestamp = 0, arrival = 0, brokerInTime = 0, brokerOutTime = 0, correlationId = null, replyTo = null, persistent = false, type = null, priority = 0, groupID = null, groupSequence = 0, targetConsumerId = null, compressed = false, userID = null, content = null, marshalledProperties = null, dataStructure = null, redeliveryCounter = 0, size = 0, properties = null, readOnlyProperties = false, readOnlyBody = false, droppable = false, jmsXGroupFirstForConsumer = false} ActiveMQMapMessage{ theTable = {text=发送消息第2条, time=1506864451971} }

ActiveMQMapMessage {commandId = 0, responseRequired = false, messageId = null, originalDestination = null, originalTransactionId = null, producerId = null, destination = null, transactionId = null, expiration = 0, timestamp = 0, arrival = 0, brokerInTime = 0, brokerOutTime = 0, correlationId = null, replyTo = null, persistent = false, type = null, priority = 0, groupID = null, groupSequence = 0, targetConsumerId = null, compressed = false, userID = null, content = null, marshalledProperties = null, dataStructure = null, redeliveryCounter = 0, size = 0, properties = null, readOnlyProperties = false, readOnlyBody = false, droppable = false, jmsXGroupFirstForConsumer = false} ActiveMQMapMessage{ theTable = {text=发送消息第3条, time=1506864451973} }

ActiveMQMapMessage {commandId = 0, responseRequired = false, messageId = null, originalDestination = null, originalTransactionId = null, producerId = null, destination = null, transactionId = null, expiration = 0, timestamp = 0, arrival = 0, brokerInTime = 0, brokerOutTime = 0, correlationId = null, replyTo = null, persistent = false, type = null, priority = 0, groupID = null, groupSequence = 0, targetConsumerId = null, compressed = false, userID = null, content = null, marshalledProperties = null, dataStructure = null, redeliveryCounter = 0, size = 0, properties = null, readOnlyProperties = false, readOnlyBody = false, droppable = false, jmsXGroupFirstForConsumer = false} ActiveMQMapMessage{ theTable = {text=发送消息第4条, time=1506864451974} }

ActiveMQMapMessage {commandId = 0, responseRequired = false, messageId = null, originalDestination = null, originalTransactionId = null, producerId = null, destination = null, transactionId = null, expiration = 0, timestamp = 0, arrival = 0, brokerInTime = 0, brokerOutTime = 0, correlationId = null, replyTo = null, persistent = false, type = null, priority = 0, groupID = null, groupSequence = 0, targetConsumerId = null, compressed = false, userID = null, content = null, marshalledProperties = null, dataStructure = null, redeliveryCounter = 0, size = 0, properties = null, readOnlyProperties = false, readOnlyBody = false, droppable = false, jmsXGroupFirstForConsumer = false} ActiveMQMapMessage{ theTable = {text=发送消息第5条, time=1506864451975} }

21:27:31.976 [main] DEBUG org.apache.activemq.ActiveMQSession - ID:Mr-Dragon-50004-1506864451704-1:1:1 Transaction Commit :TX:ID:Mr-Dragon-50004-1506864451704-1:1:1

接收方

package com.dragon.activemq.demo;

import org.apache.activemq.ActiveMQConnection;

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.JMSException;

import javax.jms.MapMessage;

import javax.jms.Message;

import javax.jms.MessageListener;

import javax.jms.Queue;

import javax.jms.QueueConnection;

import javax.jms.QueueConnectionFactory;

import javax.jms.QueueSession;

import javax.jms.Session;

/**

* @author Dragon

* @version V0.1

* @Title: com.dragon.activemq.demo.QueueReceiver

* @project ActiveMQ-5.15.0

* @Description: Queue队列方式发送点对点消息数据 - 消息发送者

* @date 2017/10/01 21:16

*/

public class QueueReceiver {

// tcp 地址

public static final String BROKER_URL = "tcp://localhost:61616";

// 目标,在ActiveMQ管理员控制台创建 http://localhost:8161/admin/queues.jsp

public static final String TARGET = "sagedragon.mq.queue";

public static void run() throws Exception {

QueueConnection connection = null;

QueueSession session = null;

try {

// 创建链接工厂

QueueConnectionFactory factory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER, ActiveMQConnection

.DEFAULT_PASSWORD, BROKER_URL);

// 通过工厂创建一个连接

connection = factory.createQueueConnection();

// 启动连接

connection.start();

// 创建一个session会话

session = connection.createQueueSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);

// 创建一个消息队列

Queue queue = session.createQueue(TARGET);

// 创建消息制作者

javax.jms.QueueReceiver receiver = session.createReceiver(queue);

receiver.setMessageListener(new MessageListener() {

public void onMessage(Message msg) {

if (msg != null) {

MapMessage map = (MapMessage) msg;

try {

System.out.println(map.getLong("time") + "接收#" + map.getString("text"));

} catch (JMSException e) {

e.printStackTrace();

}

}

}

});

// 休眠100ms再关闭

Thread.sleep(1000 * 100);

// 提交会话

session.commit();

} catch (Exception e) {

throw e;

} finally {

// 关闭释放资源

if (session != null) {

session.close();

}

if (connection != null) {

connection.close();

}

}

}

public static void main(String[] args) throws Exception {

QueueReceiver.run();

}

}

输出 , 爆了个类型转换错误

21:31:36.409 [ActiveMQ Session Task-1] ERROR org.apache.activemq.ActiveMQMessageConsumer - ID:Mr-Dragon-50055-1506864696129-1:1:1:1 Exception while processing message: ID:Mr-Dragon-49962-1506864009010-1:1:1:1:5

java.lang.ClassCastException: org.apache.activemq.command.ActiveMQTextMessage cannot be cast to javax.jms.MapMessage

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)

at java.lang.Thread.run(Thread.java:745)

1506864451941接收#发送消息第1条

1506864451971接收#发送消息第2条

1506864451973接收#发送消息第3条

1506864451974接收#发送消息第4条

1506864451975接收#发送消息第5条

3.Topic主题发布和订阅消息

发送方

package com.dragon.activemq.demo;

import org.apache.activemq.ActiveMQConnection;

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.DeliveryMode;

import javax.jms.MapMessage;

import javax.jms.Session;

import javax.jms.Topic;

import javax.jms.TopicConnection;

import javax.jms.TopicConnectionFactory;

import javax.jms.TopicPublisher;

import javax.jms.TopicSession;

/**

* @author Dragon

* @version V0.1

* @Title: com.dragon.activemq.demo.QueueSender

* @project ActiveMQ-5.15.0

* @Description: Topic主题发布和订阅消息 - 消息发送者

* @date 2017/10/01 21:16

*/

public class TopicSender {

// 发送次数

public static final int SEND_NUM = 5;

// tcp 地址

public static final String BROKER_URL = "tcp://localhost:61616";

// 目标,在ActiveMQ管理员控制台创建 http://localhost:8161/admin/queues.jsp

public static final String DESTINATION = "sagedragon.mq.queue";

/**

* function: 发送消息

*

* @param session 会话

* @param publisher 发布者

* @throws Exception

*/

public static void sendMessage(TopicSession session, TopicPublisher publisher) throws Exception {

for (int i = 0; i < SEND_NUM; i++) {

String message = "发送消息第" + (i + 1) + "条";

MapMessage map = session.createMapMessage();

map.setString("text", message);

map.setLong("time", System.currentTimeMillis());

System.out.println(map);

publisher.send(map);

}

}

public static void run() throws Exception {

TopicConnection connection = null;

TopicSession session = null;

try {

// 创建链接工厂

TopicConnectionFactory factory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER, ActiveMQConnection.DEFAULT_PASSWORD, BROKER_URL);

// 通过工厂创建一个连接

connection = factory.createTopicConnection();

// 启动连接

connection.start();

// 创建一个session会话

session = connection.createTopicSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);

// 创建一个消息队列

Topic topic = session.createTopic(DESTINATION);

// 创建消息发送者

TopicPublisher publisher = session.createPublisher(topic);

// 设置持久化模式

publisher.setDeliveryMode(DeliveryMode.NON_PERSISTENT);

sendMessage(session, publisher);

// 提交会话

session.commit();

} catch (Exception e) {

throw e;

} finally {

// 关闭释放资源

if (session != null) {

session.close();

}

if (connection != null) {

connection.close();

}

}

}

public static void main(String[] args) throws Exception {

TopicSender.run();

}

}

输出

ActiveMQMapMessage {commandId = 0, responseRequired = false, messageId = null, originalDestination = null, originalTransactionId = null, producerId = null, destination = null, transactionId = null, expiration = 0, timestamp = 0, arrival = 0, brokerInTime = 0, brokerOutTime = 0, correlationId = null, replyTo = null, persistent = false, type = null, priority = 0, groupID = null, groupSequence = 0, targetConsumerId = null, compressed = false, userID = null, content = null, marshalledProperties = null, dataStructure = null, redeliveryCounter = 0, size = 0, properties = null, readOnlyProperties = false, readOnlyBody = false, droppable = false, jmsXGroupFirstForConsumer = false} ActiveMQMapMessage{ theTable = {text=发送消息第1条, time=1506865178417} }

21:39:38.425 [main] DEBUG org.apache.activemq.TransactionContext - Begin:TX:ID:Mr-Dragon-50129-1506865178168-1:1:1

ActiveMQMapMessage {commandId = 0, responseRequired = false, messageId = null, originalDestination = null, originalTransactionId = null, producerId = null, destination = null, transactionId = null, expiration = 0, timestamp = 0, arrival = 0, brokerInTime = 0, brokerOutTime = 0, correlationId = null, replyTo = null, persistent = false, type = null, priority = 0, groupID = null, groupSequence = 0, targetConsumerId = null, compressed = false, userID = null, content = null, marshalledProperties = null, dataStructure = null, redeliveryCounter = 0, size = 0, properties = null, readOnlyProperties = false, readOnlyBody = false, droppable = false, jmsXGroupFirstForConsumer = false} ActiveMQMapMessage{ theTable = {text=发送消息第2条, time=1506865178429} }

ActiveMQMapMessage {commandId = 0, responseRequired = false, messageId = null, originalDestination = null, originalTransactionId = null, producerId = null, destination = null, transactionId = null, expiration = 0, timestamp = 0, arrival = 0, brokerInTime = 0, brokerOutTime = 0, correlationId = null, replyTo = null, persistent = false, type = null, priority = 0, groupID = null, groupSequence = 0, targetConsumerId = null, compressed = false, userID = null, content = null, marshalledProperties = null, dataStructure = null, redeliveryCounter = 0, size = 0, properties = null, readOnlyProperties = false, readOnlyBody = false, droppable = false, jmsXGroupFirstForConsumer = false} ActiveMQMapMessage{ theTable = {text=发送消息第3条, time=1506865178430} }

ActiveMQMapMessage {commandId = 0, responseRequired = false, messageId = null, originalDestination = null, originalTransactionId = null, producerId = null, destination = null, transactionId = null, expiration = 0, timestamp = 0, arrival = 0, brokerInTime = 0, brokerOutTime = 0, correlationId = null, replyTo = null, persistent = false, type = null, priority = 0, groupID = null, groupSequence = 0, targetConsumerId = null, compressed = false, userID = null, content = null, marshalledProperties = null, dataStructure = null, redeliveryCounter = 0, size = 0, properties = null, readOnlyProperties = false, readOnlyBody = false, droppable = false, jmsXGroupFirstForConsumer = false} ActiveMQMapMessage{ theTable = {text=发送消息第4条, time=1506865178432} }

ActiveMQMapMessage {commandId = 0, responseRequired = false, messageId = null, originalDestination = null, originalTransactionId = null, producerId = null, destination = null, transactionId = null, expiration = 0, timestamp = 0, arrival = 0, brokerInTime = 0, brokerOutTime = 0, correlationId = null, replyTo = null, persistent = false, type = null, priority = 0, groupID = null, groupSequence = 0, targetConsumerId = null, compressed = false, userID = null, content = null, marshalledProperties = null, dataStructure = null, redeliveryCounter = 0, size = 0, properties = null, readOnlyProperties = false, readOnlyBody = false, droppable = false, jmsXGroupFirstForConsumer = false} ActiveMQMapMessage{ theTable = {text=发送消息第5条, time=1506865178433} }

接收方

package com.dragon.activemq.demo;

import org.apache.activemq.ActiveMQConnection;

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.JMSException;

import javax.jms.MapMessage;

import javax.jms.Message;

import javax.jms.MessageListener;

import javax.jms.Session;

import javax.jms.Topic;

import javax.jms.TopicConnection;

import javax.jms.TopicConnectionFactory;

import javax.jms.TopicSession;

import javax.jms.TopicSubscriber;

/**

* @author Dragon

* @version V0.1

* @Title: com.dragon.activemq.demo.QueueSender

* @project ActiveMQ-5.15.0

* @Description: Topic主题发布和订阅消息 - 消息接收者,依赖hawtbuf-1.9.jar

* @date 2017/10/01 21:16

*/

public class TopicReceiver {

// tcp 地址

public static final String BROKER_URL = "tcp://localhost:61616";

// 目标,在ActiveMQ管理员控制台创建 http://localhost:8161/admin/queues.jsp

public static final String TARGET = "sagedragon.mq.queue";

public static void run() throws Exception {

TopicConnection connection = null;

TopicSession session = null;

try {

// 创建链接工厂

TopicConnectionFactory factory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER, ActiveMQConnection

.DEFAULT_PASSWORD, BROKER_URL);

// 通过工厂创建一个连接

connection = factory.createTopicConnection();

// 启动连接

connection.start();

// 创建一个session会话

session = connection.createTopicSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);

// 创建一个消息队列

Topic topic = session.createTopic(TARGET);

// 创建消息制作者

TopicSubscriber subscriber = session.createSubscriber(topic);

subscriber.setMessageListener(new MessageListener() {

public void onMessage(Message msg) {

if (msg != null) {

MapMessage map = (MapMessage) msg;

try {

System.out.println(map.getLong("time") + "接收#" + map.getString("text"));

} catch (JMSException e) {

e.printStackTrace();

}

}

}

});

// 休眠100ms再关闭

Thread.sleep(1000 * 100);

// 提交会话

session.commit();

} catch (Exception e) {

throw e;

} finally {

// 关闭释放资源

if (session != null) {

session.close();

}

if (connection != null) {

connection.close();

}

}

}

public static void main(String[] args) throws Exception {

TopicReceiver.run();

}

}

输出

1506865454228接收#发送消息第1条

21:44:36.318 [ActiveMQ InactivityMonitor WriteCheckTimer] DEBUG org.apache.activemq.transport.AbstractInactivityMonitor - WriteChecker: 10881ms elapsed since last write check.

21:44:36.373 [ActiveMQ InactivityMonitor Worker] DEBUG org.apache.activemq.transport.AbstractInactivityMonitor - Running WriteCheck[tcp://127.0.0.1:61616]

1506865454236接收#发送消息第2条

1506865454237接收#发送消息第3条

1506865454237接收#发送消息第4条

1506865454238接收#发送消息第5条

4.在spring中使用ActiveMQ

xml配置: applicationContext-beans.xml

xmlns:context="http://www.springframework.org/schema/context"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.1.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-3.1.xsd">

pom依赖

org.apache.activemq

activemq-all

5.15.0

org.apache.activemq

activemq-spring

5.15.0

发送方

package com.dragon.activemq.demo;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.FileSystemXmlApplicationContext;

import org.springframework.jms.core.JmsTemplate;

import org.springframework.jms.core.MessageCreator;

import javax.jms.JMSException;

import javax.jms.MapMessage;

import javax.jms.Message;

import javax.jms.Session;

import java.util.Date;

/**

* @author Dragon

* @version V0.1

* @Title: com.dragon.activemq.demo.SpringSender

* @Description: Spring JMSTemplate 消息发送者

* @project ActiveMQ-5.15.0

* @date 2017/10/01 21:47

*/

public class SpringSender {

public static void main(String[] args) {

ApplicationContext ctx = new FileSystemXmlApplicationContext("classpath:applicationContext-*.xml");

JmsTemplate jmsTemplate = (JmsTemplate) ctx.getBean("jmsTemplate");

jmsTemplate.send(new MessageCreator() {

public Message createMessage(Session session) throws JMSException {

MapMessage message = session.createMapMessage();

message.setString("message", "current system time: " + new Date().getTime());

return message;

}

});

}

}

输出

21:59:36.021 [main] DEBUG org.springframework.jms.core.JmsTemplate - Sending created message: ActiveMQMapMessage {commandId = 0, responseRequired = false, messageId = null, originalDestination = null, originalTransactionId = null, producerId = null, destination = null, transactionId = null, expiration = 0, timestamp = 0, arrival = 0, brokerInTime = 0, brokerOutTime = 0, correlationId = null, replyTo = null, persistent = false, type = null, priority = 0, groupID = null, groupSequence = 0, targetConsumerId = null, compressed = false, userID = null, content = null, marshalledProperties = null, dataStructure = null, redeliveryCounter = 0, size = 0, properties = null, readOnlyProperties = false, readOnlyBody = false, droppable = false, jmsXGroupFirstForConsumer = false} ActiveMQMapMessage{ theTable = {message=current system time: 1506866376016} }

接收方

package com.dragon.activemq.demo;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.FileSystemXmlApplicationContext;

import org.springframework.jms.core.JmsTemplate;

import java.util.Map;

/**

* @author Dragon

* @version V0.1

* @Title: com.dragon.activemq.demo.SpringSender

* @Description: Spring JMSTemplate 消息接收者

* @project ActiveMQ-5.15.0

* @date 2017/10/01 21:47

*/

public class SpringReceiver {

@SuppressWarnings("unchecked")

public static void main(String[] args) {

ApplicationContext ctx = new FileSystemXmlApplicationContext("classpath:applicationContext-*.xml");

JmsTemplate jmsTemplate = (JmsTemplate) ctx.getBean("jmsTemplate");

while (true) {

Map map = (Map) jmsTemplate.receiveAndConvert();

System.out.println("收到消息:" + map.get("message"));

}

}

}

输出

收到消息:current system time: 1506866100187

5.在springboot中使用ActiveMQ

pom.xml

org.springframework.boot

spring-boot-starter-web

org.springframework.boot

spring-boot-starter-activemq

application.yml

spring:

application:

name: activemq-demo

server:

port: 9090

发送方

/**

* @author Dragon

* @version V0.1

* @Title: com.dragon.activemq.demo.springboot.demo.MessageProduction

* @Description: 消息生产者

* @date 2017/10/01 23:14

*/

//注册为一个bean

@Component

//开启定时器

@EnableScheduling

public class MessageProduction {

@Autowired

private JmsMessagingTemplate jmsMessagingTemplate;//使用JmsMessagingTemplate将消息放入队列

@Autowired

private Queue queue;

@Scheduled(fixedDelay = 3000)//每3s执行1次,将消息放入队列内

public void send() {

this.jmsMessagingTemplate.convertAndSend(this.queue,

"测试消息队列" + System.currentTimeMillis() / 1000);

}

}

输出

消息队列

/**

* @author Dragon

* @version V0.1

* @Title: com.dragon.activemq.demo.springboot.demo.MessageQueue

* @Description: 队列消息发送者

* @date 2017/10/01 23:16

*/

@Component

public class MessageQueue {

//返回一个名为my-message的队列,并且注册为bean

@Bean

public Queue queue() {

return new ActiveMQQueue("my-message");

}

}

接收方

package com.dragon.activemq.demo.springboot.demo;

import com.dragon.activemq.demo.springboot.Constants;

import org.springframework.jms.annotation.JmsListener;

import org.springframework.stereotype.Component;

import javax.jms.JMSException;

import java.text.MessageFormat;

import java.util.Date;

/**

* @author Dragon

* @version V0.1

* @Title: com.dragon.activemq.demo.springboot.demo.MessageListener

* @Description: 消息监听者

* @date 2017/10/01 23:16

*/

@Component

public class MessageListener {

/**

* 使用@JmsListener注解来监听指定的某个队列内的消息,是否有新增,有的话则取出队列内消息

* 进行处理

**/

@JmsListener(destination = "my-message")

public void removeMessage(String msg) {

//public void removeMessage(Email email) {

System.out.println("监听接收到的消息是:" + msg);//打印队列内的消息

}

/*@JmsListener(destination = "mailbox", containerFactory = "myFactory")

public void receiveMessage(Email email) {

System.out.println("Received ");

}*/

}

启动ActiveMQApplication后的输出

监听接收到的消息是:测试消息队列1506875404

监听接收到的消息是:测试消息队列1506875407

监听接收到的消息是:测试消息队列1506875410

监听接收到的消息是:测试消息队列1506875413

ActiveMQApplication.java

package com.dragon.activemq.demo;

import com.dragon.activemq.demo.springboot.demo.Email;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.boot.autoconfigure.jms.DefaultJmsListenerContainerFactoryConfigurer;

import org.springframework.context.ConfigurableApplicationContext;

import org.springframework.context.annotation.Bean;

import org.springframework.jms.annotation.EnableJms;

import org.springframework.jms.config.DefaultJmsListenerContainerFactory;

import org.springframework.jms.config.JmsListenerContainerFactory;

import org.springframework.jms.core.JmsTemplate;

import org.springframework.jms.support.converter.MappingJackson2MessageConverter;

import org.springframework.jms.support.converter.MessageConverter;

import org.springframework.jms.support.converter.MessageType;

import javax.jms.ConnectionFactory;

/**

* @author Dragon

* @version V0.1

* @Title: com.dragon.activemq.demo.ActiveMQApplication

* @Description: ActiveMQ 启动类

* @date 2017/10/01 22:20

*/

@SpringBootApplication(scanBasePackages = {"com.dragon"})扫描com.dragon包的注解类为bean

@EnableJms//开启jms

public class ActiveMQApplication {

/**

* 将springboot里面的消息加到jms监听工厂

* @param connectionFactory

* @param configurer

* @return

*/

@Bean

public JmsListenerContainerFactory> myFactory(ConnectionFactory connectionFactory,

DefaultJmsListenerContainerFactoryConfigurer configurer) {

DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();

// This provides all boot's default to this factory, including the message converter

configurer.configure(factory, connectionFactory);

// You could still override some of Boot's default if necessary.

return factory;

}

/**

* 转换消息格式, 没有这个会爆类型转换错误:

* Caused by: org.springframework.messaging.converter.MessageConversionException:

* Cannot convert from [org.apache.activemq.command .ActiveMQTextMessage]

* to

* [com.dragon.activemq.demo.springboot.demo.Email] / [java.lang.String]

* for org.springframework.jms.listener.adapter.AbstractAdaptableMessageListener$MessagingMessageConverterAdapter$LazyResolutionMessage@3189b1ff

* @return

*/

@Bean // Serialize message content to json using TextMessage

public MessageConverter jacksonJmsMessageConverter() {

MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();

converter.setTargetType(MessageType.TEXT);

converter.setTypeIdPropertyName("_type");

return converter;

}

public static void main(String[] args) {

// Launch the application

ConfigurableApplicationContext context = SpringApplication.run(ActiveMQApplication.class, args);

//JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);

// Send a message with a POJO - the template reuse the message converter

//System.out.println("Sending an email message.");

//jmsTemplate.convertAndSend("mailbox", new Email("info@example.com", "Hello"));

}

}

4.遇到的坑

4.1消息类型转换错误

Caused by: org.springframework.messaging.converter.MessageConversionException: Cannot convert from [org.apache.activemq.command.ActiveMQTextMessage] to [com.dragon.activemq.demo.springboot.demo.Email] for org.springframework.jms.listener.adapter.AbstractAdaptableMessageListener$MessagingMessageConverterAdapter$LazyResolutionMessage@3189b1ff

解决方法:

在application类里加个bean

@Bean // Serialize message content to json using TextMessage

public MessageConverter jacksonJmsMessageConverter() {

MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();

converter.setTargetType(MessageType.TEXT);

converter.setTypeIdPropertyName("_type");

return converter;

}

4.2发送消息之后消费不了

解决方法:

将springboot里的消息加到jms工厂

@Bean

public JmsListenerContainerFactory> myFactory(ConnectionFactory connectionFactory,

DefaultJmsListenerContainerFactoryConfigurer configurer) {

DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();

// This provides all boot's default to this factory, including the message converter

configurer.configure(factory, connectionFactory);

// You could still override some of Boot's default if necessary.

return factory;

}

4.3实体类序列化后报错

Caused by: org.springframework.jms.support.converter.MessageConversionException: Could not convert JMS message; nested exception is javax.jms.JMSException: Failed to build body from content. Serializable class not available to broker. Reason: java.lang.ClassNotFoundException: Forbidden class com.dragon.activemq.demo.springboot.demo.Email! This class is not trusted to be serialized as ObjectMessage payload. Please take a look at http://activemq.apache.org/objectmessage.html for more information on how to configure trusted classes.

解决方法:

设置可以序列化的包列表, 加到vm启动参数里面!

#全部包

#org.apache.activemq.SERIALIZABLE_PACKAGES=*

org.apache.activemq.SERIALIZABLE_PACKAGES=com.dragon.activemq,com.dragon.demo

006eMRnQgy1fk3872anyjj31220m1gpz.jpg

加到vm启动参数里面

5.参考资料

最后感谢观看本教程!

@ 作者:龙圣贤

@ 写作日期:2017年10月02日 01:05:14

@ 转载请简信联系,并且带上文章出处。

此致,今日分享完毕。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值